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-2026 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#define CONSHDLR_NAME "linear"
96#define CONSHDLR_DESC "linear constraints of the form lhs <= a^T x <= rhs"
97#define CONSHDLR_SEPAPRIORITY +100000 /**< priority of the constraint handler for separation */
98#define CONSHDLR_ENFOPRIORITY -1000000 /**< priority of the constraint handler for constraint enforcing */
99#define CONSHDLR_CHECKPRIORITY -1000000 /**< priority of the constraint handler for checking feasibility */
100#define CONSHDLR_SEPAFREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
101#define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
102#define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
103 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
104#define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
105#define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
106#define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
107#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
108
109#define CONSHDLR_PRESOLTIMING (SCIP_PRESOLTIMING_FAST | SCIP_PRESOLTIMING_EXHAUSTIVE) /**< presolving timing of the constraint handler (fast, medium, or exhaustive) */
110#define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
111
112#define EVENTHDLR_NAME "linear"
113#define EVENTHDLR_DESC "bound change event handler for linear constraints"
114
115#define CONFLICTHDLR_NAME "linear"
116#define CONFLICTHDLR_DESC "conflict handler creating linear constraints"
117#define CONFLICTHDLR_PRIORITY -1000000
118
119#define DEFAULT_TIGHTENBOUNDSFREQ 1 /**< multiplier on propagation frequency, how often the bounds are tightened */
120#define DEFAULT_MAXROUNDS 5 /**< maximal number of separation rounds per node (-1: unlimited) */
121#define DEFAULT_MAXROUNDSROOT -1 /**< maximal number of separation rounds in the root node (-1: unlimited) */
122#define DEFAULT_MAXSEPACUTS 50 /**< maximal number of cuts separated per separation round */
123#define DEFAULT_MAXSEPACUTSROOT 200 /**< maximal number of cuts separated per separation round in root node */
124#define DEFAULT_PRESOLPAIRWISE TRUE /**< should pairwise constraint comparison be performed in presolving? */
125#define DEFAULT_PRESOLUSEHASHING TRUE /**< should hash table be used for detecting redundant constraints in advance */
126#define DEFAULT_NMINCOMPARISONS 200000 /**< number for minimal pairwise presolving comparisons */
127#define DEFAULT_MINGAINPERNMINCOMP 1e-06 /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise
128 * comparison round */
129#define DEFAULT_SORTVARS TRUE /**< should variables be sorted after presolve w.r.t their coefficient absolute for faster
130 * propagation? */
131#define DEFAULT_CHECKRELMAXABS FALSE /**< should the violation for a constraint with side 0.0 be checked relative
132 * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
133#define DEFAULT_MAXAGGRNORMSCALE 0.0 /**< maximal allowed relative gain in maximum norm for constraint aggregation
134 * (0.0: disable constraint aggregation) */
135#define DEFAULT_MAXEASYACTIVITYDELTA 1e6 /**< maximum activity delta to run easy propagation on linear constraint
136 * (faster, but numerically less stable) */
137#define DEFAULT_MAXCARDBOUNDDIST 0.0 /**< maximal relative distance from current node's dual bound to primal bound compared
138 * to best node's dual bound for separating knapsack cardinality cuts */
139#define DEFAULT_SEPARATEALL FALSE /**< should all constraints be subject to cardinality cut generation instead of only
140 * the ones with non-zero dual value? */
141#define DEFAULT_AGGREGATEVARIABLES TRUE /**< should presolving search for redundant variables in equations */
142#define DEFAULT_SIMPLIFYINEQUALITIES TRUE /**< should presolving try to simplify inequalities */
143#define DEFAULT_DUALPRESOLVING TRUE /**< should dual presolving steps be performed? */
144#define DEFAULT_SINGLETONSTUFFING TRUE /**< should stuffing of singleton continuous variables be performed? */
145#define DEFAULT_SINGLEVARSTUFFING FALSE /**< should single variable stuffing be performed, which tries to fulfill
146 * constraints using the cheapest variable? */
147#define DEFAULT_DETECTCUTOFFBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
148 * function defining an upper bound and prevent these constraints from
149 * entering the LP */
150#define DEFAULT_DETECTLOWERBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
151 * function defining a lower bound and prevent these constraints from
152 * entering the LP */
153#define DEFAULT_DETECTPARTIALOBJECTIVE TRUE/**< should presolving try to detect subsets of constraints parallel to the
154 * objective function */
155#define DEFAULT_RANGEDROWPROPAGATION TRUE /**< should we perform ranged row propagation */
156#define DEFAULT_RANGEDROWARTCONS TRUE /**< should presolving and propagation extract sub-constraints from ranged rows and equations? */
157#define DEFAULT_RANGEDROWMAXDEPTH INT_MAX /**< maximum depth to apply ranged row propagation */
158#define DEFAULT_RANGEDROWFREQ 1 /**< frequency for applying ranged row propagation */
159
160#define DEFAULT_MULTAGGRREMOVE FALSE /**< should multi-aggregations only be performed if the constraint can be
161 * removed afterwards? */
162#define DEFAULT_MAXMULTAGGRQUOT 1e+03 /**< maximum coefficient dynamism (ie. maxabsval / minabsval) for multiaggregation */
163#define DEFAULT_MAXDUALMULTAGGRQUOT 1e+20 /**< maximum coefficient dynamism (ie. maxabsval / minabsval) for multiaggregation */
164#define DEFAULT_EXTRACTCLIQUES TRUE /**< should cliques be extracted? */
165
166#define MAXDNOM 10000LL /**< maximal denominator for simple rational fixed values */
167#define MAXSCALEDCOEF 0 /**< maximal coefficient value after scaling */
168#define MAXSCALEDCOEFINTEGER 0 /**< maximal coefficient value after scaling if all variables are of integral
169 * type
170 */
171#define MAXACTVAL 1e+09 /**< maximal absolute value of full and partial activities such that
172 * redundancy-based simplifications are allowed to be applied
173 */
174
175#define MAXVALRECOMP 1e+06 /**< maximal abolsute value we trust without recomputing the activity */
176#define MINVALRECOMP 1e-05 /**< minimal abolsute value we trust without recomputing the activity */
177
178
179#define NONLINCONSUPGD_PRIORITY 1000000 /**< priority of the constraint handler for upgrading of expressions constraints */
180
181/* @todo add multi-aggregation of variables that are in exactly two equations (, if not numerically an issue),
182 * maybe in fullDualPresolve(), see convertLongEquality()
183 */
184
185
186/** constraint data for linear constraints */
187struct SCIP_ConsData
188{
189 SCIP_Real lhs; /**< left hand side of row (for ranged rows) */
190 SCIP_Real rhs; /**< right hand side of row */
191 SCIP_Real maxabsval; /**< maximum absolute value of all coefficients */
192 SCIP_Real minabsval; /**< minimal absolute value of all coefficients */
193 QUAD_MEMBER(SCIP_Real minactivity); /**< minimal value w.r.t. the variable's local bounds for the constraint's
194 * activity, ignoring the coefficients contributing with infinite value */
195 QUAD_MEMBER(SCIP_Real maxactivity); /**< maximal value w.r.t. the variable's local bounds for the constraint's
196 * activity, ignoring the coefficients contributing with infinite value */
197 SCIP_Real lastminactivity; /**< last minimal activity which was computed by complete summation
198 * over all contributing values */
199 SCIP_Real lastmaxactivity; /**< last maximal activity which was computed by complete summation
200 * over all contributing values */
201 QUAD_MEMBER(SCIP_Real glbminactivity); /**< minimal value w.r.t. the variable's global bounds for the constraint's
202 * activity, ignoring the coefficients contributing with infinite value */
203 QUAD_MEMBER(SCIP_Real glbmaxactivity); /**< maximal value w.r.t. the variable's global bounds for the constraint's
204 * activity, ignoring the coefficients contributing with infinite value */
205 SCIP_Real lastglbminactivity; /**< last global minimal activity which was computed by complete summation
206 * over all contributing values */
207 SCIP_Real lastglbmaxactivity; /**< last global maximal activity which was computed by complete summation
208 * over all contributing values */
209 SCIP_Real maxactdelta; /**< maximal activity contribution of a single variable, or SCIP_INVALID if invalid */
210 SCIP_VAR* maxactdeltavar; /**< variable with maximal activity contribution, or NULL if invalid */
211 uint64_t possignature; /**< bit signature of coefficients that may take a positive value */
212 uint64_t negsignature; /**< bit signature of coefficients that may take a negative value */
213 SCIP_ROW* row; /**< LP row, if constraint is already stored in LP row format */
214 SCIP_NLROW* nlrow; /**< NLP row, if constraint has been added to NLP relaxation */
215 SCIP_VAR** vars; /**< variables of constraint entries */
216 SCIP_Real* vals; /**< coefficients of constraint entries */
217 SCIP_EVENTDATA** eventdata; /**< event data for bound change events of the variables */
218 int minactivityneginf; /**< number of coefficients contributing with neg. infinite value to minactivity */
219 int minactivityposinf; /**< number of coefficients contributing with pos. infinite value to minactivity */
220 int maxactivityneginf; /**< number of coefficients contributing with neg. infinite value to maxactivity */
221 int maxactivityposinf; /**< number of coefficients contributing with pos. infinite value to maxactivity */
222 int minactivityneghuge; /**< number of coefficients contributing with huge neg. value to minactivity */
223 int minactivityposhuge; /**< number of coefficients contributing with huge pos. value to minactivity */
224 int maxactivityneghuge; /**< number of coefficients contributing with huge neg. value to maxactivity */
225 int maxactivityposhuge; /**< number of coefficients contributing with huge pos. value to maxactivity */
226 int glbminactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbminactivity */
227 int glbminactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbminactivity */
228 int glbmaxactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbmaxactivity */
229 int glbmaxactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbmaxactivity */
230 int glbminactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbminactivity */
231 int glbminactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbminactivity */
232 int glbmaxactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbmaxactivity */
233 int glbmaxactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbmaxactivity */
234 int varssize; /**< size of the vars- and vals-arrays */
235 int nvars; /**< number of nonzeros in constraint */
236 int nbinvars; /**< the number of binary variables in the constraint, only valid after
237 * sorting in stage >= SCIP_STAGE_INITSOLVE
238 */
239 unsigned int boundstightened:2; /**< is constraint already propagated with bound tightening? */
240 unsigned int rangedrowpropagated:2; /**< did we perform ranged row propagation on this constraint?
241 * (0: no, 1: yes, 2: with potentially adding artificial constraint */
242 unsigned int validmaxabsval:1; /**< is the maximum absolute value valid? */
243 unsigned int validminabsval:1; /**< is the minimum absolute value valid? */
244 unsigned int validactivities:1; /**< are the activity bounds (local and global) valid? */
245 unsigned int validminact:1; /**< is the local minactivity valid? */
246 unsigned int validmaxact:1; /**< is the local maxactivity valid? */
247 unsigned int validglbminact:1; /**< is the global minactivity valid? */
248 unsigned int validglbmaxact:1; /**< is the global maxactivity valid? */
249 unsigned int presolved:1; /**< is constraint already presolved? */
250 unsigned int removedfixings:1; /**< are all fixed variables removed from the constraint? */
251 unsigned int validsignature:1; /**< is the bit signature valid? */
252 unsigned int changed:1; /**< was constraint changed since last aggregation round in preprocessing? */
253 unsigned int normalized:1; /**< is the constraint in normalized form? */
254 unsigned int upgradetried:1; /**< was the constraint already tried to be upgraded? */
255 unsigned int upgraded:1; /**< is the constraint upgraded and will it be removed after preprocessing? */
256 unsigned int indexsorted:1; /**< are the constraint's variables sorted by type and index? */
257 unsigned int merged:1; /**< are the constraint's equal variables already merged? */
258 unsigned int cliquesadded:1; /**< were the cliques of the constraint already extracted? */
259 unsigned int implsadded:1; /**< were the implications of the constraint already extracted? */
260 unsigned int coefsorted:1; /**< are variables sorted by type and their absolute activity delta? */
261 unsigned int varsdeleted:1; /**< were variables deleted after last cleanup? */
262 unsigned int hascontvar:1; /**< does the constraint contain at least one continuous variable? */
263 unsigned int hasnonbinvar:1; /**< does the constraint contain at least one non-binary variable? */
264 unsigned int hasnonbinvalid:1; /**< is the information stored in hasnonbinvar and hascontvar valid? */
265 unsigned int checkabsolute:1; /**< should the constraint be checked w.r.t. an absolute feasibilty tolerance? */
266};
267
268/** event data for bound change event */
269struct SCIP_EventData
270{
271 SCIP_CONS* cons; /**< linear constraint to process the bound change for */
272 int varpos; /**< position of variable in vars array */
273 int filterpos; /**< position of event in variable's event filter */
274};
275
276/** constraint handler data */
277struct SCIP_ConshdlrData
278{
279 SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events */
280 SCIP_LINCONSUPGRADE** linconsupgrades; /**< linear constraint upgrade methods for specializing linear constraints */
281 SCIP_Real maxaggrnormscale; /**< maximal allowed relative gain in maximum norm for constraint aggregation
282 * (0.0: disable constraint aggregation) */
283 SCIP_Real maxcardbounddist; /**< maximal relative distance from current node's dual bound to primal bound compared
284 * to best node's dual bound for separating knapsack cardinality cuts */
285 SCIP_Real mingainpernmincomp; /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise comparison round */
286 SCIP_Real maxeasyactivitydelta;/**< maximum activity delta to run easy propagation on linear constraint
287 * (faster, but numerically less stable) */
288 int linconsupgradessize;/**< size of linconsupgrade array */
289 int nlinconsupgrades; /**< number of linear constraint upgrade methods */
290 int tightenboundsfreq; /**< multiplier on propagation frequency, how often the bounds are tightened */
291 int maxrounds; /**< maximal number of separation rounds per node (-1: unlimited) */
292 int maxroundsroot; /**< maximal number of separation rounds in the root node (-1: unlimited) */
293 int maxsepacuts; /**< maximal number of cuts separated per separation round */
294 int maxsepacutsroot; /**< maximal number of cuts separated per separation round in root node */
295 int nmincomparisons; /**< number for minimal pairwise presolving comparisons */
296 int naddconss; /**< number of added constraints */
297 SCIP_Bool presolpairwise; /**< should pairwise constraint comparison be performed in presolving? */
298 SCIP_Bool presolusehashing; /**< should hash table be used for detecting redundant constraints in advance */
299 SCIP_Bool separateall; /**< should all constraints be subject to cardinality cut generation instead of only
300 * the ones with non-zero dual value? */
301 SCIP_Bool aggregatevariables; /**< should presolving search for redundant variables in equations */
302 SCIP_Bool simplifyinequalities;/**< should presolving try to cancel down or delete coefficients in inequalities */
303 SCIP_Bool dualpresolving; /**< should dual presolving steps be performed? */
304 SCIP_Bool singletonstuffing; /**< should stuffing of singleton continuous variables be performed? */
305 SCIP_Bool singlevarstuffing; /**< should single variable stuffing be performed, which tries to fulfill
306 * constraints using the cheapest variable? */
307 SCIP_Bool sortvars; /**< should binary variables be sorted for faster propagation? */
308 SCIP_Bool checkrelmaxabs; /**< should the violation for a constraint with side 0.0 be checked relative
309 * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
310 SCIP_Bool detectcutoffbound; /**< should presolving try to detect constraints parallel to the objective
311 * function defining an upper bound and prevent these constraints from
312 * entering the LP */
313 SCIP_Bool detectlowerbound; /**< should presolving try to detect constraints parallel to the objective
314 * function defining a lower bound and prevent these constraints from
315 * entering the LP */
316 SCIP_Bool detectpartialobjective;/**< should presolving try to detect subsets of constraints parallel to
317 * the objective function */
318 SCIP_Bool rangedrowpropagation;/**< should presolving and propagation try to improve bounds, detect
319 * infeasibility, and extract sub-constraints from ranged rows and
320 * equations */
321 SCIP_Bool rangedrowartcons; /**< should presolving and propagation extract sub-constraints from ranged rows and equations?*/
322 int rangedrowmaxdepth; /**< maximum depth to apply ranged row propagation */
323 int rangedrowfreq; /**< frequency for applying ranged row propagation */
324 SCIP_Bool multaggrremove; /**< should multi-aggregations only be performed if the constraint can be
325 * removed afterwards? */
326 SCIP_Real maxmultaggrquot; /**< maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation */
327 SCIP_Real maxdualmultaggrquot;/**< maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation */
328 SCIP_Bool extractcliques; /**< should cliques be extracted? */
329};
330
331/** linear constraint update method */
333{
334 SCIP_DECL_LINCONSUPGD((*linconsupgd)); /**< method to call for upgrading linear constraint */
335 int priority; /**< priority of upgrading method */
336 SCIP_Bool active; /**< is upgrading enabled */
337};
338
339
340/*
341 * Propagation rules
342 */
343
345{
346 PROPRULE_1_RHS = 1, /**< activity residuals of all other variables tighten bounds of single
347 * variable due to the right hand side of the inequality */
348 PROPRULE_1_LHS = 2, /**< activity residuals of all other variables tighten bounds of single
349 * variable due to the left hand side of the inequality */
350 PROPRULE_1_RANGEDROW = 3, /**< fixed variables and gcd of all left variables tighten bounds of a
351 * single variable in this reanged row */
352 PROPRULE_INVALID = 0 /**< propagation was applied without a specific propagation rule */
353};
354typedef enum Proprule PROPRULE;
355
356/** inference information */
357struct InferInfo
358{
359 union
360 {
361 struct
362 {
363 unsigned int proprule:8; /**< propagation rule that was applied */
364 unsigned int pos:24; /**< variable position, the propagation rule was applied at */
365 } asbits;
366 int asint; /**< inference information as a single int value */
367 } val;
368};
369typedef struct InferInfo INFERINFO;
370
371/** converts an integer into an inference information */
372static
374 int i /**< integer to convert */
375 )
376{
377 INFERINFO inferinfo;
378
379 inferinfo.val.asint = i;
380
381 return inferinfo;
382}
383
384/** converts an inference information into an int */
385static
387 INFERINFO inferinfo /**< inference information to convert */
388 )
389{
390 return inferinfo.val.asint;
391}
392
393/** returns the propagation rule stored in the inference information */
394static
396 INFERINFO inferinfo /**< inference information to convert */
397 )
398{
399 return (int) inferinfo.val.asbits.proprule;
400}
401
402/** returns the position stored in the inference information */
403static
405 INFERINFO inferinfo /**< inference information to convert */
406 )
407{
408 return (int) inferinfo.val.asbits.pos;
409}
410
411/** constructs an inference information out of a propagation rule and a position number */
412static
414 PROPRULE proprule, /**< propagation rule that deduced the value */
415 int pos /**< variable position, the propagation rule was applied at */
416 )
417{
418 INFERINFO inferinfo;
419
420 assert(pos >= 0);
421 /* in the inferinfo struct only 24 bits for 'pos' are reserved */
422 assert(pos < (1<<24));
423
424 inferinfo.val.asbits.proprule = (unsigned int) proprule; /*lint !e641*/
425 inferinfo.val.asbits.pos = (unsigned int) pos; /*lint !e732*/
426
427 return inferinfo;
428}
429
430/** constructs an inference information out of a propagation rule and a position number, returns info as int */
431static
433 PROPRULE proprule, /**< propagation rule that deduced the value */
434 int pos /**< variable position, the propagation rule was applied at */
435 )
436{
437 return inferInfoToInt(getInferInfo(proprule, pos));
438}
439
440
441/*
442 * memory growing methods for dynamically allocated arrays
443 */
444
445/** ensures, that linconsupgrades array can store at least num entries */
446static
448 SCIP* scip, /**< SCIP data structure */
449 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
450 int num /**< minimum number of entries to store */
451 )
452{
453 assert(scip != NULL);
454 assert(conshdlrdata != NULL);
455 assert(conshdlrdata->nlinconsupgrades <= conshdlrdata->linconsupgradessize);
456
457 if( num > conshdlrdata->linconsupgradessize )
458 {
459 int newsize;
460
461 newsize = SCIPcalcMemGrowSize(scip, num);
462 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &conshdlrdata->linconsupgrades, conshdlrdata->linconsupgradessize, newsize) );
463 conshdlrdata->linconsupgradessize = newsize;
464 }
465 assert(num <= conshdlrdata->linconsupgradessize);
466
467 return SCIP_OKAY;
468}
469
470/** ensures, that vars and vals arrays can store at least num entries */
471static
473 SCIP* scip, /**< SCIP data structure */
474 SCIP_CONSDATA* consdata, /**< linear constraint data */
475 int num /**< minimum number of entries to store */
476 )
477{
478 assert(scip != NULL);
479 assert(consdata != NULL);
480 assert(consdata->nvars <= consdata->varssize);
481
482 if( num > consdata->varssize )
483 {
484 int newsize;
485
486 newsize = SCIPcalcMemGrowSize(scip, num);
487 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
488 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vals, consdata->varssize, newsize) );
489 if( consdata->eventdata != NULL )
490 {
491 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize, newsize) );
492 }
493 consdata->varssize = newsize;
494 }
495 assert(num <= consdata->varssize);
496
497 return SCIP_OKAY;
498}
499
500
501/*
502 * local methods for managing linear constraint update methods
503 */
504
505/** creates a linear constraint upgrade data object */
506static
508 SCIP* scip, /**< SCIP data structure */
509 SCIP_LINCONSUPGRADE** linconsupgrade, /**< pointer to store the linear constraint upgrade */
510 SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
511 int priority /**< priority of upgrading method */
512 )
513{
514 assert(scip != NULL);
515 assert(linconsupgrade != NULL);
516 assert(linconsupgd != NULL);
517
518 SCIP_CALL( SCIPallocBlockMemory(scip, linconsupgrade) );
519 (*linconsupgrade)->linconsupgd = linconsupgd;
520 (*linconsupgrade)->priority = priority;
521 (*linconsupgrade)->active = TRUE;
522
523 return SCIP_OKAY;
524}
525
526/** frees a linear constraint upgrade data object */
527static
529 SCIP* scip, /**< SCIP data structure */
530 SCIP_LINCONSUPGRADE** linconsupgrade /**< pointer to the linear constraint upgrade */
531 )
532{
533 assert(scip != NULL);
534 assert(linconsupgrade != NULL);
535 assert(*linconsupgrade != NULL);
536
537 SCIPfreeBlockMemory(scip, linconsupgrade);
538}
539
540/** creates constraint handler data for linear constraint handler */
541static
543 SCIP* scip, /**< SCIP data structure */
544 SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
545 SCIP_EVENTHDLR* eventhdlr /**< event handler */
546 )
547{
548 assert(scip != NULL);
549 assert(conshdlrdata != NULL);
550 assert(eventhdlr != NULL);
551
552 SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
553 (*conshdlrdata)->linconsupgrades = NULL;
554 (*conshdlrdata)->linconsupgradessize = 0;
555 (*conshdlrdata)->nlinconsupgrades = 0;
556 (*conshdlrdata)->naddconss = 0;
557
558 /* set event handler for updating linear constraint activity bounds */
559 (*conshdlrdata)->eventhdlr = eventhdlr;
560
561 return SCIP_OKAY;
562}
563
564/** frees constraint handler data for linear constraint handler */
565static
567 SCIP* scip, /**< SCIP data structure */
568 SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
569 )
570{
571 int i;
572
573 assert(scip != NULL);
574 assert(conshdlrdata != NULL);
575 assert(*conshdlrdata != NULL);
576
577 for( i = 0; i < (*conshdlrdata)->nlinconsupgrades; ++i )
578 {
579 linconsupgradeFree(scip, &(*conshdlrdata)->linconsupgrades[i]);
580 }
581 SCIPfreeBlockMemoryArrayNull(scip, &(*conshdlrdata)->linconsupgrades, (*conshdlrdata)->linconsupgradessize);
582
583 SCIPfreeBlockMemory(scip, conshdlrdata);
584}
585
586/** creates a linear constraint upgrade data object */
587static
589 SCIP* scip, /**< SCIP data structure */
590 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
591 SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
592 const char* conshdlrname /**< name of the constraint handler */
593 )
594{
595 int i;
596
597 assert(scip != NULL);
598 assert(conshdlrdata != NULL);
599 assert(linconsupgd != NULL);
600 assert(conshdlrname != NULL);
601
602 for( i = conshdlrdata->nlinconsupgrades - 1; i >= 0; --i )
603 {
604 if( conshdlrdata->linconsupgrades[i]->linconsupgd == linconsupgd )
605 {
606#ifdef SCIP_DEBUG
607 SCIPwarningMessage(scip, "Try to add already known upgrade message for constraint handler %s.\n", conshdlrname);
608#endif
609 return TRUE;
610 }
611 }
612
613 return FALSE;
614}
615
616/** adds a linear constraint update method to the constraint handler's data */
617static
619 SCIP* scip, /**< SCIP data structure */
620 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
621 SCIP_LINCONSUPGRADE* linconsupgrade /**< linear constraint upgrade method */
622 )
623{
624 int i;
625
626 assert(scip != NULL);
627 assert(conshdlrdata != NULL);
628 assert(linconsupgrade != NULL);
629
630 SCIP_CALL( conshdlrdataEnsureLinconsupgradesSize(scip, conshdlrdata, conshdlrdata->nlinconsupgrades+1) );
631
632 for( i = conshdlrdata->nlinconsupgrades;
633 i > 0 && conshdlrdata->linconsupgrades[i-1]->priority < linconsupgrade->priority; --i )
634 {
635 conshdlrdata->linconsupgrades[i] = conshdlrdata->linconsupgrades[i-1];
636 }
637 assert(0 <= i && i <= conshdlrdata->nlinconsupgrades);
638 conshdlrdata->linconsupgrades[i] = linconsupgrade;
639 conshdlrdata->nlinconsupgrades++;
640
641 return SCIP_OKAY;
642}
643
644/*
645 * local methods
646 */
647
648/** installs rounding locks for the given variable associated to the given coefficient in the linear constraint */
649static
651 SCIP* scip, /**< SCIP data structure */
652 SCIP_CONS* cons, /**< linear constraint */
653 SCIP_VAR* var, /**< variable of constraint entry */
654 SCIP_Real val /**< coefficient of constraint entry */
655 )
656{
657 SCIP_CONSDATA* consdata;
658
659 assert(scip != NULL);
660 assert(cons != NULL);
661 assert(var != NULL);
662
663 consdata = SCIPconsGetData(cons);
664 assert(consdata != NULL);
665 assert(!SCIPisZero(scip, val));
666
667 if( val < 0.0 )
668 {
670 !SCIPisInfinity(scip, consdata->rhs), !SCIPisInfinity(scip, -consdata->lhs)) );
671 }
672 else
673 {
675 !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
676 }
677
678 return SCIP_OKAY;
679}
680
681/** removes rounding locks for the given variable associated to the given coefficient in the linear constraint */
682static
684 SCIP* scip, /**< SCIP data structure */
685 SCIP_CONS* cons, /**< linear constraint */
686 SCIP_VAR* var, /**< variable of constraint entry */
687 SCIP_Real val /**< coefficient of constraint entry */
688 )
689{
690 SCIP_CONSDATA* consdata;
691
692 assert(scip != NULL);
693 assert(cons != NULL);
694 assert(var != NULL);
695
696 consdata = SCIPconsGetData(cons);
697 assert(consdata != NULL);
698 assert(!SCIPisZero(scip, val));
699
700 if( val < 0.0 )
701 {
703 !SCIPisInfinity(scip, consdata->rhs), !SCIPisInfinity(scip, -consdata->lhs)) );
704 }
705 else
706 {
708 !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
709 }
710
711 return SCIP_OKAY;
712}
713
714/** creates event data for variable at given position, and catches events */
715/**! [SnippetDebugAssertions] */
716static
718 SCIP* scip, /**< SCIP data structure */
719 SCIP_CONS* cons, /**< linear constraint */
720 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
721 int pos /**< array position of variable to catch bound change events for */
722 )
723{
724 SCIP_CONSDATA* consdata;
725 assert(scip != NULL);
726 assert(cons != NULL);
727 assert(eventhdlr != NULL);
728
729 consdata = SCIPconsGetData(cons);
730 assert(consdata != NULL);
731
732 assert(0 <= pos && pos < consdata->nvars);
733 assert(consdata->vars != NULL);
734 assert(consdata->vars[pos] != NULL);
735 assert(SCIPvarIsTransformed(consdata->vars[pos]));
736 assert(consdata->eventdata != NULL);
737 assert(consdata->eventdata[pos] == NULL);
738
739 SCIP_CALL( SCIPallocBlockMemory(scip, &(consdata->eventdata[pos])) ); /*lint !e866*/
740 consdata->eventdata[pos]->cons = cons;
741 consdata->eventdata[pos]->varpos = pos;
742
743 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],
783 eventhdlr, consdata->eventdata[pos], consdata->eventdata[pos]->filterpos) );
784
785 SCIPfreeBlockMemory(scip, &consdata->eventdata[pos]); /*lint !e866*/
786
787 return SCIP_OKAY;
788}
789
790/** catches bound change events for all variables in transformed linear constraint */
791static
793 SCIP* scip, /**< SCIP data structure */
794 SCIP_CONS* cons, /**< linear constraint */
795 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
796 )
797{
798 SCIP_CONSDATA* consdata;
799 int i;
800
801 assert(scip != NULL);
802 assert(cons != NULL);
803
804 consdata = SCIPconsGetData(cons);
805 assert(consdata != NULL);
806 assert(consdata->eventdata == NULL);
807
808 /* allocate eventdata array */
809 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize) );
810 assert(consdata->eventdata != NULL);
811 BMSclearMemoryArray(consdata->eventdata, consdata->nvars);
812
813 /* catch event for every single variable */
814 for( i = 0; i < consdata->nvars; ++i )
815 {
816 SCIP_CALL( consCatchEvent(scip, cons, eventhdlr, i) );
817 }
818
819 return SCIP_OKAY;
820}
821
822/** drops bound change events for all variables in transformed linear constraint */
823static
825 SCIP* scip, /**< SCIP data structure */
826 SCIP_CONS* cons, /**< linear constraint */
827 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
828 )
829{
830 SCIP_CONSDATA* consdata;
831 int i;
832
833 assert(scip != NULL);
834 assert(cons != NULL);
835
836 consdata = SCIPconsGetData(cons);
837 assert(consdata != NULL);
838 assert(consdata->eventdata != NULL);
839
840 /* drop event of every single variable */
841 for( i = consdata->nvars - 1; i >= 0; --i )
842 {
843 SCIP_CALL( consDropEvent(scip, cons, eventhdlr, i) );
844 }
845
846 /* free eventdata array */
847 SCIPfreeBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize);
848 assert(consdata->eventdata == NULL);
849
850 return SCIP_OKAY;
851}
852
853/** creates a linear constraint data */
854static
856 SCIP* scip, /**< SCIP data structure */
857 SCIP_CONSDATA** consdata, /**< pointer to linear constraint data */
858 int nvars, /**< number of nonzeros in the constraint */
859 SCIP_VAR** vars, /**< array with variables of constraint entries */
860 SCIP_Real* vals, /**< array with coefficients of constraint entries */
861 SCIP_Real lhs, /**< left hand side of row */
862 SCIP_Real rhs /**< right hand side of row */
863 )
864{
865 int v;
866 SCIP_Real constant;
867
868 assert(scip != NULL);
869 assert(consdata != NULL);
870 assert(nvars == 0 || vars != NULL);
871 assert(nvars == 0 || vals != NULL);
872
873 if( SCIPisInfinity(scip, rhs) )
874 rhs = SCIPinfinity(scip);
875 else if( SCIPisInfinity(scip, -rhs) )
876 rhs = -SCIPinfinity(scip);
877
878 if( SCIPisInfinity(scip, -lhs) )
879 lhs = -SCIPinfinity(scip);
880 else if( SCIPisInfinity(scip, lhs) )
881 lhs = SCIPinfinity(scip);
882
883 if( SCIPisGT(scip, lhs, rhs) )
884 {
885 SCIPwarningMessage(scip, "left hand side of linear constraint greater than right hand side\n");
886 SCIPwarningMessage(scip, " -> lhs=%g, rhs=%g\n", lhs, rhs);
887 }
888
889 SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
890
891 (*consdata)->varssize = 0;
892 (*consdata)->nvars = nvars;
893 (*consdata)->hascontvar = FALSE;
894 (*consdata)->hasnonbinvar = FALSE;
895 (*consdata)->hasnonbinvalid = TRUE;
896 (*consdata)->vars = NULL;
897 (*consdata)->vals = NULL;
898
899 constant = 0.0;
900 if( nvars > 0 )
901 {
902 SCIP_VAR** varsbuffer;
903 SCIP_Real* valsbuffer;
904
905 /* copy variables into temporary buffer */
906 SCIP_CALL( SCIPallocBufferArray(scip, &varsbuffer, nvars) );
907 SCIP_CALL( SCIPallocBufferArray(scip, &valsbuffer, nvars) );
908 nvars = 0;
909
910 /* loop over variables and sort out fixed ones */
911 for( v = 0; v < (*consdata)->nvars; ++v )
912 {
913 SCIP_VAR* var;
914 SCIP_Real val;
915
916 var = vars[v];
917 assert(var != NULL);
918 val = vals[v];
919 assert(!SCIPisInfinity(scip, val));
920
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[nvars] = var;
931 valsbuffer[nvars] = val;
932 ++nvars;
933
934 if( !(*consdata)->hascontvar && !SCIPvarIsBinary(var) )
935 {
936 (*consdata)->hasnonbinvar = TRUE;
937
938 if( !SCIPvarIsIntegral(var) )
939 (*consdata)->hascontvar = TRUE;
940 }
941 }
942 }
943 }
944 (*consdata)->nvars = nvars;
945
946 if( nvars > 0 )
947 {
948 /* copy the possibly reduced buffer arrays into block */
949 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, varsbuffer, nvars) );
950 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vals, valsbuffer, nvars) );
951 (*consdata)->varssize = nvars;
952 }
953 /* free temporary buffer */
954 SCIPfreeBufferArray(scip, &valsbuffer);
955 SCIPfreeBufferArray(scip, &varsbuffer);
956 }
957
958 (*consdata)->eventdata = NULL;
959
960 /* due to compressed copying, we may have fixed variables contributing to the left and right hand side */
961 if( !SCIPisZero(scip, constant) )
962 {
963 if( !SCIPisInfinity(scip, REALABS(lhs)) )
964 lhs -= constant;
965
966 if( !SCIPisInfinity(scip, REALABS(rhs)) )
967 rhs -= constant;
968 }
969
970 (*consdata)->row = NULL;
971 (*consdata)->nlrow = NULL;
972 (*consdata)->lhs = lhs;
973 (*consdata)->rhs = rhs;
974 (*consdata)->maxabsval = SCIP_INVALID;
975 (*consdata)->minabsval = SCIP_INVALID;
976 QUAD_ASSIGN((*consdata)->minactivity, SCIP_INVALID);
977 QUAD_ASSIGN((*consdata)->maxactivity, SCIP_INVALID);
978 (*consdata)->lastminactivity = SCIP_INVALID;
979 (*consdata)->lastmaxactivity = SCIP_INVALID;
980 (*consdata)->maxactdelta = SCIP_INVALID;
981 (*consdata)->maxactdeltavar = NULL;
982 (*consdata)->minactivityneginf = -1;
983 (*consdata)->minactivityposinf = -1;
984 (*consdata)->maxactivityneginf = -1;
985 (*consdata)->maxactivityposinf = -1;
986 (*consdata)->minactivityneghuge = -1;
987 (*consdata)->minactivityposhuge = -1;
988 (*consdata)->maxactivityneghuge = -1;
989 (*consdata)->maxactivityposhuge = -1;
990 QUAD_ASSIGN((*consdata)->glbminactivity, SCIP_INVALID);
991 QUAD_ASSIGN((*consdata)->glbmaxactivity, SCIP_INVALID);
992 (*consdata)->lastglbminactivity = SCIP_INVALID;
993 (*consdata)->lastglbmaxactivity = SCIP_INVALID;
994 (*consdata)->glbminactivityneginf = -1;
995 (*consdata)->glbminactivityposinf = -1;
996 (*consdata)->glbmaxactivityneginf = -1;
997 (*consdata)->glbmaxactivityposinf = -1;
998 (*consdata)->glbminactivityneghuge = -1;
999 (*consdata)->glbminactivityposhuge = -1;
1000 (*consdata)->glbmaxactivityneghuge = -1;
1001 (*consdata)->glbmaxactivityposhuge = -1;
1002 (*consdata)->possignature = 0;
1003 (*consdata)->negsignature = 0;
1004 (*consdata)->validmaxabsval = FALSE;
1005 (*consdata)->validminabsval = FALSE;
1006 (*consdata)->validactivities = FALSE;
1007 (*consdata)->validminact = FALSE;
1008 (*consdata)->validmaxact = FALSE;
1009 (*consdata)->validglbminact = FALSE;
1010 (*consdata)->validglbmaxact = FALSE;
1011 (*consdata)->boundstightened = 0;
1012 (*consdata)->presolved = FALSE;
1013 (*consdata)->removedfixings = FALSE;
1014 (*consdata)->validsignature = FALSE;
1015 (*consdata)->changed = TRUE;
1016 (*consdata)->normalized = FALSE;
1017 (*consdata)->upgradetried = FALSE;
1018 (*consdata)->upgraded = FALSE;
1019 (*consdata)->indexsorted = (nvars <= 1);
1020 (*consdata)->merged = (nvars <= 1);
1021 (*consdata)->cliquesadded = FALSE;
1022 (*consdata)->implsadded = FALSE;
1023 (*consdata)->coefsorted = FALSE;
1024 (*consdata)->nbinvars = -1;
1025 (*consdata)->varsdeleted = FALSE;
1026 (*consdata)->rangedrowpropagated = 0;
1027 (*consdata)->checkabsolute = FALSE;
1028
1029 if( SCIPisTransformed(scip) )
1030 {
1031 /* get transformed variables */
1032 SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
1033 }
1034
1035 /* capture variables */
1036 for( v = 0; v < (*consdata)->nvars; v++ )
1037 {
1038 /* likely implies a deleted variable */
1039 if( (*consdata)->vars[v] == NULL )
1040 {
1041 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
1042 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize);
1043 SCIPfreeBlockMemory(scip, consdata);
1044 return SCIP_INVALIDDATA;
1045 }
1046
1047 assert(!SCIPisZero(scip, (*consdata)->vals[v]));
1048 SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
1049 }
1050
1051 return SCIP_OKAY;
1052}
1053
1054/** frees a linear constraint data */
1055static
1057 SCIP* scip, /**< SCIP data structure */
1058 SCIP_CONSDATA** consdata /**< pointer to linear constraint data */
1059 )
1060{
1061 int v;
1062
1063 assert(scip != NULL);
1064 assert(consdata != NULL);
1065 assert(*consdata != NULL);
1066 assert((*consdata)->varssize >= 0);
1067
1068 /* release the row */
1069 if( (*consdata)->row != NULL )
1070 {
1071 SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) );
1072 }
1073
1074 /* release the nlrow */
1075 if( (*consdata)->nlrow != NULL )
1076 {
1077 SCIP_CALL( SCIPreleaseNlRow(scip, &(*consdata)->nlrow) );
1078 }
1079
1080 /* release variables */
1081 for( v = 0; v < (*consdata)->nvars; v++ )
1082 {
1083 assert((*consdata)->vars[v] != NULL);
1084 assert(!SCIPisZero(scip, (*consdata)->vals[v]));
1085 SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->vars[v])) );
1086 }
1087
1088 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
1089 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize);
1090 SCIPfreeBlockMemory(scip, consdata);
1091
1092 return SCIP_OKAY;
1093}
1094
1095/** prints linear constraint in CIP format to file stream */
1096static
1098 SCIP* scip, /**< SCIP data structure */
1099 SCIP_CONSDATA* consdata, /**< linear constraint data */
1100 FILE* file /**< output file (or NULL for standard output) */
1101 )
1102{
1103 assert(scip != NULL);
1104 assert(consdata != NULL);
1105
1106 /* print left hand side for ranged rows */
1107 if( !SCIPisInfinity(scip, -consdata->lhs)
1108 && !SCIPisInfinity(scip, consdata->rhs)
1109 && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1110 SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
1111
1112 /* print coefficients and variables */
1113 if( consdata->nvars == 0 )
1114 SCIPinfoMessage(scip, file, "0");
1115 else
1116 {
1117 /* post linear sum of the linear constraint */
1118 SCIP_CALL( SCIPwriteVarsLinearsum(scip, file, consdata->vars, consdata->vals, consdata->nvars, TRUE) );
1119 }
1120
1121 /* print right hand side */
1122 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1123 SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
1124 else if( !SCIPisInfinity(scip, consdata->rhs) )
1125 SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
1126 else if( !SCIPisInfinity(scip, -consdata->lhs) )
1127 SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
1128 else
1129 SCIPinfoMessage(scip, file, " [free]");
1130
1131 return SCIP_OKAY;
1132}
1133
1134/** prints linear constraint and contained solution values of variables to file stream */
1135static
1137 SCIP* scip, /**< SCIP data structure */
1138 SCIP_CONS* cons, /**< linear constraint */
1139 SCIP_SOL* sol, /**< solution to print */
1140 FILE* file /**< output file (or NULL for standard output) */
1141 )
1142{
1143 SCIP_CONSDATA* consdata;
1144
1145 assert(scip != NULL);
1146 assert(cons != NULL);
1147
1148 consdata = SCIPconsGetData(cons);
1149 assert(consdata != NULL);
1150
1152
1153 /* print left hand side for ranged rows */
1154 if( !SCIPisInfinity(scip, -consdata->lhs)
1155 && !SCIPisInfinity(scip, consdata->rhs)
1156 && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1157 SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
1158
1159 /* print coefficients and variables */
1160 if( consdata->nvars == 0 )
1161 SCIPinfoMessage(scip, file, "0");
1162 else
1163 {
1164 int v;
1165
1166 /* post linear sum of the linear constraint */
1167 for( v = 0; v < consdata->nvars; ++v )
1168 {
1169 if( consdata->vals != NULL )
1170 {
1171 if( consdata->vals[v] == 1.0 )
1172 {
1173 if( v > 0 )
1174 SCIPinfoMessage(scip, file, " +");
1175 }
1176 else if( consdata->vals[v] == -1.0 )
1177 SCIPinfoMessage(scip, file, " -");
1178 else
1179 SCIPinfoMessage(scip, file, " %+.9g", consdata->vals[v]);
1180 }
1181 else if( consdata->nvars > 0 )
1182 SCIPinfoMessage(scip, file, " +");
1183
1184 /* print variable name */
1185 SCIP_CALL( SCIPwriteVarName(scip, file, consdata->vars[v], TRUE) );
1186
1187 SCIPinfoMessage(scip, file, " (%+.9g)", SCIPgetSolVal(scip, sol, consdata->vars[v]));
1188 }
1189 }
1190
1191 /* print right hand side */
1192 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1193 SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
1194 else if( !SCIPisInfinity(scip, consdata->rhs) )
1195 SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
1196 else if( !SCIPisInfinity(scip, -consdata->lhs) )
1197 SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
1198 else
1199 SCIPinfoMessage(scip, file, " [free]");
1200
1201 SCIPinfoMessage(scip, file, ";\n");
1202
1203 return SCIP_OKAY;
1204}
1205
1206/** invalidates activity bounds, such that they are recalculated in next get */
1207static
1209 SCIP_CONSDATA* consdata /**< linear constraint */
1210 )
1211{
1212 assert(consdata != NULL);
1213
1214 consdata->validactivities = FALSE;
1215 consdata->validminact = FALSE;
1216 consdata->validmaxact = FALSE;
1217 consdata->validglbminact = FALSE;
1218 consdata->validglbmaxact = FALSE;
1219 consdata->validmaxabsval = FALSE;
1220 consdata->validminabsval = FALSE;
1221 consdata->hasnonbinvalid = FALSE;
1222 QUAD_ASSIGN(consdata->minactivity, SCIP_INVALID);
1223 QUAD_ASSIGN(consdata->maxactivity, SCIP_INVALID);
1224 consdata->lastminactivity = SCIP_INVALID;
1225 consdata->lastmaxactivity = SCIP_INVALID;
1226 consdata->maxabsval = SCIP_INVALID;
1227 consdata->minabsval = SCIP_INVALID;
1228 consdata->maxactdelta = SCIP_INVALID;
1229 consdata->maxactdeltavar = NULL;
1230 consdata->minactivityneginf = -1;
1231 consdata->minactivityposinf = -1;
1232 consdata->maxactivityneginf = -1;
1233 consdata->maxactivityposinf = -1;
1234 consdata->minactivityneghuge = -1;
1235 consdata->minactivityposhuge = -1;
1236 consdata->maxactivityneghuge = -1;
1237 consdata->maxactivityposhuge = -1;
1238 QUAD_ASSIGN(consdata->glbminactivity, SCIP_INVALID);
1239 QUAD_ASSIGN(consdata->glbmaxactivity, SCIP_INVALID);
1240 consdata->lastglbminactivity = SCIP_INVALID;
1241 consdata->lastglbmaxactivity = SCIP_INVALID;
1242 consdata->glbminactivityneginf = -1;
1243 consdata->glbminactivityposinf = -1;
1244 consdata->glbmaxactivityneginf = -1;
1245 consdata->glbmaxactivityposinf = -1;
1246 consdata->glbminactivityneghuge = -1;
1247 consdata->glbminactivityposhuge = -1;
1248 consdata->glbmaxactivityneghuge = -1;
1249 consdata->glbmaxactivityposhuge = -1;
1250}
1251
1252/** compute the pseudo activity of a constraint */
1253static
1255 SCIP* scip, /**< SCIP data structure */
1256 SCIP_CONSDATA* consdata /**< linear constraint data */
1257 )
1258{
1259 int i;
1260 int pseudoactivityposinf;
1261 int pseudoactivityneginf;
1262 SCIP_Real pseudoactivity;
1264 SCIP_Real val;
1265
1266 pseudoactivity = 0;
1267 pseudoactivityposinf = 0;
1268 pseudoactivityneginf = 0;
1269
1270 for( i = consdata->nvars - 1; i >= 0; --i )
1271 {
1272 bound = SCIPvarGetBestBoundLocal(consdata->vars[i]);
1273 val = consdata->vals[i];
1274 assert(!SCIPisZero(scip, val));
1275
1276 if( SCIPisInfinity(scip, -bound) )
1277 {
1278 if( val < 0.0 )
1279 ++pseudoactivityposinf;
1280 else
1281 ++pseudoactivityneginf;
1282 }
1283 else if( SCIPisInfinity(scip, bound) )
1284 {
1285 if( val < 0.0 )
1286 ++pseudoactivityneginf;
1287 else
1288 ++pseudoactivityposinf;
1289 }
1290 else
1291 pseudoactivity += val * bound;
1292 }
1293
1294 /* invalidate pseudo activity for contradicting contributions */
1295 if( pseudoactivityneginf > 0 && pseudoactivityposinf > 0 )
1296 return SCIP_INVALID;
1297 else if( pseudoactivityneginf > 0 )
1298 return -SCIPinfinity(scip);
1299 else if( pseudoactivityposinf > 0 )
1300 return SCIPinfinity(scip);
1301
1302 return pseudoactivity;
1303}
1304
1305/** recompute the minactivity of a constraint */
1306static
1308 SCIP* scip, /**< SCIP data structure */
1309 SCIP_CONSDATA* consdata /**< linear constraint data */
1310 )
1311{
1312 int i;
1314
1315 QUAD_ASSIGN(consdata->minactivity, 0.0);
1316
1317 for( i = consdata->nvars - 1; i >= 0; --i )
1318 {
1319 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1321 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1322 SCIPquadprecSumQD(consdata->minactivity, consdata->minactivity, consdata->vals[i] * bound);
1323 }
1324
1325 /* the activity was just computed from scratch and is valid now */
1326 consdata->validminact = TRUE;
1327
1328 /* the activity was just computed from scratch, mark it to be reliable */
1329 consdata->lastminactivity = QUAD_TO_DBL(consdata->minactivity);
1330}
1331
1332/** recompute the maxactivity of a constraint */
1333static
1335 SCIP* scip, /**< SCIP data structure */
1336 SCIP_CONSDATA* consdata /**< linear constraint data */
1337 )
1338{
1339 int i;
1341
1342 QUAD_ASSIGN(consdata->maxactivity, 0.0);
1343
1344 for( i = consdata->nvars - 1; i >= 0; --i )
1345 {
1346 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbLocal(consdata->vars[i]) : SCIPvarGetLbLocal(consdata->vars[i]);
1348 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1349 SCIPquadprecSumQD(consdata->maxactivity, consdata->maxactivity, consdata->vals[i] * bound);
1350 }
1351
1352 /* the activity was just computed from scratch and is valid now */
1353 consdata->validmaxact = TRUE;
1354
1355 /* the activity was just computed from scratch, mark it to be reliable */
1356 consdata->lastmaxactivity = QUAD_TO_DBL(consdata->maxactivity);
1357}
1358
1359/** recompute the global minactivity of a constraint */
1360static
1362 SCIP* scip, /**< SCIP data structure */
1363 SCIP_CONSDATA* consdata /**< linear constraint data */
1364 )
1365{
1366 int i;
1368
1369 QUAD_ASSIGN(consdata->glbminactivity, 0.0);
1370
1371 for( i = consdata->nvars - 1; i >= 0; --i )
1372 {
1373 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbGlobal(consdata->vars[i]) : SCIPvarGetUbGlobal(consdata->vars[i]);
1375 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1376 SCIPquadprecSumQD(consdata->glbminactivity, consdata->glbminactivity, consdata->vals[i] * bound);
1377 }
1378
1379 /* the activity was just computed from scratch and is valid now */
1380 consdata->validglbminact = TRUE;
1381
1382 /* the activity was just computed from scratch, mark it to be reliable */
1383 consdata->lastglbminactivity = QUAD_TO_DBL(consdata->glbminactivity);
1384}
1385
1386/** recompute the global maxactivity of a constraint */
1387static
1389 SCIP* scip, /**< SCIP data structure */
1390 SCIP_CONSDATA* consdata /**< linear constraint data */
1391 )
1392{
1393 int i;
1395
1396 QUAD_ASSIGN(consdata->glbmaxactivity, 0.0);
1397
1398 for( i = consdata->nvars - 1; i >= 0; --i )
1399 {
1400 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbGlobal(consdata->vars[i]) : SCIPvarGetLbGlobal(consdata->vars[i]);
1402 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1403 SCIPquadprecSumQD(consdata->glbmaxactivity, consdata->glbmaxactivity, consdata->vals[i] * bound);
1404 }
1405
1406 /* the activity was just computed from scratch and is valid now */
1407 consdata->validglbmaxact = TRUE;
1408
1409 /* the activity was just computed from scratch, mark it to be reliable */
1410 consdata->lastglbmaxactivity = QUAD_TO_DBL(consdata->glbmaxactivity);
1411}
1412
1413/** calculates maximum absolute value of coefficients */
1414static
1416 SCIP_CONSDATA* consdata /**< linear constraint data */
1417 )
1418{
1419 SCIP_Real absval;
1420 int i;
1421
1422 assert(consdata != NULL);
1423 assert(!consdata->validmaxabsval);
1424 assert(consdata->maxabsval >= SCIP_INVALID);
1425
1426 consdata->validmaxabsval = TRUE;
1427 consdata->maxabsval = 0.0;
1428 for( i = 0; i < consdata->nvars; ++i )
1429 {
1430 absval = consdata->vals[i];
1431 absval = REALABS(absval);
1432 if( absval > consdata->maxabsval )
1433 consdata->maxabsval = absval;
1434 }
1435}
1436
1437/** calculates minimum absolute value of coefficients */
1438static
1440 SCIP_CONSDATA* consdata /**< linear constraint data */
1441 )
1442{
1443 SCIP_Real absval;
1444 int i;
1445
1446 assert(consdata != NULL);
1447 assert(!consdata->validminabsval);
1448 assert(consdata->minabsval >= SCIP_INVALID);
1449
1450 consdata->validminabsval = TRUE;
1451
1452 if( consdata->nvars > 0 )
1453 consdata->minabsval = REALABS(consdata->vals[0]);
1454 else
1455 consdata->minabsval = 0.0;
1456
1457 for( i = 1; i < consdata->nvars; ++i )
1458 {
1459 absval = consdata->vals[i];
1460 absval = REALABS(absval);
1461 if( absval < consdata->minabsval )
1462 consdata->minabsval = absval;
1463 }
1464}
1465
1466/** checks the type of all variables of the constraint and sets hasnonbinvar and hascontvar flags accordingly */
1467static
1469 SCIP_CONSDATA* consdata /**< linear constraint data */
1470 )
1471{
1472 int v;
1473
1474 assert(!consdata->hasnonbinvalid);
1475 consdata->hasnonbinvar = FALSE;
1476 consdata->hascontvar = FALSE;
1477
1478 for( v = consdata->nvars - 1; v >= 0; --v )
1479 {
1480 if( !SCIPvarIsBinary(consdata->vars[v]) )
1481 {
1482 consdata->hasnonbinvar = TRUE;
1483
1484 if( !SCIPvarIsIntegral(consdata->vars[v]) )
1485 {
1486 consdata->hascontvar = TRUE;
1487 break;
1488 }
1489 }
1490 }
1491 assert(consdata->hascontvar || v < 0);
1492
1493 consdata->hasnonbinvalid = TRUE;
1494}
1495
1496
1497#ifdef CHECKMAXACTDELTA
1498/** checks that the stored maximal activity delta (if not invalid) is correct */
1499static
1501 SCIP* scip, /**< SCIP data structure */
1502 SCIP_CONSDATA* consdata /**< linear constraint data */
1503 )
1504{
1505 if( consdata->maxactdelta != SCIP_INVALID )
1506 {
1507 SCIP_Real maxactdelta = 0.0;
1508 SCIP_Real domain;
1509 SCIP_Real delta;
1510 SCIP_Real lb;
1511 SCIP_Real ub;
1512 int v;
1513
1514 for( v = consdata->nvars - 1; v >= 0; --v )
1515 {
1516 lb = SCIPvarGetLbLocal(consdata->vars[v]);
1517 ub = SCIPvarGetUbLocal(consdata->vars[v]);
1518
1519 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1520 {
1521 maxactdelta = SCIPinfinity(scip);
1522 break;
1523 }
1524
1525 domain = ub - lb;
1526 delta = REALABS(consdata->vals[v]) * domain;
1527
1528 if( delta > maxactdelta )
1529 {
1530 maxactdelta = delta;
1531 }
1532 }
1533 assert(SCIPisFeasEQ(scip, maxactdelta, consdata->maxactdelta));
1534 }
1535}
1536#else
1537#define checkMaxActivityDelta(scip, consdata) /**/
1538#endif
1539
1540/** recompute maximal activity contribution for a single variable */
1541static
1543 SCIP* scip, /**< SCIP data structure */
1544 SCIP_CONSDATA* consdata /**< linear constraint data */
1545 )
1546{
1547 SCIP_Real delta;
1548 int v;
1549
1550 consdata->maxactdelta = 0.0;
1551
1552 if( !consdata->hasnonbinvalid )
1553 consdataCheckNonbinvar(consdata);
1554
1555 /* easy case, the problem consists only of binary variables */
1556 if( !consdata->hasnonbinvar )
1557 {
1558 for( v = consdata->nvars - 1; v >= 0; --v )
1559 {
1560 if( SCIPvarGetLbLocal(consdata->vars[v]) < 0.5 && SCIPvarGetUbLocal(consdata->vars[v]) > 0.5 )
1561 {
1562 delta = REALABS(consdata->vals[v]);
1563
1564 if( delta > consdata->maxactdelta )
1565 {
1566 consdata->maxactdelta = delta;
1567 consdata->maxactdeltavar = consdata->vars[v];
1568 }
1569 }
1570 }
1571 return;
1572 }
1573
1574 for( v = consdata->nvars - 1; v >= 0; --v )
1575 {
1576 SCIP_Real domain;
1577 SCIP_Real lb;
1578 SCIP_Real ub;
1579
1580 lb = SCIPvarGetLbLocal(consdata->vars[v]);
1581 ub = SCIPvarGetUbLocal(consdata->vars[v]);
1582
1583 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1584 {
1585 consdata->maxactdelta = SCIPinfinity(scip);
1586 consdata->maxactdeltavar = consdata->vars[v];
1587 break;
1588 }
1589
1590 domain = ub - lb;
1591 delta = REALABS(consdata->vals[v]) * domain;
1592
1593 if( delta > consdata->maxactdelta )
1594 {
1595 consdata->maxactdelta = delta;
1596 consdata->maxactdeltavar = consdata->vars[v];
1597 }
1598 }
1599}
1600
1601
1602/** updates activities for a change in a bound */
1603static
1605 SCIP* scip, /**< SCIP data structure */
1606 SCIP_CONSDATA* consdata, /**< linear constraint data */
1607 SCIP_VAR* var, /**< variable that has been changed; can be NULL for global bound changes */
1608 SCIP_Real oldbound, /**< old bound of variable */
1609 SCIP_Real newbound, /**< new bound of variable */
1610 SCIP_Real val, /**< coefficient of constraint entry */
1611 SCIP_BOUNDTYPE boundtype, /**< type of the bound change */
1612 SCIP_Bool global, /**< is it a global or a local bound change? */
1613 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1614 )
1615{
1616 QUAD_MEMBER(SCIP_Real* activity);
1617 QUAD_MEMBER(SCIP_Real delta);
1618 SCIP_Real* lastactivity;
1619 int* activityposinf;
1620 int* activityneginf;
1621 int* activityposhuge;
1622 int* activityneghuge;
1623 SCIP_Real oldcontribution;
1624 SCIP_Real newcontribution;
1625 SCIP_Bool validact;
1626 SCIP_Bool finitenewbound;
1627 SCIP_Bool hugevalnewcont;
1628
1629 assert(scip != NULL);
1630 assert(consdata != NULL);
1631 assert(global || (var != NULL));
1632 assert(consdata->validactivities);
1633 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
1634 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
1635 assert(consdata->lastminactivity < SCIP_INVALID);
1636 assert(consdata->lastmaxactivity < SCIP_INVALID);
1637 assert(consdata->minactivityneginf >= 0);
1638 assert(consdata->minactivityposinf >= 0);
1639 assert(consdata->maxactivityneginf >= 0);
1640 assert(consdata->maxactivityposinf >= 0);
1641 assert(consdata->minactivityneghuge >= 0);
1642 assert(consdata->minactivityposhuge >= 0);
1643 assert(consdata->maxactivityneghuge >= 0);
1644 assert(consdata->maxactivityposhuge >= 0);
1645 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
1646 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
1647 assert(consdata->lastglbminactivity < SCIP_INVALID);
1648 assert(consdata->lastglbmaxactivity < SCIP_INVALID);
1649 assert(consdata->glbminactivityneginf >= 0);
1650 assert(consdata->glbminactivityposinf >= 0);
1651 assert(consdata->glbmaxactivityneginf >= 0);
1652 assert(consdata->glbmaxactivityposinf >= 0);
1653 assert(consdata->glbminactivityneghuge >= 0);
1654 assert(consdata->glbminactivityposhuge >= 0);
1655 assert(consdata->glbmaxactivityneghuge >= 0);
1656 assert(consdata->glbmaxactivityposhuge >= 0);
1657
1658 QUAD_ASSIGN(delta, 0.0);
1659
1660 /* we are updating global activities */
1661 if( global )
1662 {
1663 /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1664 * lower bound + pos. coef: update minactivity
1665 * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1666 * upper bound + pos. coef: update maxactivity
1667 * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1668 */
1669 if( boundtype == SCIP_BOUNDTYPE_LOWER )
1670 {
1671 if( val > 0.0 )
1672 {
1673 QUAD_ASSIGN_Q(activity, &consdata->glbminactivity);
1674 lastactivity = &(consdata->lastglbminactivity);
1675 activityposinf = &(consdata->glbminactivityposinf);
1676 activityneginf = &(consdata->glbminactivityneginf);
1677 activityposhuge = &(consdata->glbminactivityposhuge);
1678 activityneghuge = &(consdata->glbminactivityneghuge);
1679 validact = consdata->validglbminact;
1680 }
1681 else
1682 {
1683 QUAD_ASSIGN_Q(activity, &consdata->glbmaxactivity);
1684 lastactivity = &(consdata->lastglbmaxactivity);
1685 activityposinf = &(consdata->glbmaxactivityneginf);
1686 activityneginf = &(consdata->glbmaxactivityposinf);
1687 activityposhuge = &(consdata->glbmaxactivityposhuge);
1688 activityneghuge = &(consdata->glbmaxactivityneghuge);
1689 validact = consdata->validglbmaxact;
1690 }
1691 }
1692 else
1693 {
1694 if( val > 0.0 )
1695 {
1696 QUAD_ASSIGN_Q(activity, &consdata->glbmaxactivity);
1697 lastactivity = &(consdata->lastglbmaxactivity);
1698 activityposinf = &(consdata->glbmaxactivityposinf);
1699 activityneginf = &(consdata->glbmaxactivityneginf);
1700 activityposhuge = &(consdata->glbmaxactivityposhuge);
1701 activityneghuge = &(consdata->glbmaxactivityneghuge);
1702 validact = consdata->validglbmaxact;
1703 }
1704 else
1705 {
1706 QUAD_ASSIGN_Q(activity, &consdata->glbminactivity);
1707 lastactivity = &(consdata->lastglbminactivity);
1708 activityposinf = &(consdata->glbminactivityneginf);
1709 activityneginf = &(consdata->glbminactivityposinf);
1710 activityposhuge = &(consdata->glbminactivityposhuge);
1711 activityneghuge = &(consdata->glbminactivityneghuge);
1712 validact = consdata->validglbminact;
1713 }
1714 }
1715 }
1716 /* we are updating local activities */
1717 else
1718 {
1719 /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1720 * lower bound + pos. coef: update minactivity
1721 * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1722 * upper bound + pos. coef: update maxactivity
1723 * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1724 */
1725 if( boundtype == SCIP_BOUNDTYPE_LOWER )
1726 {
1727 if( val > 0.0 )
1728 {
1729 QUAD_ASSIGN_Q(activity, &consdata->minactivity);
1730 lastactivity = &(consdata->lastminactivity);
1731 activityposinf = &(consdata->minactivityposinf);
1732 activityneginf = &(consdata->minactivityneginf);
1733 activityposhuge = &(consdata->minactivityposhuge);
1734 activityneghuge = &(consdata->minactivityneghuge);
1735 validact = consdata->validminact;
1736 }
1737 else
1738 {
1739 QUAD_ASSIGN_Q(activity, &consdata->maxactivity);
1740 lastactivity = &(consdata->lastmaxactivity);
1741 activityposinf = &(consdata->maxactivityneginf);
1742 activityneginf = &(consdata->maxactivityposinf);
1743 activityposhuge = &(consdata->maxactivityposhuge);
1744 activityneghuge = &(consdata->maxactivityneghuge);
1745 validact = consdata->validmaxact;
1746 }
1747 }
1748 else
1749 {
1750 if( val > 0.0 )
1751 {
1752 QUAD_ASSIGN_Q(activity, &consdata->maxactivity);
1753 lastactivity = &(consdata->lastmaxactivity);
1754 activityposinf = &(consdata->maxactivityposinf);
1755 activityneginf = &(consdata->maxactivityneginf);
1756 activityposhuge = &(consdata->maxactivityposhuge);
1757 activityneghuge = &(consdata->maxactivityneghuge);
1758 validact = consdata->validmaxact;
1759 }
1760 else
1761 {
1762 QUAD_ASSIGN_Q(activity, &consdata->minactivity);
1763 lastactivity = &(consdata->lastminactivity);
1764 activityposinf = &(consdata->minactivityneginf);
1765 activityneginf = &(consdata->minactivityposinf);
1766 activityposhuge = &(consdata->minactivityposhuge);
1767 activityneghuge = &(consdata->minactivityneghuge);
1768 validact = consdata->validminact;
1769 }
1770 }
1771 }
1772
1773 oldcontribution = val * oldbound;
1774 newcontribution = val * newbound;
1775 hugevalnewcont = SCIPisHugeValue(scip, REALABS(newcontribution));
1776 finitenewbound = !SCIPisInfinity(scip, REALABS(newbound));
1777
1778 if( SCIPisInfinity(scip, REALABS(oldbound)) )
1779 {
1780 /* old bound was +infinity */
1781 if( oldbound > 0.0 )
1782 {
1783 assert((*activityposinf) >= 1);
1784
1785 /* we only have to do something if the new bound is not again +infinity */
1786 if( finitenewbound || newbound < 0.0 )
1787 {
1788 /* decrease the counter for positive infinite contributions */
1789 (*activityposinf)--;
1790
1791 /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1792 if( !finitenewbound && newbound < 0.0 )
1793 (*activityneginf)++;
1794 else if( hugevalnewcont )
1795 {
1796 /* if the contribution of this variable is too large, increase the counter for huge values */
1797 if( newcontribution > 0.0 )
1798 (*activityposhuge)++;
1799 else
1800 (*activityneghuge)++;
1801 }
1802 /* "normal case": just add the contribution to the activity */
1803 else
1804 QUAD_ASSIGN(delta, newcontribution);
1805 }
1806 }
1807 /* old bound was -infinity */
1808 else
1809 {
1810 assert(oldbound < 0.0);
1811 assert((*activityneginf) >= 1);
1812
1813 /* we only have to do something ig the new bound is not again -infinity */
1814 if( finitenewbound || newbound > 0.0 )
1815 {
1816 /* decrease the counter for negative infinite contributions */
1817 (*activityneginf)--;
1818
1819 /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1820 if( !finitenewbound && newbound > 0.0 )
1821 (*activityposinf)++;
1822 else if( hugevalnewcont )
1823 {
1824 /* if the contribution of this variable is too large, increase the counter for huge values */
1825 if( newcontribution > 0.0 )
1826 (*activityposhuge)++;
1827 else
1828 (*activityneghuge)++;
1829 }
1830 /* "normal case": just add the contribution to the activity */
1831 else
1832 QUAD_ASSIGN(delta, newcontribution);
1833 }
1834 }
1835 }
1836 else if( SCIPisHugeValue(scip, REALABS(oldcontribution)) )
1837 {
1838 /* old contribution was too large and positive */
1839 if( oldcontribution > 0.0 )
1840 {
1841 assert((*activityposhuge) >= 1);
1842
1843 /* decrease the counter for huge positive contributions; it might be increased again later,
1844 * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1845 */
1846 (*activityposhuge)--;
1847
1848 if( !finitenewbound )
1849 {
1850 /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1851 if( newbound > 0.0 )
1852 (*activityposinf)++;
1853 /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1854 else
1855 (*activityneginf)++;
1856 }
1857 else if( hugevalnewcont )
1858 {
1859 /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1860 if( newcontribution > 0.0 )
1861 (*activityposhuge)++;
1862 /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1863 else
1864 (*activityneghuge)++;
1865 }
1866 /* "normal case": just add the contribution to the activity */
1867 else
1868 QUAD_ASSIGN(delta, newcontribution);
1869 }
1870 /* old contribution was too large and negative */
1871 else
1872 {
1873 assert(oldcontribution < 0.0);
1874 assert((*activityneghuge) >= 1);
1875
1876 /* decrease the counter for huge negative contributions; it might be increased again later,
1877 * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1878 */
1879 (*activityneghuge)--;
1880
1881 if( !finitenewbound )
1882 {
1883 /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1884 if( newbound > 0.0 )
1885 (*activityposinf)++;
1886 /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1887 else
1888 (*activityneginf)++;
1889 }
1890 else if( hugevalnewcont )
1891 {
1892 /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1893 if( newcontribution > 0.0 )
1894 (*activityposhuge)++;
1895 /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1896 else
1897 (*activityneghuge)++;
1898 }
1899 /* "normal case": just add the contribution to the activity */
1900 else
1901 QUAD_ASSIGN(delta, newcontribution);
1902 }
1903 }
1904 /* old bound was finite and not too large */
1905 else
1906 {
1907 if( !finitenewbound )
1908 {
1909 /* if the new bound is +infinity, the old contribution has to be subtracted
1910 * and the counter for positive infinite contributions has to be increased
1911 */
1912 if( newbound > 0.0 )
1913 {
1914 (*activityposinf)++;
1915 QUAD_ASSIGN(delta, -oldcontribution);
1916 }
1917 /* if the new bound is -infinity, the old contribution has to be subtracted
1918 * and the counter for negative infinite contributions has to be increased
1919 */
1920 else
1921 {
1922 assert(newbound < 0.0 );
1923
1924 (*activityneginf)++;
1925 QUAD_ASSIGN(delta, -oldcontribution);
1926 }
1927 }
1928 /* if the contribution of this variable is too large, increase the counter for huge values */
1929 else if( hugevalnewcont )
1930 {
1931 if( newcontribution > 0.0 )
1932 {
1933 (*activityposhuge)++;
1934 QUAD_ASSIGN(delta, -oldcontribution);
1935 }
1936 else
1937 {
1938 (*activityneghuge)++;
1939 QUAD_ASSIGN(delta, -oldcontribution);
1940 }
1941 }
1942 /* "normal case": just update the activity */
1943 else
1944 {
1945 QUAD_ASSIGN(delta, newcontribution);
1946 SCIPquadprecSumQD(delta, delta, -oldcontribution);
1947 }
1948 }
1949
1950 /* update the activity, if the current value is valid and there was a change in the finite part */
1951 if( validact && (QUAD_TO_DBL(delta) != 0.0) )
1952 {
1953 SCIP_Real curractivity;
1954
1955 /* if the absolute value of the activity is increased, this is regarded as reliable,
1956 * otherwise, we check whether we can still trust the updated value
1957 */
1958 SCIPquadprecSumQD(*activity, *activity, QUAD_TO_DBL(delta));
1959
1960 curractivity = QUAD_TO_DBL(*activity);
1961 assert(!SCIPisInfinity(scip, -curractivity) && !SCIPisInfinity(scip, curractivity));
1962
1963 if( REALABS((*lastactivity)) < REALABS(curractivity) )
1964 {
1965 (*lastactivity) = curractivity;
1966 }
1967 else
1968 {
1969 if( checkreliability && SCIPisUpdateUnreliable(scip, curractivity, (*lastactivity)) )
1970 {
1971 SCIPdebugMsg(scip, "%s activity of linear constraint unreliable after update: %16.9g\n",
1972 (global ? "global " : ""), curractivity);
1973
1974 /* mark the activity that was just changed and is not reliable anymore to be invalid */
1975 if( global )
1976 {
1977 if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1978 consdata->validglbminact = FALSE;
1979 else
1980 consdata->validglbmaxact = FALSE;
1981 }
1982 else
1983 {
1984 if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1985 consdata->validminact = FALSE;
1986 else
1987 consdata->validmaxact = FALSE;
1988 }
1989 }
1990 }
1991 }
1992}
1993
1994/** updates minimum and maximum activity for a change in lower bound */
1995static
1997 SCIP* scip, /**< SCIP data structure */
1998 SCIP_CONSDATA* consdata, /**< linear constraint data */
1999 SCIP_VAR* var, /**< variable that has been changed */
2000 SCIP_Real oldlb, /**< old lower bound of variable */
2001 SCIP_Real newlb, /**< new lower bound of variable */
2002 SCIP_Real val, /**< coefficient of constraint entry */
2003 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2004 )
2005{
2006 assert(scip != NULL);
2007 assert(consdata != NULL);
2008 assert(var != NULL);
2009
2010 if( consdata->validactivities )
2011 {
2012 consdataUpdateActivities(scip, consdata, var, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, FALSE, checkreliability);
2013
2014 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->minactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->minactivity)));
2015 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->maxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->maxactivity)));
2016 }
2017}
2018
2019/** updates minimum and maximum activity for a change in upper bound */
2020static
2022 SCIP* scip, /**< SCIP data structure */
2023 SCIP_CONSDATA* consdata, /**< linear constraint data */
2024 SCIP_VAR* var, /**< variable that has been changed */
2025 SCIP_Real oldub, /**< old upper bound of variable */
2026 SCIP_Real newub, /**< new upper bound of variable */
2027 SCIP_Real val, /**< coefficient of constraint entry */
2028 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2029 )
2030{
2031 assert(scip != NULL);
2032 assert(consdata != NULL);
2033 assert(var != NULL);
2034
2035 if( consdata->validactivities )
2036 {
2037 consdataUpdateActivities(scip, consdata, var, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, FALSE, checkreliability);
2038
2039 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->minactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->minactivity)));
2040 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->maxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->maxactivity)));
2041 }
2042}
2043
2044/** updates minimum and maximum global activity for a change in the global lower bound */
2045static
2047 SCIP* scip, /**< SCIP data structure */
2048 SCIP_CONSDATA* consdata, /**< linear constraint data */
2049 SCIP_Real oldlb, /**< old lower bound of variable */
2050 SCIP_Real newlb, /**< new lower bound of variable */
2051 SCIP_Real val, /**< coefficient of constraint entry */
2052 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2053 )
2054{
2055 assert(scip != NULL);
2056 assert(consdata != NULL);
2057
2058 if( consdata->validactivities )
2059 {
2060 consdataUpdateActivities(scip, consdata, NULL, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, TRUE, checkreliability);
2061
2062 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbminactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbminactivity)));
2063 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbmaxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbmaxactivity)));
2064 }
2065}
2066
2067/** updates minimum and maximum global activity for a change in global upper bound */
2068static
2070 SCIP* scip, /**< SCIP data structure */
2071 SCIP_CONSDATA* consdata, /**< linear constraint data */
2072 SCIP_Real oldub, /**< old upper bound of variable */
2073 SCIP_Real newub, /**< new upper bound of variable */
2074 SCIP_Real val, /**< coefficient of constraint entry */
2075 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2076 )
2077{
2078 assert(scip != NULL);
2079 assert(consdata != NULL);
2080
2081 if( consdata->validactivities )
2082 {
2083 consdataUpdateActivities(scip, consdata, NULL, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, TRUE, checkreliability);
2084
2085 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbminactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbminactivity)));
2086 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbmaxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbmaxactivity)));
2087 }
2088}
2089
2090/** updates minimum and maximum activity and maximum absolute value for coefficient addition */
2091static
2093 SCIP* scip, /**< SCIP data structure */
2094 SCIP_CONSDATA* consdata, /**< linear constraint data */
2095 SCIP_VAR* var, /**< variable of constraint entry */
2096 SCIP_Real val, /**< coefficient of constraint entry */
2097 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2098 )
2099{
2100 assert(scip != NULL);
2101 assert(consdata != NULL);
2102 assert(var != NULL);
2103 assert(!SCIPisZero(scip, val));
2104
2105 /* update maximum absolute value */
2106 if( consdata->validmaxabsval )
2107 {
2108 SCIP_Real absval;
2109
2110 assert(consdata->maxabsval < SCIP_INVALID);
2111
2112 absval = REALABS(val);
2113 consdata->maxabsval = MAX(consdata->maxabsval, absval);
2114 }
2115
2116 /* update minimum absolute value */
2117 if( consdata->validminabsval )
2118 {
2119 SCIP_Real absval;
2120
2121 assert(consdata->minabsval < SCIP_INVALID);
2122
2123 absval = REALABS(val);
2124 consdata->minabsval = MIN(consdata->minabsval, absval);
2125 }
2126
2127 /* update minimum and maximum activity */
2128 if( consdata->validactivities )
2129 {
2130 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2131 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2132 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2133 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2134
2135 consdataUpdateActivitiesLb(scip, consdata, var, 0.0, SCIPvarGetLbLocal(var), val, checkreliability);
2136 consdataUpdateActivitiesUb(scip, consdata, var, 0.0, SCIPvarGetUbLocal(var), val, checkreliability);
2137 consdataUpdateActivitiesGlbLb(scip, consdata, 0.0, SCIPvarGetLbGlobal(var), val, checkreliability);
2138 consdataUpdateActivitiesGlbUb(scip, consdata, 0.0, SCIPvarGetUbGlobal(var), val, checkreliability);
2139 }
2140
2141 /* update maximum activity delta */
2142 if( consdata->maxactdeltavar == NULL || !SCIPisInfinity(scip, consdata->maxactdelta) )
2143 {
2146
2147 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
2148 {
2149 consdata->maxactdelta = SCIPinfinity(scip);
2150 consdata->maxactdeltavar = var;
2151 }
2152 else if( consdata->maxactdeltavar != NULL )
2153 {
2154 SCIP_Real domain = ub - lb;
2155 SCIP_Real delta = REALABS(val) * domain;
2156
2157 if( delta > consdata->maxactdelta )
2158 {
2159 consdata->maxactdelta = delta;
2160 consdata->maxactdeltavar = var;
2161 }
2162 }
2163 }
2164}
2165
2166/** updates minimum and maximum activity for coefficient deletion, invalidates maximum absolute value if necessary */
2167static
2169 SCIP* scip, /**< SCIP data structure */
2170 SCIP_CONSDATA* consdata, /**< linear constraint data */
2171 SCIP_VAR* var, /**< variable of constraint entry */
2172 SCIP_Real val, /**< coefficient of constraint entry */
2173 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2174 )
2175{
2176 assert(scip != NULL);
2177 assert(consdata != NULL);
2178 assert(var != NULL);
2179 assert(!SCIPisZero(scip, val));
2180
2181 /* invalidate maximum absolute value, if this coefficient was the maximum */
2182 if( consdata->validmaxabsval )
2183 {
2184 SCIP_Real absval;
2185
2186 absval = REALABS(val);
2187
2188 if( SCIPisEQ(scip, absval, consdata->maxabsval) )
2189 {
2190 consdata->validmaxabsval = FALSE;
2191 consdata->maxabsval = SCIP_INVALID;
2192 }
2193 }
2194
2195 /* invalidate minimum absolute value, if this coefficient was the minimum */
2196 if( consdata->validminabsval )
2197 {
2198 SCIP_Real absval;
2199
2200 absval = REALABS(val);
2201
2202 if( SCIPisEQ(scip, absval, consdata->minabsval) )
2203 {
2204 consdata->validminabsval = FALSE;
2205 consdata->minabsval = SCIP_INVALID;
2206 }
2207 }
2208
2209 /* update minimum and maximum activity */
2210 if( consdata->validactivities )
2211 {
2212 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2213 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2214 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2215 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2216
2217 consdataUpdateActivitiesLb(scip, consdata, var, SCIPvarGetLbLocal(var), 0.0, val, checkreliability);
2218 consdataUpdateActivitiesUb(scip, consdata, var, SCIPvarGetUbLocal(var), 0.0, val, checkreliability);
2219 consdataUpdateActivitiesGlbLb(scip, consdata, SCIPvarGetLbGlobal(var), 0.0, val, checkreliability);
2220 consdataUpdateActivitiesGlbUb(scip, consdata, SCIPvarGetUbGlobal(var), 0.0, val, checkreliability);
2221 }
2222
2223 /* reset maximum activity delta so that it will be recalculated on the next real propagation */
2224 if( consdata->maxactdeltavar == var )
2225 {
2226 consdata->maxactdelta = SCIP_INVALID;
2227 consdata->maxactdeltavar = NULL;
2228 }
2229}
2230
2231/** updates minimum and maximum activity for coefficient change, invalidates maximum absolute value if necessary */
2232static
2234 SCIP* scip, /**< SCIP data structure */
2235 SCIP_CONSDATA* consdata, /**< linear constraint data */
2236 SCIP_VAR* var, /**< variable of constraint entry */
2237 SCIP_Real oldval, /**< old coefficient of constraint entry */
2238 SCIP_Real newval, /**< new coefficient of constraint entry */
2239 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2240 )
2241{
2242 /* @todo do something more clever here, e.g. if oldval * newval >= 0, do the update directly */
2243 consdataUpdateDelCoef(scip, consdata, var, oldval, checkreliability);
2244 consdataUpdateAddCoef(scip, consdata, var, newval, checkreliability);
2245}
2246
2247/** returns the maximum absolute value of all coefficients in the constraint */
2248static
2250 SCIP_CONSDATA* consdata /**< linear constraint data */
2251 )
2252{
2253 assert(consdata != NULL);
2254
2255 if( !consdata->validmaxabsval )
2256 consdataCalcMaxAbsval(consdata);
2257 assert(consdata->validmaxabsval);
2258 assert(consdata->maxabsval < SCIP_INVALID);
2259
2260 return consdata->maxabsval;
2261}
2262
2263/** returns the minimum absolute value of all coefficients in the constraint */
2264static
2266 SCIP_CONSDATA* consdata /**< linear constraint data */
2267 )
2268{
2269 assert(consdata != NULL);
2270
2271 if( !consdata->validminabsval )
2272 consdataCalcMinAbsval(consdata);
2273 assert(consdata->validminabsval);
2274 assert(consdata->minabsval < SCIP_INVALID);
2275
2276 return consdata->minabsval;
2277}
2278
2279/** calculates minimum and maximum local and global activity for constraint from scratch;
2280 * additionally recalculates maximum absolute value of coefficients
2281 */
2282static
2284 SCIP* scip, /**< SCIP data structure */
2285 SCIP_CONSDATA* consdata /**< linear constraint data */
2286 )
2287{
2288 int i;
2289
2290 assert(scip != NULL);
2291 assert(consdata != NULL);
2292 assert(!consdata->validactivities);
2293 assert(QUAD_TO_DBL(consdata->minactivity) >= SCIP_INVALID || consdata->validminact);
2294 assert(QUAD_TO_DBL(consdata->maxactivity) >= SCIP_INVALID || consdata->validmaxact);
2295 assert(QUAD_TO_DBL(consdata->glbminactivity) >= SCIP_INVALID || consdata->validglbminact);
2296 assert(QUAD_TO_DBL(consdata->glbmaxactivity) >= SCIP_INVALID || consdata->validglbmaxact);
2297
2298 consdata->validmaxabsval = TRUE;
2299 consdata->validminabsval = TRUE;
2300 consdata->validactivities = TRUE;
2301 consdata->validminact = TRUE;
2302 consdata->validmaxact = TRUE;
2303 consdata->validglbminact = TRUE;
2304 consdata->validglbmaxact = TRUE;
2305 consdata->maxabsval = 0.0;
2306 consdata->minabsval = (consdata->nvars == 0 ? 0.0 : REALABS(consdata->vals[0]));
2307 QUAD_ASSIGN(consdata->minactivity, 0.0);
2308 QUAD_ASSIGN(consdata->maxactivity, 0.0);
2309 consdata->lastminactivity = 0.0;
2310 consdata->lastmaxactivity = 0.0;
2311 consdata->minactivityneginf = 0;
2312 consdata->minactivityposinf = 0;
2313 consdata->maxactivityneginf = 0;
2314 consdata->maxactivityposinf = 0;
2315 consdata->minactivityneghuge = 0;
2316 consdata->minactivityposhuge = 0;
2317 consdata->maxactivityneghuge = 0;
2318 consdata->maxactivityposhuge = 0;
2319 QUAD_ASSIGN(consdata->glbminactivity, 0.0);
2320 QUAD_ASSIGN(consdata->glbmaxactivity, 0.0);
2321 consdata->lastglbminactivity = 0.0;
2322 consdata->lastglbmaxactivity = 0.0;
2323 consdata->glbminactivityneginf = 0;
2324 consdata->glbminactivityposinf = 0;
2325 consdata->glbmaxactivityneginf = 0;
2326 consdata->glbmaxactivityposinf = 0;
2327 consdata->glbminactivityneghuge = 0;
2328 consdata->glbminactivityposhuge = 0;
2329 consdata->glbmaxactivityneghuge = 0;
2330 consdata->glbmaxactivityposhuge = 0;
2331
2332 for( i = 0; i < consdata->nvars; ++i )
2333 consdataUpdateAddCoef(scip, consdata, consdata->vars[i], consdata->vals[i], FALSE);
2334
2335 consdata->lastminactivity = QUAD_TO_DBL(consdata->minactivity);
2336 consdata->lastmaxactivity = QUAD_TO_DBL(consdata->maxactivity);
2337 consdata->lastglbminactivity = QUAD_TO_DBL(consdata->glbminactivity);
2338 consdata->lastglbmaxactivity = QUAD_TO_DBL(consdata->glbmaxactivity);
2339}
2340
2341/** gets minimal activity for constraint and given values of counters for infinite and huge contributions
2342 * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2343 */
2344static
2346 SCIP* scip, /**< SCIP data structure */
2347 SCIP_CONSDATA* consdata, /**< linear constraint */
2348 int posinf, /**< number of coefficients contributing pos. infinite value */
2349 int neginf, /**< number of coefficients contributing neg. infinite value */
2350 int poshuge, /**< number of coefficients contributing huge pos. value */
2351 int neghuge, /**< number of coefficients contributing huge neg. value */
2352 SCIP_Real delta, /**< value to subtract from stored minactivity
2353 * (contribution of the variable set to zero when getting residual activity) */
2354 SCIP_Bool global, /**< should the global or local minimal activity be returned? */
2355 SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2356 SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2357 SCIP_Bool* istight, /**< pointer to store whether activity bound is tight to variable bounds
2358 * i.e. is the actual minactivity (otherwise a lower bound is provided) */
2359 SCIP_Bool* issettoinfinity /**< pointer to store whether minactivity was set to infinity or calculated */
2360 )
2361{
2362 assert(scip != NULL);
2363 assert(consdata != NULL);
2364 assert(posinf >= 0);
2365 assert(neginf >= 0);
2366 assert(poshuge >= 0);
2367 assert(neghuge >= 0);
2368 assert(minactivity != NULL);
2369 assert(istight != NULL);
2370 assert(issettoinfinity != NULL);
2371
2372 /* if we have neg. infinite contributions, the minactivity is -infty */
2373 if( neginf > 0 )
2374 {
2375 *minactivity = -SCIPinfinity(scip);
2376 *issettoinfinity = TRUE;
2377 *istight = posinf == 0;
2378 }
2379 /* if we have pos. (and no neg.) infinite contributions, the minactivity is +infty */
2380 else if( posinf > 0 )
2381 {
2382 *minactivity = SCIPinfinity(scip);
2383 *issettoinfinity = TRUE;
2384 *istight = TRUE;
2385 }
2386 /* if we have neg. huge contributions or do not need a good relaxation, we just return -infty as minactivity */
2387 else if( neghuge > 0 || ( poshuge > 0 && !goodrelax ) )
2388 {
2389 *minactivity = -SCIPinfinity(scip);
2390 *issettoinfinity = TRUE;
2391 *istight = FALSE;
2392 }
2393 else
2394 {
2395 SCIP_Real QUAD(tmpactivity);
2396
2397 /* recompute minactivity if it is not valid */
2398 if( global )
2399 {
2400 if( !consdata->validglbminact )
2402 assert(consdata->validglbminact);
2403
2404 QUAD_ASSIGN_Q(tmpactivity, consdata->glbminactivity);
2405 }
2406 else
2407 {
2408 if( !consdata->validminact )
2410 assert(consdata->validminact);
2411
2412 QUAD_ASSIGN_Q(tmpactivity, consdata->minactivity);
2413 }
2414
2415 /* calculate residual minactivity */
2416 SCIPquadprecSumQD(tmpactivity, tmpactivity, -delta);
2417
2418 /* we have no infinite and no neg. huge contributions, but pos. huge contributions; a feasible relaxation of the
2419 * minactivity is given by adding the number of positive huge contributions times the huge value
2420 */
2421 if( poshuge > 0 )
2422 {
2423 SCIPquadprecSumQD(tmpactivity, tmpactivity, poshuge * SCIPgetHugeValue(scip));
2424 *istight = FALSE;
2425 }
2426 /* all counters are zero, so the minactivity is tight */
2427 else
2428 *istight = TRUE;
2429
2430 /* round residual minactivity */
2431 *minactivity = QUAD_TO_DBL(tmpactivity);
2432 *issettoinfinity = FALSE;
2433 }
2434}
2435
2436/** gets maximal activity for constraint and given values of counters for infinite and huge contributions
2437 * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2438 */
2439static
2441 SCIP* scip, /**< SCIP data structure */
2442 SCIP_CONSDATA* consdata, /**< linear constraint */
2443 int posinf, /**< number of coefficients contributing pos. infinite value */
2444 int neginf, /**< number of coefficients contributing neg. infinite value */
2445 int poshuge, /**< number of coefficients contributing huge pos. value */
2446 int neghuge, /**< number of coefficients contributing huge neg. value */
2447 SCIP_Real delta, /**< value to subtract from stored maxactivity
2448 * (contribution of the variable set to zero when getting residual activity) */
2449 SCIP_Bool global, /**< should the global or local maximal activity be returned? */
2450 SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2451 SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2452 SCIP_Bool* istight, /**< pointer to store whether activity bound is tight to variable bounds
2453 * i.e. is the actual maxactivity (otherwise an upper bound is provided) */
2454 SCIP_Bool* issettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2455 )
2456{
2457 assert(scip != NULL);
2458 assert(consdata != NULL);
2459 assert(posinf >= 0);
2460 assert(neginf >= 0);
2461 assert(poshuge >= 0);
2462 assert(neghuge >= 0);
2463 assert(maxactivity != NULL);
2464 assert(istight != NULL);
2465 assert(issettoinfinity != NULL);
2466
2467 /* if we have pos. infinite contributions, the maxactivity is +infty */
2468 if( posinf > 0 )
2469 {
2470 *maxactivity = SCIPinfinity(scip);
2471 *issettoinfinity = TRUE;
2472 *istight = neginf == 0;
2473 }
2474 /* if we have neg. (and no pos.) infinite contributions, the maxactivity is -infty */
2475 else if( neginf > 0 )
2476 {
2477 *maxactivity = -SCIPinfinity(scip);
2478 *issettoinfinity = TRUE;
2479 *istight = TRUE;
2480 }
2481 /* if we have pos. huge contributions or do not need a good relaxation, we just return +infty as maxactivity */
2482 else if( poshuge > 0 || ( neghuge > 0 && !goodrelax ) )
2483 {
2484 *maxactivity = SCIPinfinity(scip);
2485 *issettoinfinity = TRUE;
2486 *istight = FALSE;
2487 }
2488 else
2489 {
2490 SCIP_Real QUAD(tmpactivity);
2491
2492 /* recompute maxactivity if it is not valid */
2493 if( global )
2494 {
2495 if( !consdata->validglbmaxact )
2497 assert(consdata->validglbmaxact);
2498
2499 QUAD_ASSIGN_Q(tmpactivity, consdata->glbmaxactivity);
2500 }
2501 else
2502 {
2503 if( !consdata->validmaxact )
2505 assert(consdata->validmaxact);
2506
2507 QUAD_ASSIGN_Q(tmpactivity, consdata->maxactivity);
2508 }
2509
2510 /* calculate residual maxactivity */
2511 SCIPquadprecSumQD(tmpactivity, tmpactivity, -delta);
2512
2513 /* we have no infinite and no pos. huge contributions, but neg. huge contributions; a feasible relaxation of the
2514 * maxactivity is given by subtracting the number of negative huge contributions times the huge value
2515 */
2516 if( neghuge > 0 )
2517 {
2518 SCIPquadprecSumQD(tmpactivity, tmpactivity, -neghuge * SCIPgetHugeValue(scip));
2519 *istight = FALSE;
2520 }
2521 /* all counters are zero, so the maxactivity is tight */
2522 else
2523 *istight = TRUE;
2524
2525 /* round residual maxactivity */
2526 *maxactivity = QUAD_TO_DBL(tmpactivity);
2527 *issettoinfinity = FALSE;
2528 }
2529}
2530
2531/** gets activity bounds for constraint */
2532static
2534 SCIP* scip, /**< SCIP data structure */
2535 SCIP_CONSDATA* consdata, /**< linear constraint */
2536 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2537 * relaxed activities ignored, anyway? */
2538 SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2539 SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2540 SCIP_Bool* ismintight, /**< pointer to store whether the minactivity bound is tight
2541 * i.e. is the actual minactivity (otherwise a lower bound is provided) */
2542 SCIP_Bool* ismaxtight, /**< pointer to store whether the maxactivity bound is tight
2543 * i.e. is the actual maxactivity (otherwise an upper bound is provided) */
2544 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minactivity was set to infinity or calculated */
2545 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2546
2547 )
2548{
2549 assert(scip != NULL);
2550 assert(consdata != NULL);
2551 assert(minactivity != NULL);
2552 assert(maxactivity != NULL);
2553 assert(isminsettoinfinity != NULL);
2554 assert(ismaxsettoinfinity != NULL);
2555
2556 if( !consdata->validactivities )
2557 {
2558 consdataCalcActivities(scip, consdata);
2559 assert(consdata->validminact);
2560 assert(consdata->validmaxact);
2561 }
2562 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2563 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2564 assert(consdata->minactivityneginf >= 0);
2565 assert(consdata->minactivityposinf >= 0);
2566 assert(consdata->maxactivityneginf >= 0);
2567 assert(consdata->maxactivityposinf >= 0);
2568
2569 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2570 consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2571 minactivity, ismintight, isminsettoinfinity);
2572
2573 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2574 consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2575 maxactivity, ismaxtight, ismaxsettoinfinity);
2576}
2577
2578/** calculates activity bounds for constraint after setting variable to zero */
2579static
2581 SCIP* scip, /**< SCIP data structure */
2582 SCIP_CONSDATA* consdata, /**< linear constraint */
2583 SCIP_VAR* cancelvar, /**< variable to calculate activity residual for */
2584 SCIP_Real* resactivity, /**< pointer to store the residual activity */
2585 SCIP_Bool isminresact, /**< should minimal or maximal residual activity be calculated? */
2586 SCIP_Bool useglobalbounds /**< should global or local bounds be used? */
2587 )
2588{
2589 SCIP_VAR* var;
2590 SCIP_Real val;
2591 SCIP_Real lb;
2592 SCIP_Real ub;
2593 int v;
2594
2595 assert(scip != NULL);
2596 assert(consdata != NULL);
2597 assert(cancelvar != NULL);
2598 assert(resactivity != NULL);
2599
2600 *resactivity = 0.0;
2601
2602 for( v = 0; v < consdata->nvars; ++v )
2603 {
2604 var = consdata->vars[v];
2605 assert(var != NULL);
2606 if( var == cancelvar )
2607 continue;
2608
2609 val = consdata->vals[v];
2610
2611 if( useglobalbounds )
2612 {
2613 lb = SCIPvarGetLbGlobal(var);
2614 ub = SCIPvarGetUbGlobal(var);
2615 }
2616 else
2617 {
2618 lb = SCIPvarGetLbLocal(var);
2619 ub = SCIPvarGetUbLocal(var);
2620 }
2621
2622 assert(!SCIPisZero(scip, val));
2623 assert(SCIPisLE(scip, lb, ub));
2624
2625 if( val > 0.0 )
2626 {
2627 if( isminresact )
2628 {
2629 assert(!SCIPisInfinity(scip, -lb));
2630 assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2631 *resactivity += val*lb;
2632 }
2633 else
2634 {
2635 assert(!SCIPisInfinity(scip, ub));
2636 assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2637 *resactivity += val*ub;
2638 }
2639 }
2640 else
2641 {
2642 if( isminresact)
2643 {
2644 assert(!SCIPisInfinity(scip, ub));
2645 assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2646 *resactivity += val*ub;
2647 }
2648 else
2649 {
2650 assert(!SCIPisInfinity(scip, -lb));
2651 assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2652 *resactivity += val*lb;
2653 }
2654 }
2655 }
2656 assert(!SCIPisInfinity(scip, *resactivity) && !SCIPisInfinity(scip, -(*resactivity)));
2657}
2658
2659/** gets activity bounds for constraint after setting variable to zero */
2660static
2662 SCIP* scip, /**< SCIP data structure */
2663 SCIP_CONSDATA* consdata, /**< linear constraint */
2664 SCIP_VAR* var, /**< variable to calculate activity residual for */
2665 SCIP_Real val, /**< coefficient value of variable in linear constraint */
2666 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2667 * relaxed acticities ignored, anyway? */
2668 SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity */
2669 SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity */
2670 SCIP_Bool* ismintight, /**< pointer to store whether the residual minactivity bound is tight
2671 * i.e. is the actual residual minactivity (otherwise a lower bound is provided) */
2672 SCIP_Bool* ismaxtight, /**< pointer to store whether the residual maxactivity bound is tight
2673 * i.e. is the actual residual maxactivity (otherwise an upper bound is provided) */
2674 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2675 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2676 )
2677{
2678 SCIP_Real minactbound;
2679 SCIP_Real maxactbound;
2680 SCIP_Real absval;
2681
2682 assert(scip != NULL);
2683 assert(consdata != NULL);
2684 assert(var != NULL);
2685 assert(minresactivity != NULL);
2686 assert(maxresactivity != NULL);
2687 assert(ismintight != NULL);
2688 assert(ismaxtight != NULL);
2689 assert(isminsettoinfinity != NULL);
2690 assert(ismaxsettoinfinity != NULL);
2691
2692 /* get activity bounds of linear constraint */
2693 if( !consdata->validactivities )
2694 {
2695 consdataCalcActivities(scip, consdata);
2696 assert(consdata->validminact);
2697 assert(consdata->validmaxact);
2698 }
2699 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2700 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2701 assert(consdata->minactivityneginf >= 0);
2702 assert(consdata->minactivityposinf >= 0);
2703 assert(consdata->maxactivityneginf >= 0);
2704 assert(consdata->maxactivityposinf >= 0);
2705 assert(consdata->minactivityneghuge >= 0);
2706 assert(consdata->minactivityposhuge >= 0);
2707 assert(consdata->maxactivityneghuge >= 0);
2708 assert(consdata->maxactivityposhuge >= 0);
2709
2710 if( val > 0.0 )
2711 {
2712 minactbound = SCIPvarGetLbLocal(var);
2713 maxactbound = SCIPvarGetUbLocal(var);
2714 absval = val;
2715 }
2716 else
2717 {
2718 minactbound = -SCIPvarGetUbLocal(var);
2719 maxactbound = -SCIPvarGetLbLocal(var);
2720 absval = -val;
2721 }
2722
2723 /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2724 * and contribution of variable set to zero that has to be subtracted from finite part of activity
2725 */
2726 if( SCIPisInfinity(scip, minactbound) )
2727 {
2728 assert(consdata->minactivityposinf >= 1);
2729
2730 getMinActivity(scip, consdata, consdata->minactivityposinf - 1, consdata->minactivityneginf,
2731 consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2732 minresactivity, ismintight, isminsettoinfinity);
2733 }
2734 else if( SCIPisInfinity(scip, -minactbound) )
2735 {
2736 assert(consdata->minactivityneginf >= 1);
2737
2738 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf - 1,
2739 consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2740 minresactivity, ismintight, isminsettoinfinity);
2741 }
2742 else if( SCIPisHugeValue(scip, minactbound * absval) )
2743 {
2744 assert(consdata->minactivityposhuge >= 1);
2745
2746 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2747 consdata->minactivityposhuge - 1, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2748 minresactivity, ismintight, isminsettoinfinity);
2749 }
2750 else if( SCIPisHugeValue(scip, -minactbound * absval) )
2751 {
2752 assert(consdata->minactivityneghuge >= 1);
2753
2754 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2755 consdata->minactivityposhuge, consdata->minactivityneghuge - 1, 0.0, FALSE, goodrelax,
2756 minresactivity, ismintight, isminsettoinfinity);
2757 }
2758 else
2759 {
2760 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2761 consdata->minactivityposhuge, consdata->minactivityneghuge, absval * minactbound, FALSE, goodrelax,
2762 minresactivity, ismintight, isminsettoinfinity);
2763 }
2764
2765 /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
2766 * and contribution of variable set to zero that has to be subtracted from finite part of activity
2767 */
2768 if( SCIPisInfinity(scip, -maxactbound) )
2769 {
2770 assert(consdata->maxactivityneginf >= 1);
2771
2772 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf - 1,
2773 consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2774 maxresactivity, ismaxtight, ismaxsettoinfinity);
2775 }
2776 else if( SCIPisInfinity(scip, maxactbound) )
2777 {
2778 assert(consdata->maxactivityposinf >= 1);
2779
2780 getMaxActivity(scip, consdata, consdata->maxactivityposinf - 1, consdata->maxactivityneginf,
2781 consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2782 maxresactivity, ismaxtight, ismaxsettoinfinity);
2783 }
2784 else if( SCIPisHugeValue(scip, absval * maxactbound) )
2785 {
2786 assert(consdata->maxactivityposhuge >= 1);
2787
2788 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2789 consdata->maxactivityposhuge - 1, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2790 maxresactivity, ismaxtight, ismaxsettoinfinity);
2791 }
2792 else if( SCIPisHugeValue(scip, -absval * maxactbound) )
2793 {
2794 assert(consdata->maxactivityneghuge >= 1);
2795
2796 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2797 consdata->maxactivityposhuge, consdata->maxactivityneghuge - 1, 0.0, FALSE, goodrelax,
2798 maxresactivity, ismaxtight, ismaxsettoinfinity);
2799 }
2800 else
2801 {
2802 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2803 consdata->maxactivityposhuge, consdata->maxactivityneghuge, absval * maxactbound, FALSE, goodrelax,
2804 maxresactivity, ismaxtight, ismaxsettoinfinity);
2805 }
2806}
2807
2808/** gets global activity bounds for constraint */
2809static
2811 SCIP* scip, /**< SCIP data structure */
2812 SCIP_CONSDATA* consdata, /**< linear constraint */
2813 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2814 * relaxed acticities ignored, anyway? */
2815 SCIP_Real* glbminactivity, /**< pointer to store the minimal activity, or NULL, if not needed */
2816 SCIP_Real* glbmaxactivity, /**< pointer to store the maximal activity, or NULL, if not needed */
2817 SCIP_Bool* ismintight, /**< pointer to store whether the minactivity bound is tight
2818 * i.e. is the actual minactivity (otherwise a lower bound is provided) */
2819 SCIP_Bool* ismaxtight, /**< pointer to store whether the maxactivity bound is tight
2820 * i.e. is the actual maxactivity (otherwise an upper bound is provided) */
2821 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2822 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2823 )
2824{
2825 assert(scip != NULL);
2826 assert(consdata != NULL);
2827 assert((glbminactivity != NULL && ismintight != NULL && isminsettoinfinity != NULL)
2828 || (glbmaxactivity != NULL && ismaxtight != NULL && ismaxsettoinfinity != NULL));
2829
2830 if( !consdata->validactivities )
2831 {
2832 consdataCalcActivities(scip, consdata);
2833 assert(consdata->validglbminact);
2834 assert(consdata->validglbmaxact);
2835 }
2836 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2837 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2838 assert(consdata->glbminactivityneginf >= 0);
2839 assert(consdata->glbminactivityposinf >= 0);
2840 assert(consdata->glbmaxactivityneginf >= 0);
2841 assert(consdata->glbmaxactivityposinf >= 0);
2842 assert(consdata->glbminactivityneghuge >= 0);
2843 assert(consdata->glbminactivityposhuge >= 0);
2844 assert(consdata->glbmaxactivityneghuge >= 0);
2845 assert(consdata->glbmaxactivityposhuge >= 0);
2846
2847 if( glbminactivity != NULL )
2848 {
2849 assert(isminsettoinfinity != NULL);
2850 assert(ismintight != NULL);
2851
2852 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2853 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2854 glbminactivity, ismintight, isminsettoinfinity);
2855 }
2856
2857 if( glbmaxactivity != NULL )
2858 {
2859 assert(ismaxsettoinfinity != NULL);
2860 assert(ismaxtight != NULL);
2861
2862 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2863 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2864 glbmaxactivity, ismaxtight, ismaxsettoinfinity);
2865 }
2866}
2867
2868/** gets global activity bounds for constraint after setting variable to zero */
2869static
2871 SCIP* scip, /**< SCIP data structure */
2872 SCIP_CONSDATA* consdata, /**< linear constraint */
2873 SCIP_VAR* var, /**< variable to calculate activity residual for */
2874 SCIP_Real val, /**< coefficient value of variable in linear constraint */
2875 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2876 * relaxed acticities ignored, anyway? */
2877 SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity, or NULL, if not needed */
2878 SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity, or NULL, if not needed */
2879 SCIP_Bool* ismintight, /**< pointer to store whether the residual minactivity bound is tight
2880 * i.e. is the actual residual minactivity (otherwise a lower bound is provided) */
2881 SCIP_Bool* ismaxtight, /**< pointer to store whether the residual maxactivity bound is tight
2882 * i.e. is the actual residual maxactivity (otherwise an upper bound is provided) */
2883 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2884 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2885 )
2886{
2887 SCIP_Real minactbound;
2888 SCIP_Real maxactbound;
2889 SCIP_Real absval;
2890
2891 assert(scip != NULL);
2892 assert(consdata != NULL);
2893 assert(var != NULL);
2894 assert((minresactivity != NULL && ismintight != NULL && isminsettoinfinity != NULL )
2895 || (maxresactivity != NULL && ismaxtight != NULL && ismaxsettoinfinity != NULL));
2896
2897 /* get activity bounds of linear constraint */
2898 if( !consdata->validactivities )
2899 consdataCalcActivities(scip, consdata);
2900
2901 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2902 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2903 assert(consdata->glbminactivityneginf >= 0);
2904 assert(consdata->glbminactivityposinf >= 0);
2905 assert(consdata->glbmaxactivityneginf >= 0);
2906 assert(consdata->glbmaxactivityposinf >= 0);
2907
2908 if( val > 0.0 )
2909 {
2910 minactbound = SCIPvarGetLbGlobal(var);
2911 maxactbound = SCIPvarGetUbGlobal(var);
2912 absval = val;
2913 }
2914 else
2915 {
2916 minactbound = -SCIPvarGetUbGlobal(var);
2917 maxactbound = -SCIPvarGetLbGlobal(var);
2918 absval = -val;
2919 }
2920
2921 if( minresactivity != NULL )
2922 {
2923 assert(isminsettoinfinity != NULL);
2924 assert(ismintight != NULL);
2925
2926 /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2927 * and contribution of variable set to zero that has to be subtracted from finite part of activity
2928 */
2929 if( SCIPisInfinity(scip, minactbound) )
2930 {
2931 assert(consdata->glbminactivityposinf >= 1);
2932
2933 getMinActivity(scip, consdata, consdata->glbminactivityposinf - 1, consdata->glbminactivityneginf,
2934 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2935 minresactivity, ismintight, isminsettoinfinity);
2936 }
2937 else if( SCIPisInfinity(scip, -minactbound) )
2938 {
2939 assert(consdata->glbminactivityneginf >= 1);
2940
2941 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf - 1,
2942 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2943 minresactivity, ismintight, isminsettoinfinity);
2944 }
2945 else if( SCIPisHugeValue(scip, minactbound * absval) )
2946 {
2947 assert(consdata->glbminactivityposhuge >= 1);
2948
2949 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2950 consdata->glbminactivityposhuge - 1, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2951 minresactivity, ismintight, isminsettoinfinity);
2952 }
2953 else if( SCIPisHugeValue(scip, -minactbound * absval) )
2954 {
2955 assert(consdata->glbminactivityneghuge >= 1);
2956
2957 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2958 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge - 1, 0.0, TRUE, goodrelax,
2959 minresactivity, ismintight, isminsettoinfinity);
2960 }
2961 else
2962 {
2963 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2964 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, absval * minactbound, TRUE,
2965 goodrelax, minresactivity, ismintight, isminsettoinfinity);
2966 }
2967 }
2968
2969 if( maxresactivity != NULL )
2970 {
2971 assert(ismaxsettoinfinity != NULL);
2972 assert(ismaxtight != NULL);
2973
2974 /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
2975 * and contribution of variable set to zero that has to be subtracted from finite part of activity
2976 */
2977 if( SCIPisInfinity(scip, -maxactbound) )
2978 {
2979 assert(consdata->glbmaxactivityneginf >= 1);
2980
2981 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf - 1,
2982 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2983 maxresactivity, ismaxtight, ismaxsettoinfinity);
2984 }
2985 else if( SCIPisInfinity(scip, maxactbound) )
2986 {
2987 assert(consdata->glbmaxactivityposinf >= 1);
2988
2989 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf - 1, consdata->glbmaxactivityneginf,
2990 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2991 maxresactivity, ismaxtight, ismaxsettoinfinity);
2992 }
2993 else if( SCIPisHugeValue(scip, absval * maxactbound) )
2994 {
2995 assert(consdata->glbmaxactivityposhuge >= 1);
2996
2997 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2998 consdata->glbmaxactivityposhuge - 1, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2999 maxresactivity, ismaxtight, ismaxsettoinfinity);
3000 }
3001 else if( SCIPisHugeValue(scip, -absval * maxactbound) )
3002 {
3003 assert(consdata->glbmaxactivityneghuge >= 1);
3004
3005 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3006 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge - 1, 0.0, TRUE, goodrelax,
3007 maxresactivity, ismaxtight, ismaxsettoinfinity);
3008 }
3009 else
3010 {
3011 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3012 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, absval * maxactbound, TRUE,
3013 goodrelax, maxresactivity, ismaxtight, ismaxsettoinfinity);
3014 }
3015 }
3016}
3017
3018/** calculates the activity of the linear constraint for given solution */
3019static
3021 SCIP* scip, /**< SCIP data structure */
3022 SCIP_CONSDATA* consdata, /**< linear constraint data */
3023 SCIP_SOL* sol /**< solution to get activity for, NULL to current solution */
3024 )
3025{
3026 SCIP_Real activity;
3027
3028 assert(scip != NULL);
3029 assert(consdata != NULL);
3030
3031 if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
3032 activity = consdataComputePseudoActivity(scip, consdata);
3033 else
3034 {
3035 SCIP_Real solval;
3036 int nposinf;
3037 int nneginf;
3038 SCIP_Bool negsign;
3039 int v;
3040
3041 activity = 0.0;
3042 nposinf = 0;
3043 nneginf = 0;
3044
3045 for( v = 0; v < consdata->nvars; ++v )
3046 {
3047 solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
3048
3049 assert(!SCIPisZero(scip, consdata->vals[v]));
3050 negsign = consdata->vals[v] < 0.0;
3051
3052 if( (SCIPisInfinity(scip, solval) && !negsign) || (SCIPisInfinity(scip, -solval) && negsign) )
3053 ++nposinf;
3054 else if( (SCIPisInfinity(scip, solval) && negsign) || (SCIPisInfinity(scip, -solval) && !negsign) )
3055 ++nneginf;
3056 else
3057 activity += consdata->vals[v] * solval;
3058 }
3059 assert(nneginf >= 0 && nposinf >= 0);
3060
3061 SCIPdebugMsg(scip, "activity of linear constraint: %.15g, %d positive infinity values, %d negative infinity values \n", activity, nposinf, nneginf);
3062
3063 /* invalidate activity for contradicting contributions */
3064 if( nposinf > 0 && nneginf > 0 )
3065 activity = SCIP_INVALID;
3066 else if( nneginf > 0 )
3067 activity = -SCIPinfinity(scip);
3068 else if( nposinf > 0 )
3069 activity = SCIPinfinity(scip);
3070
3071 SCIPdebugMsg(scip, "corrected activity of linear constraint: %.15g\n", activity);
3072 }
3073
3074 if( activity == SCIP_INVALID ) /*lint !e777*/
3075 return activity;
3076 else if( activity < 0 )
3077 activity = MAX(activity, -SCIPinfinity(scip)); /*lint !e666*/
3078 else
3079 activity = MIN(activity, SCIPinfinity(scip)); /*lint !e666*/
3080
3081 return activity;
3082}
3083
3084/** calculates the feasibility of the linear constraint for given solution */
3085static
3087 SCIP* scip, /**< SCIP data structure */
3088 SCIP_CONSDATA* consdata, /**< linear constraint data */
3089 SCIP_SOL* sol /**< solution to get feasibility for, NULL to current solution */
3090 )
3091{
3092 SCIP_Real activity;
3093
3094 assert(scip != NULL);
3095 assert(consdata != NULL);
3096
3097 activity = consdataGetActivity(scip, consdata, sol);
3098
3099 if( activity == SCIP_INVALID ) /*lint !e777*/
3100 return -SCIPinfinity(scip);
3101
3102 return MIN(consdata->rhs - activity, activity - consdata->lhs);
3103}
3104
3105/** updates bit signatures after adding a single coefficient */
3106static
3108 SCIP_CONSDATA* consdata, /**< linear constraint data */
3109 int pos /**< position of coefficient to update signatures for */
3110 )
3111{
3112 uint64_t varsignature;
3113 SCIP_Real lb;
3114 SCIP_Real ub;
3115 SCIP_Real val;
3116
3117 assert(consdata != NULL);
3118 assert(consdata->validsignature);
3119
3120 varsignature = SCIPhashSignature64(SCIPvarGetIndex(consdata->vars[pos]));
3121 lb = SCIPvarGetLbGlobal(consdata->vars[pos]);
3122 ub = SCIPvarGetUbGlobal(consdata->vars[pos]);
3123 val = consdata->vals[pos];
3124 if( (val > 0.0 && ub > 0.0) || (val < 0.0 && lb < 0.0) )
3125 consdata->possignature |= varsignature;
3126 if( (val > 0.0 && lb < 0.0) || (val < 0.0 && ub > 0.0) )
3127 consdata->negsignature |= varsignature;
3128}
3129
3130/** calculates the bit signatures of the given constraint data */
3131static
3133 SCIP_CONSDATA* consdata /**< linear constraint data */
3134 )
3135{
3136 assert(consdata != NULL);
3137
3138 if( !consdata->validsignature )
3139 {
3140 int i;
3141
3142 consdata->validsignature = TRUE;
3143 consdata->possignature = 0;
3144 consdata->negsignature = 0;
3145 for( i = 0; i < consdata->nvars; ++i )
3146 consdataUpdateSignatures(consdata, i);
3147 }
3148}
3149
3150/** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3151static
3153{ /*lint --e{715}*/
3154 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3155 SCIP_VAR* var1;
3156 SCIP_VAR* var2;
3157
3158 assert(consdata != NULL);
3159 assert(0 <= ind1 && ind1 < consdata->nvars);
3160 assert(0 <= ind2 && ind2 < consdata->nvars);
3161
3162 var1 = consdata->vars[ind1];
3163 var2 = consdata->vars[ind2];
3164
3165 /* exactly one variable is binary */
3166 if( SCIPvarIsBinary(var1) != SCIPvarIsBinary(var2) )
3167 {
3168 return (SCIPvarIsBinary(var1) ? -1 : +1);
3169 }
3170 /* both variables are binary */
3171 else if( SCIPvarIsBinary(var1) )
3172 {
3173 return SCIPvarCompare(var1, var2);
3174 }
3175 else
3176 {
3179
3180 if( vartype1 < vartype2 )
3181 return -1;
3182 else if( vartype1 > vartype2 )
3183 return +1;
3184 else
3185 return SCIPvarCompare(var1, var2);
3186 }
3187}
3188
3189/** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3190static
3191SCIP_DECL_SORTINDCOMP(consdataCompVarProp)
3192{ /*lint --e{715}*/
3193 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3194 SCIP_VAR* var1;
3195 SCIP_VAR* var2;
3196
3197 assert(consdata != NULL);
3198 assert(0 <= ind1 && ind1 < consdata->nvars);
3199 assert(0 <= ind2 && ind2 < consdata->nvars);
3200
3201 var1 = consdata->vars[ind1];
3202 var2 = consdata->vars[ind2];
3203
3204 /* exactly one variable is binary */
3205 if( SCIPvarIsBinary(var1) != SCIPvarIsBinary(var2) )
3206 {
3207 return (SCIPvarIsBinary(var1) ? -1 : +1);
3208 }
3209 /* both variables are binary */
3210 else if( SCIPvarIsBinary(var1) )
3211 {
3212 SCIP_Real abscoef1 = REALABS(consdata->vals[ind1]);
3213 SCIP_Real abscoef2 = REALABS(consdata->vals[ind2]);
3214
3215 if( EPSGT(abscoef1, abscoef2, 1e-9) )
3216 return -1;
3217 else if( EPSGT(abscoef2, abscoef1, 1e-9) )
3218 return +1;
3219 else
3220 return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3221 }
3222 else
3223 {
3226
3227 if( vartype1 < vartype2 )
3228 {
3229 return -1;
3230 }
3231 else if( vartype1 > vartype2 )
3232 {
3233 return +1;
3234 }
3235 else
3236 {
3237 /* both variables are continuous */
3238 if( !SCIPvarIsIntegral(var1) )
3239 {
3240 assert(!SCIPvarIsIntegral(var2));
3241 return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3242 }
3243 else
3244 {
3245 SCIP_Real abscont1 = REALABS(consdata->vals[ind1] * (SCIPvarGetUbGlobal(var1) - SCIPvarGetLbGlobal(var1)));
3246 SCIP_Real abscont2 = REALABS(consdata->vals[ind2] * (SCIPvarGetUbGlobal(var2) - SCIPvarGetLbGlobal(var2)));
3247
3248 if( EPSGT(abscont1, abscont2, 1e-9) )
3249 return -1;
3250 else if( EPSGT(abscont2, abscont1, 1e-9) )
3251 return +1;
3252 else
3253 return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3254 }
3255 }
3256 }
3257}
3258
3259/** permutes the constraint's variables according to a given permutation. */
3260static
3262 SCIP_CONSDATA* consdata, /**< the constraint data */
3263 int* perm, /**< the target permutation */
3264 int nvars /**< the number of variables */
3265 )
3266{ /*lint --e{715}*/
3267 SCIP_VAR* varv;
3268 SCIP_EVENTDATA* eventdatav;
3269 SCIP_Real valv;
3270 int v;
3271 int i;
3272 int nexti;
3273
3274 assert(perm != NULL);
3275 assert(consdata != NULL);
3276
3277 /* permute the variables in the linear constraint according to the target permutation */
3278 eventdatav = NULL;
3279 for( v = 0; v < nvars; ++v )
3280 {
3281 if( perm[v] != v )
3282 {
3283 varv = consdata->vars[v];
3284 valv = consdata->vals[v];
3285 if( consdata->eventdata != NULL )
3286 eventdatav = consdata->eventdata[v];
3287 i = v;
3288 do
3289 {
3290 assert(0 <= perm[i] && perm[i] < nvars);
3291 assert(perm[i] != i);
3292 consdata->vars[i] = consdata->vars[perm[i]];
3293 consdata->vals[i] = consdata->vals[perm[i]];
3294 if( consdata->eventdata != NULL )
3295 {
3296 consdata->eventdata[i] = consdata->eventdata[perm[i]];
3297 consdata->eventdata[i]->varpos = i;
3298 }
3299 nexti = perm[i];
3300 perm[i] = i;
3301 i = nexti;
3302 }
3303 while( perm[i] != v );
3304 consdata->vars[i] = varv;
3305 consdata->vals[i] = valv;
3306 if( consdata->eventdata != NULL )
3307 {
3308 consdata->eventdata[i] = eventdatav;
3309 consdata->eventdata[i]->varpos = i;
3310 }
3311 perm[i] = i;
3312 }
3313 }
3314#ifdef SCIP_DEBUG
3315 /* check sorting */
3316 for( v = 0; v < nvars; ++v )
3317 {
3318 assert(perm[v] == v);
3319 assert(consdata->eventdata == NULL || consdata->eventdata[v]->varpos == v);
3320 }
3321#endif
3322}
3323
3324/** sorts linear constraint's variables depending on the stage of the solving process:
3325 * - during PRESOLVING
3326 * sorts variables by binary, integer, implied integral, and continuous variables,
3327 * and the variables of the same type by non-decreasing variable index
3328 *
3329 * - during SOLVING
3330 * sorts variables of the remaining problem by binary, integer, implied integral, and continuous variables,
3331 * and binary and integer variables by their global max activity delta (within each group),
3332 * ties within a group are broken by problem index of the variable.
3333 *
3334 * This fastens the propagation time of the constraint handler.
3335 */
3336static
3338 SCIP* scip, /**< SCIP data structure */
3339 SCIP_CONSDATA* consdata /**< linear constraint data */
3340 )
3341{
3342 assert(scip != NULL);
3343 assert(consdata != NULL);
3344
3345 /* check if there are variables for sorting */
3346 if( consdata->nvars <= 1 )
3347 {
3348 consdata->indexsorted = TRUE;
3349 consdata->coefsorted = TRUE;
3350 consdata->nbinvars = (consdata->nvars == 1 ? (int)SCIPvarIsBinary(consdata->vars[0]) : 0);
3351 }
3352 else if( (!consdata->indexsorted && SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE)
3353 || (!consdata->coefsorted && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE) )
3354 {
3355 int* perm;
3356 int v;
3357
3358 /* get temporary memory to store the sorted permutation */
3359 SCIP_CALL( SCIPallocBufferArray(scip, &perm, consdata->nvars) );
3360
3361 /* call sorting method */
3363 SCIPsort(perm, consdataCompVar, (void*)consdata, consdata->nvars);
3364 else
3365 SCIPsort(perm, consdataCompVarProp, (void*)consdata, consdata->nvars);
3366
3367 permSortConsdata(consdata, perm, consdata->nvars);
3368
3369 /* free temporary memory */
3370 SCIPfreeBufferArray(scip, &perm);
3371
3373 {
3374 consdata->indexsorted = FALSE;
3375 consdata->coefsorted = TRUE;
3376
3377 /* count binary variables in the sorted vars array */
3378 consdata->nbinvars = 0;
3379 for( v = 0; v < consdata->nvars; ++v )
3380 {
3381 if( SCIPvarIsBinary(consdata->vars[v]) )
3382 ++consdata->nbinvars;
3383 else
3384 break;
3385 }
3386 }
3387 else
3388 {
3389 consdata->indexsorted = TRUE;
3390 consdata->coefsorted = FALSE;
3391 }
3392 }
3393
3394 return SCIP_OKAY;
3395}
3396
3397
3398/*
3399 * local linear constraint handler methods
3400 */
3401
3402/** sets left hand side of linear constraint */
3403static
3405 SCIP* scip, /**< SCIP data structure */
3406 SCIP_CONS* cons, /**< linear constraint */
3407 SCIP_Real lhs /**< new left hand side */
3408 )
3409{
3410 SCIP_CONSDATA* consdata;
3411 SCIP_Bool locked;
3412 int i;
3413
3414 assert(scip != NULL);
3415 assert(cons != NULL);
3416
3417 /* adjust value to be not beyond infinity */
3418 if( SCIPisInfinity(scip, -lhs) )
3419 lhs = -SCIPinfinity(scip);
3420 else if( SCIPisInfinity(scip, lhs) )
3421 lhs = SCIPinfinity(scip);
3422
3423 consdata = SCIPconsGetData(cons);
3424 assert(consdata != NULL);
3425 assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3426
3427 /* check whether the side is not changed */
3428 if( SCIPisEQ(scip, consdata->lhs, lhs) )
3429 return SCIP_OKAY;
3430
3431 assert(!SCIPisInfinity(scip, ABS(consdata->lhs)) || !SCIPisInfinity(scip, ABS(lhs)));
3432
3433 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3434 if( SCIPisEQ(scip, lhs, consdata->rhs) )
3435 {
3436 consdata->rhs = lhs;
3437 assert(consdata->row == NULL);
3438 }
3439
3440 locked = FALSE;
3441 for( i = 0; i < NLOCKTYPES && !locked; i++ )
3442 locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3443
3444 /* if necessary, update the rounding locks of variables */
3445 if( locked )
3446 {
3447 if( SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, -lhs) )
3448 {
3449 SCIP_VAR** vars;
3450 SCIP_Real* vals;
3451 int v;
3452
3453 /* the left hand side switched from -infinity to a non-infinite value -> install rounding locks */
3454 vars = consdata->vars;
3455 vals = consdata->vals;
3456
3457 for( v = 0; v < consdata->nvars; ++v )
3458 {
3459 assert(vars[v] != NULL);
3460 assert(!SCIPisZero(scip, vals[v]));
3461
3462 if( SCIPisPositive(scip, vals[v]) )
3463 {
3464 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3465 }
3466 else
3467 {
3468 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3469 }
3470 }
3471 }
3472 else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -lhs) )
3473 {
3474 SCIP_VAR** vars;
3475 SCIP_Real* vals;
3476 int v;
3477
3478 /* the left hand side switched from a non-infinite value to -infinity -> remove rounding locks */
3479 vars = consdata->vars;
3480 vals = consdata->vals;
3481
3482 for( v = 0; v < consdata->nvars; ++v )
3483 {
3484 assert(vars[v] != NULL);
3485 assert(!SCIPisZero(scip, vals[v]));
3486
3487 if( SCIPisPositive(scip, vals[v]) )
3488 {
3490 }
3491 else
3492 {
3494 }
3495 }
3496 }
3497 }
3498
3499 /* 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 */
3500 if( !SCIPisInfinity(scip, ABS(lhs)) && SCIPisGT(scip, lhs, consdata->lhs) )
3501 {
3502 consdata->boundstightened = 0;
3503 consdata->presolved = FALSE;
3504 consdata->cliquesadded = FALSE;
3505 consdata->implsadded = FALSE;
3506
3507 /* mark the constraint for propagation */
3508 if( SCIPconsIsTransformed(cons) )
3509 {
3511 }
3512 }
3513
3514 /* set new left hand side and update constraint data */
3515 consdata->lhs = lhs;
3516 consdata->changed = TRUE;
3517 consdata->normalized = FALSE;
3518 consdata->upgradetried = FALSE;
3519 consdata->rangedrowpropagated = 0;
3520
3521 /* update the lhs of the LP row */
3522 if( consdata->row != NULL )
3523 {
3524 SCIP_CALL( SCIPchgRowLhs(scip, consdata->row, lhs) );
3525 }
3526
3527 return SCIP_OKAY;
3528}
3529
3530/** sets right hand side of linear constraint */
3531static
3533 SCIP* scip, /**< SCIP data structure */
3534 SCIP_CONS* cons, /**< linear constraint */
3535 SCIP_Real rhs /**< new right hand side */
3536 )
3537{
3538 SCIP_CONSDATA* consdata;
3539 SCIP_Bool locked;
3540 int i;
3541
3542 assert(scip != NULL);
3543 assert(cons != NULL);
3544
3545 /* adjust value to be not beyond infinity */
3546 if( SCIPisInfinity(scip, rhs) )
3547 rhs = SCIPinfinity(scip);
3548 else if( SCIPisInfinity(scip, -rhs) )
3549 rhs = -SCIPinfinity(scip);
3550
3551 consdata = SCIPconsGetData(cons);
3552 assert(consdata != NULL);
3553 assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3554
3555 /* check whether the side is not changed */
3556 if( SCIPisEQ(scip, consdata->rhs, rhs) )
3557 return SCIP_OKAY;
3558
3559 assert(!SCIPisInfinity(scip, ABS(consdata->rhs)) || !SCIPisInfinity(scip, ABS(rhs)));
3560
3561 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3562 if( SCIPisEQ(scip, rhs, consdata->lhs) )
3563 {
3564 consdata->lhs = rhs;
3565 assert(consdata->row == NULL);
3566 }
3567
3568 locked = FALSE;
3569 for( i = 0; i < NLOCKTYPES && !locked; i++ )
3570 locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3571
3572 /* if necessary, update the rounding locks of variables */
3573 if( locked )
3574 {
3576
3577 if( SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, rhs) )
3578 {
3579 SCIP_VAR** vars;
3580 SCIP_Real* vals;
3581 int v;
3582
3583 /* the right hand side switched from infinity to a non-infinite value -> install rounding locks */
3584 vars = consdata->vars;
3585 vals = consdata->vals;
3586
3587 for( v = 0; v < consdata->nvars; ++v )
3588 {
3589 assert(vars[v] != NULL);
3590 assert(!SCIPisZero(scip, vals[v]));
3591
3592 if( SCIPisPositive(scip, vals[v]) )
3593 {
3594 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3595 }
3596 else
3597 {
3598 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3599 }
3600 }
3601 }
3602 else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, rhs) )
3603 {
3604 SCIP_VAR** vars;
3605 SCIP_Real* vals;
3606 int v;
3607
3608 /* the right hand side switched from a non-infinite value to infinity -> remove rounding locks */
3609 vars = consdata->vars;
3610 vals = consdata->vals;
3611
3612 for( v = 0; v < consdata->nvars; ++v )
3613 {
3614 assert(vars[v] != NULL);
3615 assert(!SCIPisZero(scip, vals[v]));
3616
3617 if( SCIPisPositive(scip, vals[v]) )
3618 {
3620 }
3621 else
3622 {
3624 }
3625 }
3626 }
3627 }
3628
3629 /* 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 */
3630 if( !SCIPisInfinity(scip, ABS(rhs)) && SCIPisLT(scip, rhs, consdata->rhs) )
3631 {
3632 consdata->boundstightened = 0;
3633 consdata->presolved = FALSE;
3634 consdata->cliquesadded = FALSE;
3635 consdata->implsadded = FALSE;
3636
3637 /* mark the constraint for propagation */
3638 if( SCIPconsIsTransformed(cons) )
3639 {
3641 }
3642 }
3643
3644 /* set new right hand side and update constraint data */
3645 consdata->rhs = rhs;
3646 consdata->changed = TRUE;
3647 consdata->normalized = FALSE;
3648 consdata->upgradetried = FALSE;
3649 consdata->rangedrowpropagated = 0;
3650
3651 /* update the rhs of the LP row */
3652 if( consdata->row != NULL )
3653 {
3654 SCIP_CALL( SCIPchgRowRhs(scip, consdata->row, rhs) );
3655 }
3656
3657 return SCIP_OKAY;
3658}
3659
3660/** adds coefficient in linear constraint */
3661static
3663 SCIP* scip, /**< SCIP data structure */
3664 SCIP_CONS* cons, /**< linear constraint */
3665 SCIP_VAR* var, /**< variable of constraint entry */
3666 SCIP_Real val /**< coefficient of constraint entry */
3667 )
3668{
3669 SCIP_CONSDATA* consdata;
3670 SCIP_Bool transformed;
3671
3672 assert(scip != NULL);
3673 assert(cons != NULL);
3674 assert(var != NULL);
3675
3676 /* relaxation-only variables must not be used in checked or enforced constraints */
3678 consdata = SCIPconsGetData(cons);
3679 assert(consdata != NULL);
3680
3681 /* are we in the transformed problem? */
3682 transformed = SCIPconsIsTransformed(cons);
3683
3684 /* always use transformed variables in transformed constraints */
3685 if( transformed )
3686 {
3688 }
3689 assert(var != NULL);
3690 assert(transformed == SCIPvarIsTransformed(var));
3691
3692 SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
3693 consdata->vars[consdata->nvars] = var;
3694 consdata->vals[consdata->nvars] = val;
3695 consdata->nvars++;
3696
3697 /* capture variable */
3699
3700 /* if we are in transformed problem, the variable needs an additional event data */
3701 if( transformed )
3702 {
3703 if( consdata->eventdata != NULL )
3704 {
3705 SCIP_CONSHDLR* conshdlr;
3706 SCIP_CONSHDLRDATA* conshdlrdata;
3707
3708 /* check for event handler */
3709 conshdlr = SCIPconsGetHdlr(cons);
3710 conshdlrdata = SCIPconshdlrGetData(conshdlr);
3711 assert(conshdlrdata != NULL);
3712 assert(conshdlrdata->eventhdlr != NULL);
3713
3714 /* initialize eventdata array */
3715 consdata->eventdata[consdata->nvars-1] = NULL;
3716
3717 /* catch bound change events of variable */
3718 SCIP_CALL( consCatchEvent(scip, cons, conshdlrdata->eventhdlr, consdata->nvars-1) );
3719 }
3720
3721 /* update minimum and maximum activities */
3722 if( !SCIPisZero(scip, val) )
3723 consdataUpdateAddCoef(scip, consdata, var, val, FALSE);
3724 }
3725
3726 /* install rounding locks for new variable with non-zero coefficient */
3727 if( !SCIPisZero(scip, val) )
3728 {
3729 SCIP_CALL( lockRounding(scip, cons, var, val) );
3730 }
3731
3732 /* mark the constraint for propagation */
3733 if( transformed )
3734 {
3736 }
3737
3738 consdata->boundstightened = 0;
3739 consdata->presolved = FALSE;
3740 consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(var);
3741
3742 if( consdata->validsignature )
3743 consdataUpdateSignatures(consdata, consdata->nvars-1);
3744
3745 consdata->changed = TRUE;
3746 consdata->normalized = FALSE;
3747 consdata->upgradetried = FALSE;
3748 consdata->cliquesadded = FALSE;
3749 consdata->implsadded = FALSE;
3750 consdata->rangedrowpropagated = 0;
3751 consdata->merged = FALSE;
3752
3753 if( consdata->nvars == 1 )
3754 {
3755 consdata->indexsorted = TRUE;
3756 consdata->coefsorted = TRUE;
3757 }
3758 else
3759 {
3761 {
3762 consdata->indexsorted = consdata->indexsorted && (consdataCompVar((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0);
3763 consdata->coefsorted = FALSE;
3764 }
3765 else
3766 {
3767 consdata->indexsorted = FALSE;
3768 consdata->coefsorted = consdata->coefsorted && (consdataCompVarProp((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0);
3769 }
3770 }
3771
3772 /* update hascontvar and hasnonbinvar flags */
3773 if( consdata->hasnonbinvalid && !consdata->hascontvar )
3774 {
3775 if( !SCIPvarIsBinary(var) )
3776 {
3777 consdata->hasnonbinvar = TRUE;
3778
3779 if( !SCIPvarIsIntegral(var) )
3780 consdata->hascontvar = TRUE;
3781 }
3782 }
3783
3784 /* add the new coefficient to the LP row */
3785 if( consdata->row != NULL )
3786 {
3787 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, val) );
3788 }
3789
3790 return SCIP_OKAY;
3791}
3792
3793/** deletes coefficient at given position from linear constraint data */
3794static
3796 SCIP* scip, /**< SCIP data structure */
3797 SCIP_CONS* cons, /**< linear constraint */
3798 int pos /**< position of coefficient to delete */
3799 )
3800{
3801 SCIP_CONSDATA* consdata;
3802 SCIP_VAR* var;
3803 SCIP_Real val;
3804
3805 assert(scip != NULL);
3806 assert(cons != NULL);
3807
3808 consdata = SCIPconsGetData(cons);
3809 assert(consdata != NULL);
3810 assert(0 <= pos && pos < consdata->nvars);
3811
3812 var = consdata->vars[pos];
3813 val = consdata->vals[pos];
3814 assert(var != NULL);
3815
3816 /* remove rounding locks for deleted variable with non-zero coefficient */
3817 if( !SCIPisZero(scip, val) )
3818 {
3819 SCIP_CALL( unlockRounding(scip, cons, var, val) );
3820 }
3821
3822 /* if we are in transformed problem, delete the event data of the variable */
3823 if( SCIPconsIsTransformed(cons) )
3824 {
3825 SCIP_CONSHDLR* conshdlr;
3826 SCIP_CONSHDLRDATA* conshdlrdata;
3827
3828 /* check for event handler */
3829 conshdlr = SCIPconsGetHdlr(cons);
3830 conshdlrdata = SCIPconshdlrGetData(conshdlr);
3831 assert(conshdlrdata != NULL);
3832 assert(conshdlrdata->eventhdlr != NULL);
3833
3834 /* drop bound change events of variable */
3835 if( consdata->eventdata != NULL )
3836 {
3837 SCIP_CALL( consDropEvent(scip, cons, conshdlrdata->eventhdlr, pos) );
3838 assert(consdata->eventdata[pos] == NULL);
3839 }
3840 }
3841
3842 /* move the last variable to the free slot */
3843 if( pos != consdata->nvars - 1 )
3844 {
3845 consdata->vars[pos] = consdata->vars[consdata->nvars-1];
3846 consdata->vals[pos] = consdata->vals[consdata->nvars-1];
3847
3848 if( consdata->eventdata != NULL )
3849 {
3850 consdata->eventdata[pos] = consdata->eventdata[consdata->nvars-1];
3851 assert(consdata->eventdata[pos] != NULL);
3852 consdata->eventdata[pos]->varpos = pos;
3853 }
3854
3855 consdata->indexsorted = consdata->indexsorted && (pos + 2 >= consdata->nvars);
3856 consdata->coefsorted = consdata->coefsorted && (pos + 2 >= consdata->nvars);
3857 }
3858 consdata->nvars--;
3859
3860 /* if at most one variable is left, the activities should be recalculated (to correspond exactly to the bounds
3861 * of the remaining variable, or give exactly 0.0)
3862 */
3863 if( consdata->nvars <= 1 )
3865 else
3866 {
3867 /* if we are in transformed problem, update minimum and maximum activities */
3868 if( SCIPconsIsTransformed(cons) && !SCIPisZero(scip, val) )
3869 consdataUpdateDelCoef(scip, consdata, var, val, TRUE);
3870 }
3871
3872 /* mark the constraint for propagation */
3873 if( SCIPconsIsTransformed(cons) )
3874 {
3876 }
3877
3878 consdata->boundstightened = 0;
3879 consdata->presolved = FALSE;
3880 consdata->validsignature = FALSE;
3881 consdata->changed = TRUE;
3882 consdata->normalized = FALSE;
3883 consdata->upgradetried = FALSE;
3884 consdata->cliquesadded = FALSE;
3885 consdata->implsadded = FALSE;
3886 consdata->rangedrowpropagated = 0;
3887
3888 /* check if hasnonbinvar flag might be incorrect now */
3889 if( consdata->hasnonbinvar && !SCIPvarIsBinary(var) )
3890 {
3891 consdata->hasnonbinvalid = FALSE;
3892 }
3893
3894 /* delete coefficient from the LP row */
3895 if( consdata->row != NULL )
3896 {
3897 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, -val) );
3898 }
3899
3900 /* release variable */
3902
3903 return SCIP_OKAY;
3904}
3905
3906/** changes coefficient value at given position of linear constraint data */
3907static
3909 SCIP* scip, /**< SCIP data structure */
3910 SCIP_CONS* cons, /**< linear constraint */
3911 int pos, /**< position of coefficient to delete */
3912 SCIP_Real newval /**< new value of coefficient */
3913 )
3914{
3915 SCIP_CONSDATA* consdata;
3916 SCIP_VAR* var;
3917 SCIP_Real val;
3918 SCIP_Bool locked;
3919 int i;
3920
3921 assert(scip != NULL);
3922 assert(cons != NULL);
3923 consdata = SCIPconsGetData(cons);
3924 assert(consdata != NULL);
3925 assert(0 <= pos && pos < consdata->nvars);
3926 var = consdata->vars[pos];
3927 assert(var != NULL);
3929 val = consdata->vals[pos];
3930 assert(!SCIPisZero(scip, val) || !SCIPisZero(scip, newval));
3931
3932 locked = FALSE;
3933 for( i = 0; i < NLOCKTYPES && !locked; i++ )
3934 locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3935
3936 /* if necessary, update the rounding locks of the variable */
3937 if( locked && ( !SCIPisNegative(scip, val) || !SCIPisNegative(scip, newval) )
3938 && ( !SCIPisPositive(scip, val) || !SCIPisPositive(scip, newval) ) )
3939 {
3941
3942 /* remove rounding locks for variable with old non-zero coefficient */
3943 if( !SCIPisZero(scip, val) )
3944 {
3945 SCIP_CALL( unlockRounding(scip, cons, var, val) );
3946 }
3947
3948 /* install rounding locks for variable with new non-zero coefficient */
3949 if( !SCIPisZero(scip, newval) )
3950 {
3951 SCIP_CALL( lockRounding(scip, cons, var, newval) );
3952 }
3953 }
3954
3955 /* change the value */
3956 consdata->vals[pos] = newval;
3957
3958 if( consdata->coefsorted )
3959 {
3960 if( pos > 0 )
3961 consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos - 1, pos) <= 0);
3962 if( consdata->coefsorted && pos < consdata->nvars - 1 )
3963 consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos, pos + 1) <= 0);
3964 }
3965
3966 /* update minimum and maximum activities */
3967 if( SCIPconsIsTransformed(cons) )
3968 {
3969 if( SCIPisZero(scip, val) )
3970 consdataUpdateAddCoef(scip, consdata, var, newval, TRUE);
3971 else if( SCIPisZero(scip, newval) )
3972 consdataUpdateDelCoef(scip, consdata, var, val, TRUE);
3973 else
3974 consdataUpdateChgCoef(scip, consdata, var, val, newval, TRUE);
3975 }
3976
3977 /* mark the constraint for propagation */
3978 if( SCIPconsIsTransformed(cons) )
3979 {
3981 }
3982
3983 consdata->boundstightened = 0;
3984 consdata->presolved = FALSE;
3985 consdata->validsignature = consdata->validsignature && (newval * val > 0.0);
3986 consdata->changed = TRUE;
3987 consdata->normalized = FALSE;
3988 consdata->upgradetried = FALSE;
3989 consdata->cliquesadded = FALSE;
3990 consdata->implsadded = FALSE;
3991 consdata->rangedrowpropagated = 0;
3992
3993 return SCIP_OKAY;
3994}
3995
3996/** scales a linear constraint with a constant scalar */
3997static
3999 SCIP* scip, /**< SCIP data structure */
4000 SCIP_CONS* cons, /**< linear constraint to scale */
4001 SCIP_Real scalar /**< value to scale constraint with */
4002 )
4003{
4004 SCIP_CONSDATA* consdata;
4005 SCIP_Real newval;
4006 SCIP_Real absscalar;
4007 int i;
4008
4009 assert(scip != NULL);
4010 assert(cons != NULL);
4011
4012 consdata = SCIPconsGetData(cons);
4013 assert(consdata != NULL);
4014 assert(consdata->row == NULL);
4015 assert(scalar != 1.0);
4016
4017 if( (!SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -consdata->lhs * scalar))
4018 || (!SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, consdata->rhs * scalar)) )
4019 {
4020 SCIPwarningMessage(scip, "skipped scaling for linear constraint <%s> to avoid numerical troubles (scalar: %.15g)\n",
4021 SCIPconsGetName(cons), scalar);
4022
4023 return SCIP_OKAY;
4024 }
4025
4026 /* scale the coefficients */
4027 for( i = consdata->nvars - 1; i >= 0; --i )
4028 {
4029 newval = scalar * consdata->vals[i];
4030
4031 /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4032 * flooring down our new value
4033 */
4034 if( SCIPisScalingIntegral(scip, consdata->vals[i], scalar) )
4035 newval = SCIPfeasFloor(scip, newval + 0.5);
4036
4037 if( SCIPisZero(scip, newval) )
4038 {
4039 SCIPwarningMessage(scip, "coefficient %.15g of variable <%s> in linear constraint <%s> scaled to zero (scalar: %.15g)\n",
4040 consdata->vals[i], SCIPvarGetName(consdata->vars[i]), SCIPconsGetName(cons), scalar);
4041 SCIP_CALL( delCoefPos(scip, cons, i) );
4042 }
4043 else
4044 consdata->vals[i] = newval;
4045 }
4046
4047 /* scale the sides */
4048 if( scalar < 0.0 )
4049 {
4050 SCIP_Real lhs;
4051
4052 lhs = consdata->lhs;
4053 consdata->lhs = -consdata->rhs;
4054 consdata->rhs = -lhs;
4055 }
4056 absscalar = REALABS(scalar);
4057 if( !SCIPisInfinity(scip, -consdata->lhs) )
4058 {
4059 newval = absscalar * consdata->lhs;
4060
4061 /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4062 * flooring down our new value
4063 */
4064 if( SCIPisScalingIntegral(scip, consdata->lhs, absscalar) )
4065 consdata->lhs = SCIPfeasFloor(scip, newval + 0.5);
4066 else
4067 consdata->lhs = newval;
4068 }
4069 if( !SCIPisInfinity(scip, consdata->rhs) )
4070 {
4071 newval = absscalar * consdata->rhs;
4072
4073 /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasCeil, we subtract 0.5 before ceiling up
4074 * our new value
4075 */
4076 if( SCIPisScalingIntegral(scip, consdata->rhs, absscalar) )
4077 consdata->rhs = SCIPfeasCeil(scip, newval - 0.5);
4078 else
4079 consdata->rhs = newval;
4080 }
4081
4083 consdata->cliquesadded = FALSE;
4084 consdata->implsadded = FALSE;
4085
4086 return SCIP_OKAY;
4087}
4088
4089/** perform deletion of variables in all constraints of the constraint handler */
4090static
4092 SCIP* scip, /**< SCIP data structure */
4093 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4094 SCIP_CONS** conss, /**< array of constraints */
4095 int nconss /**< number of constraints */
4096 )
4097{
4098 SCIP_CONSDATA* consdata;
4099 int i;
4100 int v;
4101
4102 assert(scip != NULL);
4103 assert(conshdlr != NULL);
4104 assert(conss != NULL);
4105 assert(nconss >= 0);
4106
4108
4109 /* iterate over all constraints */
4110 for( i = 0; i < nconss; i++ )
4111 {
4112 consdata = SCIPconsGetData(conss[i]);
4113
4114 /* constraint is marked, that some of its variables were deleted */
4115 if( consdata->varsdeleted )
4116 {
4117 /* iterate over all variables of the constraint and delete them from the constraint */
4118 for( v = consdata->nvars - 1; v >= 0; --v )
4119 {
4120 if( SCIPvarIsDeleted(consdata->vars[v]) )
4121 {
4122 SCIP_CALL( delCoefPos(scip, conss[i], v) );
4123 }
4124 }
4125 consdata->varsdeleted = FALSE;
4126 }
4127 }
4128
4129 return SCIP_OKAY;
4130}
4131
4132
4133/** normalizes a linear constraint with the following rules:
4134 * - if all coefficients have them same absolute value, change them to (-)1.0
4135 * - multiplication with +1 or -1:
4136 * Apply the following rules in the given order, until the sign of the factor is determined. Later rules only apply,
4137 * if the current rule doesn't determine the sign):
4138 * 1. the right hand side must not be negative
4139 * 2. the right hand side must not be infinite
4140 * 3. the absolute value of the right hand side must be greater than that of the left hand side
4141 * 4. the number of positive coefficients must not be smaller than the number of negative coefficients
4142 * 5. multiply with +1
4143 * - rationals to integrals
4144 * Try to identify a rational representation of the fractional coefficients, and multiply all coefficients
4145 * by the smallest common multiple of all denominators to get integral coefficients.
4146 * Forbid large denominators due to numerical stability.
4147 * - division by greatest common divisor
4148 * If all coefficients are integral, divide them by the greatest common divisor.
4149 */
4150static
4152 SCIP* scip, /**< SCIP data structure */
4153 SCIP_CONS* cons, /**< linear constraint to normalize */
4154 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
4155 )
4156{
4157 SCIP_CONSDATA* consdata;
4158 SCIP_Real* vals;
4159 SCIP_Longint scm;
4160 SCIP_Longint numerator;
4161 SCIP_Longint denominator;
4162 SCIP_Longint gcd;
4163 SCIP_Longint maxmult;
4164 SCIP_Real epsilon;
4165 SCIP_Real feastol;
4166 SCIP_Real maxabsval;
4167 SCIP_Real minabsval;
4168 SCIP_Bool success;
4169 SCIP_Bool onlyintegral;
4170 int nvars;
4171 int mult;
4172 int nposcoeffs;
4173 int nnegcoeffs;
4174 int i;
4175
4176 assert(scip != NULL);
4177 assert(cons != NULL);
4178 assert(infeasible != NULL);
4179
4180 *infeasible = FALSE;
4181
4182 /* we must not change a modifiable constraint in any way */
4183 if( SCIPconsIsModifiable(cons) )
4184 return SCIP_OKAY;
4185
4186 /* get constraint data */
4187 consdata = SCIPconsGetData(cons);
4188 assert(consdata != NULL);
4189
4190 /* check, if the constraint is already normalized */
4191 if( consdata->normalized )
4192 return SCIP_OKAY;
4193
4194 /* get coefficient arrays */
4195 vals = consdata->vals;
4196 nvars = consdata->nvars;
4197 assert(nvars == 0 || vals != NULL);
4198
4199 if( nvars == 0 )
4200 {
4201 consdata->normalized = TRUE;
4202 return SCIP_OKAY;
4203 }
4204
4205 assert(vals != NULL);
4206
4207 /* get maximum and minimum absolute coefficient */
4208 maxabsval = consdataGetMaxAbsval(consdata);
4209 minabsval = consdataGetMinAbsval(consdata);
4210
4211 /* return if scaling by maxval will eliminate coefficients */
4212 if( SCIPisZero(scip, minabsval/maxabsval) )
4213 return SCIP_OKAY;
4214
4215 /* return if scaling by maxval will eliminate or generate non-zero sides */
4216 if( !SCIPisInfinity(scip, consdata->lhs) && SCIPisFeasZero(scip, consdata->lhs) != SCIPisFeasZero(scip, consdata->lhs/maxabsval) )
4217 return SCIP_OKAY;
4218 if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisFeasZero(scip, consdata->rhs) != SCIPisFeasZero(scip, consdata->rhs/maxabsval) )
4219 return SCIP_OKAY;
4220
4221 /* check if not all absolute coefficients are near 1.0 but scaling could do */
4222 if( SCIPisLT(scip, minabsval, 1.0) != SCIPisGT(scip, maxabsval, 1.0) )
4223 {
4224 SCIP_Real scalar;
4225
4226 /* calculate scale of the average minimum and maximum absolute coefficient to 1.0 */
4227 scalar = 2.0 / (minabsval + maxabsval);
4228
4229 /* check if all scaled absolute coefficients are near 1.0
4230 * we can relax EQ(x,1.0) to LE(x,1.0), as LT(x,1.0) is not possible
4231 */
4232 if( SCIPisLE(scip, scalar * maxabsval, 1.0) )
4233 {
4234 SCIPdebugMsg(scip, "divide linear constraint with %g, because all coefficients are in absolute value the same\n", maxabsval);
4236 SCIP_CALL( scaleCons(scip, cons, scalar) );
4237
4238 /* get new consdata information, because scaleCons() might have deleted variables */
4239 vals = consdata->vals;
4240 nvars = consdata->nvars;
4241
4242 assert(nvars == 0 || vals != NULL);
4243 }
4244 }
4245
4246 /* nvars might have changed */
4247 if( nvars == 0 )
4248 {
4249 consdata->normalized = TRUE;
4250 return SCIP_OKAY;
4251 }
4252
4253 assert(vals != NULL);
4254
4255 /* calculate the maximal multiplier for common divisor calculation:
4256 * |p/q - val| < epsilon and q < feastol/epsilon => |p - q*val| < feastol
4257 * which means, a value of feastol/epsilon should be used as maximal multiplier;
4258 * additionally, we don't want to scale the constraint if this would lead to too
4259 * large coefficients
4260 */
4261 epsilon = SCIPepsilon(scip) * 0.9; /* slightly decrease epsilon to be safe in rational conversion below */
4262 feastol = SCIPfeastol(scip);
4263 maxmult = (SCIP_Longint)(feastol/epsilon + feastol);
4264
4265 if( !consdata->hasnonbinvalid )
4266 consdataCheckNonbinvar(consdata);
4267
4268 /* get maximum absolute coefficient */
4269 maxabsval = consdataGetMaxAbsval(consdata);
4270
4271 /* if all variables are of integral type we will allow a greater multiplier */
4272 if( !consdata->hascontvar )
4273 maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEFINTEGER / MAX(maxabsval, 1.0))); /*lint !e835*/
4274 else
4275 maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEF / MAX(maxabsval, 1.0))); /*lint !e835*/
4276
4277 /*
4278 * multiplication with +1 or -1
4279 */
4280 mult = 0;
4281
4282 /* 1. the right hand side must not be negative */
4283 if( SCIPisPositive(scip, consdata->lhs) )
4284 mult = +1;
4285 else if( SCIPisNegative(scip, consdata->rhs) )
4286 mult = -1;
4287
4288 if( mult == 0 )
4289 {
4290 /* 2. the right hand side must not be infinite */
4291 if( SCIPisInfinity(scip, -consdata->lhs) )
4292 mult = +1;
4293 else if( SCIPisInfinity(scip, consdata->rhs) )
4294 mult = -1;
4295 }
4296
4297 if( mult == 0 )
4298 {
4299 /* 3. the absolute value of the right hand side must be greater than that of the left hand side */
4300 if( SCIPisGT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4301 mult = +1;
4302 else if( SCIPisLT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4303 mult = -1;
4304 }
4305
4306 if( mult == 0 )
4307 {
4308 /* 4. the number of positive coefficients must not be smaller than the number of negative coefficients */
4309 nposcoeffs = 0;
4310 nnegcoeffs = 0;
4311 for( i = 0; i < nvars; ++i )
4312 {
4313 if( vals[i] > 0.0 )
4314 nposcoeffs++;
4315 else
4316 nnegcoeffs++;
4317 }
4318 if( nposcoeffs > nnegcoeffs )
4319 mult = +1;
4320 else if( nposcoeffs < nnegcoeffs )
4321 mult = -1;
4322 }
4323
4324 if( mult == 0 )
4325 {
4326 /* 5. multiply with +1 */
4327 mult = +1;
4328 }
4329
4330 assert(mult == +1 || mult == -1);
4331 if( mult == -1 )
4332 {
4333 /* scale the constraint with -1 */
4334 SCIPdebugMsg(scip, "multiply linear constraint with -1.0\n");
4336 SCIP_CALL( scaleCons(scip, cons, -1.0) );
4337
4338 /* scalecons() can delete variables, but scaling with -1 should not do that */
4339 assert(nvars == consdata->nvars);
4340 }
4341
4342 /*
4343 * rationals to integrals
4344 *
4345 * @todo try scaling only on behalf of non-continuous variables
4346 */
4347 success = TRUE;
4348 scm = 1;
4349 for( i = 0; i < nvars && success && scm <= maxmult; ++i )
4350 {
4351 if( !SCIPisIntegral(scip, vals[i]) )
4352 {
4353 /* epsilon has been slightly decreased above - to be on the safe side */
4354 success = SCIPrealToRational(vals[i], -epsilon, epsilon , maxmult, &numerator, &denominator);
4355 if( success )
4356 scm = SCIPcalcSmaComMul(scm, denominator);
4357 }
4358 }
4359 assert(scm >= 1);
4360
4361 /* it might be that we have really big coefficients, but all are integral, in that case we want to divide them by
4362 * their greatest common divisor
4363 */
4364 onlyintegral = TRUE;
4365 if( scm == 1 )
4366 {
4367 for( i = nvars - 1; i >= 0; --i )
4368 {
4369 if( !SCIPisIntegral(scip, vals[i]) )
4370 {
4371 onlyintegral = FALSE;
4372 break;
4373 }
4374 }
4375 }
4376
4377 success = success && (scm <= maxmult || (scm == 1 && onlyintegral));
4378 if( success && scm != 1 )
4379 {
4380 /* scale the constraint with the smallest common multiple of all denominators */
4381 SCIPdebugMsg(scip, "scale linear constraint with %" SCIP_LONGINT_FORMAT " to make coefficients integral\n", scm);
4383 SCIP_CALL( scaleCons(scip, cons, (SCIP_Real)scm) );
4384
4385 if( consdata->validmaxabsval )
4386 {
4387 consdata->maxabsval *= REALABS((SCIP_Real)scm);
4388 if( !SCIPisIntegral(scip, consdata->maxabsval) )
4389 {
4390 consdata->validmaxabsval = FALSE;
4391 consdata->maxabsval = SCIP_INVALID;
4392 consdataCalcMaxAbsval(consdata);
4393 }
4394 }
4395
4396 if( consdata->validminabsval )
4397 {
4398 consdata->minabsval *= REALABS((SCIP_Real)scm);
4399 if( !SCIPisIntegral(scip, consdata->minabsval) )
4400 {
4401 consdata->validminabsval = FALSE;
4402 consdata->minabsval = SCIP_INVALID;
4403 consdataCalcMinAbsval(consdata);
4404 }
4405 }
4406
4407 /* get new consdata information, because scalecons() might have deleted variables */
4408 vals = consdata->vals;
4409 nvars = consdata->nvars;
4410 assert(nvars == 0 || vals != NULL);
4411 }
4412
4413 /*
4414 * division by greatest common divisor
4415 */
4416 if( success && nvars >= 1 )
4417 {
4418 /* all coefficients are integral: divide them by their greatest common divisor */
4419 assert(SCIPisIntegral(scip, vals[0]));
4420
4421 gcd = (SCIP_Longint)(REALABS(vals[0]) + feastol);
4422 for( i = 1; i < nvars && gcd > 1; ++i )
4423 {
4424 assert(SCIPisIntegral(scip, vals[i]));
4425 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[i]) + feastol));
4426 }
4427
4428 if( gcd > 1 )
4429 {
4430 /* since the lhs/rhs is not respected for gcd calculation it can happen that we detect infeasibility */
4431 if( !consdata->hascontvar && onlyintegral )
4432 {
4433 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) && !SCIPisFeasIntegral(scip, consdata->rhs / gcd) )
4434 {
4435 *infeasible = TRUE;
4436
4437 SCIPdebugMsg(scip, "detected infeasibility of constraint after scaling with gcd=%" SCIP_LONGINT_FORMAT ":\n", gcd);
4439
4440 return SCIP_OKAY;
4441 }
4442 }
4443
4444 /* divide the constraint by the greatest common divisor of the coefficients */
4445 SCIPdebugMsg(scip, "divide linear constraint by greatest common divisor %" SCIP_LONGINT_FORMAT "\n", gcd);
4447 SCIP_CALL( scaleCons(scip, cons, 1.0/(SCIP_Real)gcd) );
4448
4449 if( consdata->validmaxabsval )
4450 {
4451 consdata->maxabsval /= REALABS((SCIP_Real)gcd);
4452 }
4453 if( consdata->validminabsval )
4454 {
4455 consdata->minabsval /= REALABS((SCIP_Real)gcd);
4456 }
4457 }
4458 }
4459
4460 /* mark constraint to be normalized */
4461 consdata->normalized = TRUE;
4462
4463 SCIPdebugMsg(scip, "normalized constraint:\n");
4465
4466 return SCIP_OKAY;
4467}
4468
4469/** replaces multiple occurrences of a variable by a single non-zero coefficient */
4470static
4472 SCIP* scip, /**< SCIP data structure */
4473 SCIP_CONS* cons /**< linear constraint */
4474 )
4475{
4476 SCIP_CONSDATA* consdata;
4477 SCIP_VAR* var;
4478 SCIP_Real valsum;
4479 int v;
4480
4481 assert(scip != NULL);
4482 assert(cons != NULL);
4483
4484 consdata = SCIPconsGetData(cons);
4485 assert(consdata != NULL);
4486
4487 if( consdata->merged )
4488 return SCIP_OKAY;
4489
4490 /* sort the constraint */
4491 SCIP_CALL( consdataSort(scip, consdata) );
4492
4493 v = consdata->nvars - 1;
4494
4495 /* go backwards through the constraint looking for multiple occurrences of the same variable;
4496 * backward direction is necessary, since delCoefPos() modifies the given position and
4497 * the subsequent ones
4498 */
4499 while( v >= 0 )
4500 {
4501 var = consdata->vars[v];
4502 valsum = consdata->vals[v];
4503
4504 /* sum multiple occurrences */
4505 while( v >= 1 && consdata->vars[v-1] == var )
4506 {
4507 SCIP_CALL( delCoefPos(scip, cons, v) );
4508 --v;
4509 valsum += consdata->vals[v];
4510 }
4511
4512 assert(consdata->vars[v] == var);
4513
4514 /* modify the last existing occurrence of the variable */
4515 if( SCIPisZero(scip, valsum) )
4516 {
4517 SCIP_CALL( delCoefPos(scip, cons, v) );
4518 }
4519 else if( valsum != consdata->vals[v] ) /*lint !e777*/
4520 {
4521 SCIP_CALL( chgCoefPos(scip, cons, v, valsum) );
4522 }
4523
4524 --v;
4525 }
4526
4527 consdata->merged = TRUE;
4528
4529 return SCIP_OKAY;
4530}
4531
4532/** replaces all fixed and aggregated variables by their non-fixed counterparts */
4533static
4535 SCIP* scip, /**< SCIP data structure */
4536 SCIP_CONS* cons, /**< linear constraint */
4537 SCIP_Bool* infeasible /**< pointer to store if infeasibility is detected; or NULL if this
4538 * information is not needed; in this case, we apply all fixings
4539 * instead of stopping after the first infeasible one */
4540 )
4541{
4542 SCIP_CONSDATA* consdata;
4543 int v;
4544
4545 assert(scip != NULL);
4546 assert(cons != NULL);
4547
4548 if( infeasible != NULL )
4549 *infeasible = FALSE;
4550
4551 consdata = SCIPconsGetData(cons);
4552 assert(consdata != NULL);
4553
4554 if( consdata->eventdata == NULL )
4555 {
4556 SCIP_CONSHDLR* conshdlr;
4557 SCIP_CONSHDLRDATA* conshdlrdata;
4558
4559 conshdlr = SCIPconsGetHdlr(cons);
4560 assert(conshdlr != NULL);
4561
4562 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4563 assert(conshdlrdata != NULL);
4564
4565 /* catch bound change events of variables */
4566 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
4567 assert(consdata->eventdata != NULL);
4568 }
4569
4570 if( !consdata->removedfixings )
4571 {
4572 SCIP_Real lhssubtrahend;
4573 SCIP_Real rhssubtrahend;
4574
4575 /* if an unmodifiable row has been added to the LP, then we cannot apply fixing anymore (cannot change a row)
4576 * this should not happen, as applyFixings is called in addRelaxation() before creating and adding a row
4577 */
4578 assert(consdata->row == NULL || !SCIProwIsInLP(consdata->row) || SCIProwIsModifiable(consdata->row));
4579
4580 lhssubtrahend = 0.0;
4581 rhssubtrahend = 0.0;
4582
4583 SCIPdebugMsg(scip, "applying fixings:\n");
4585
4586 v = 0;
4587 while( v < consdata->nvars )
4588 {
4589 SCIP_VAR* var = consdata->vars[v];
4590 SCIP_Real scalar = consdata->vals[v];
4591 SCIP_Real constant = 0.0;
4593
4594 SCIP_CALL( SCIPgetProbvarSum(scip, &var, &scalar, &constant) );
4595
4596 switch( SCIPvarGetStatus(var) )
4597 {
4599 SCIPerrorMessage("original variable in transformed linear constraint\n");
4600 return SCIP_INVALIDDATA;
4601
4604 SCIPerrorMessage("aggregated variable after resolving linear term\n");
4605 return SCIP_INVALIDDATA;
4606
4609 if( var != consdata->vars[v] )
4610 {
4611 assert(scalar != 0.0);
4612 SCIP_CALL( addCoef(scip, cons, var, scalar) );
4613 SCIP_CALL( delCoefPos(scip, cons, v) );
4614
4615 assert(!SCIPisInfinity(scip, ABS(constant)));
4616 if( !SCIPisInfinity(scip, -consdata->lhs) )
4617 lhssubtrahend += constant;
4618 if( !SCIPisInfinity(scip, consdata->rhs) )
4619 rhssubtrahend += constant;
4620 }
4621 ++v;
4622 break;
4623
4625 if( scalar != 0.0 )
4626 {
4627 SCIP_VAR** aggrvars;
4628 SCIP_Real* aggrscalars;
4629 SCIP_Real aggrconstant;
4630 int naggrvars;
4631 int i;
4632
4634 aggrvars = SCIPvarGetMultaggrVars(var);
4635 aggrscalars = SCIPvarGetMultaggrScalars(var);
4636 aggrconstant = SCIPvarGetMultaggrConstant(var);
4637 naggrvars = SCIPvarGetMultaggrNVars(var);
4638
4639 for( i = 0; i < naggrvars; ++i )
4640 {
4641 SCIP_CALL( addCoef(scip, cons, aggrvars[i], scalar * aggrscalars[i]) );
4642 }
4643
4644 constant += scalar * aggrconstant;
4645 }
4646 /*lint -fallthrough*/
4647
4649 if( !SCIPisInfinity(scip, -consdata->lhs) )
4650 {
4651 if( SCIPisInfinity(scip, ABS(constant)) )
4652 {
4653 /* if lhs gets infinity it means that the problem is infeasible */
4654 if( constant < 0.0 )
4655 {
4657
4658 if( infeasible != NULL )
4659 {
4660 *infeasible = TRUE;
4661 return SCIP_OKAY;
4662 }
4663 }
4664 else
4665 {
4666 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
4667 }
4668 }
4669 else
4670 lhssubtrahend += constant;
4671 }
4672 if( !SCIPisInfinity(scip, consdata->rhs) )
4673 {
4674 if( SCIPisInfinity(scip, ABS(constant)) )
4675 {
4676 /* if rhs gets -infinity it means that the problem is infeasible */
4677 if( constant > 0.0 )
4678 {
4679 SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
4680
4681 if( infeasible != NULL )
4682 {
4683 *infeasible = TRUE;
4684 return SCIP_OKAY;
4685 }
4686 }
4687 else
4688 {
4690 }
4691 }
4692 else
4693 rhssubtrahend += constant;
4694 }
4695 SCIP_CALL( delCoefPos(scip, cons, v) );
4696 break;
4697
4698 default:
4699 SCIPerrorMessage("unknown variable status\n");
4700 SCIPABORT();
4701 return SCIP_INVALIDDATA; /*lint !e527*/
4702 }
4703 }
4704
4705 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->lhs) )
4706 {
4707 /* check left hand side of unmodifiable empty constraint with former feasibility tolerance */
4708 if( !SCIPconsIsModifiable(cons) && consdata->nvars == 0 )
4709 {
4710 if( SCIPisFeasLT(scip, lhssubtrahend, consdata->lhs) )
4711 {
4713
4714 if( infeasible != NULL )
4715 {
4716 *infeasible = TRUE;
4717 return SCIP_OKAY;
4718 }
4719 }
4720 else
4721 {
4722 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
4723 }
4724 }
4725 /* for normal numbers that are relatively equal, subtraction can lead to cancellation,
4726 * causing wrong fixings of other variables --> better use a real zero here
4727 */
4728 else if( SCIPisGE(scip, ABS(consdata->lhs), 1.0) && SCIPisEQ(scip, lhssubtrahend, consdata->lhs) )
4729 {
4730 SCIP_CALL( chgLhs(scip, cons, 0.0) );
4731 }
4732 else
4733 {
4734 SCIP_CALL( chgLhs(scip, cons, consdata->lhs - lhssubtrahend) );
4735 }
4736 }
4737 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs) )
4738 {
4739 /* check right hand side of unmodifiable empty constraint with former feasibility tolerance */
4740 if( !SCIPconsIsModifiable(cons) && consdata->nvars == 0 )
4741 {
4742 if( SCIPisFeasGT(scip, rhssubtrahend, consdata->rhs) )
4743 {
4744 SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
4745
4746 if( infeasible != NULL )
4747 {
4748 *infeasible = TRUE;
4749 return SCIP_OKAY;
4750 }
4751 }
4752 else
4753 {
4755 }
4756 }
4757 /* for normal numbers that are relatively equal, subtraction can lead to cancellation,
4758 * causing wrong fixings of other variables --> better use a real zero here
4759 */
4760 else if( SCIPisGE(scip, ABS(consdata->rhs), 1.0) && SCIPisEQ(scip, rhssubtrahend, consdata->rhs) )
4761 {
4762 SCIP_CALL( chgRhs(scip, cons, 0.0) );
4763 }
4764 else
4765 {
4766 SCIP_CALL( chgRhs(scip, cons, consdata->rhs - rhssubtrahend) );
4767 }
4768 }
4769 consdata->removedfixings = TRUE;
4770
4771 SCIPdebugMsg(scip, "after fixings:\n");
4773
4774 /* if aggregated variables have been replaced, multiple entries of the same variable are possible and we have
4775 * to clean up the constraint
4776 */
4777 SCIP_CALL( mergeMultiples(scip, cons) );
4778
4779 SCIPdebugMsg(scip, "after merging:\n");
4781 }
4782 assert(consdata->removedfixings);
4783
4784#ifndef NDEBUG
4785 /* check, if all fixings are applied */
4786 for( v = 0; v < consdata->nvars; ++v )
4787 assert(SCIPvarIsActive(consdata->vars[v]));
4788#endif
4789
4790 return SCIP_OKAY;
4791}
4792
4793/** for each variable in the linear constraint, except the inferred variable, adds one bound to the conflict analysis'
4794 * candidate store (bound depends on sign of coefficient and whether the left or right hand side was the reason for the
4795 * inference variable's bound change); the conflict analysis can be initialized with the linear constraint being the
4796 * conflict detecting constraint by using NULL as inferred variable
4797 */
4798static
4800 SCIP* scip, /**< SCIP data structure */
4801 SCIP_CONS* cons, /**< constraint that inferred the bound change */
4802 SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
4803 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4804 int inferpos, /**< position of the inferred variable in the vars array */
4805 SCIP_Bool reasonisrhs /**< is the right hand side responsible for the bound change? */
4806 )
4807{
4808 SCIP_CONSDATA* consdata;
4809 SCIP_VAR** vars;
4810 SCIP_Real* vals;
4811 int nvars;
4812 int i;
4813
4814 assert(scip != NULL);
4815 assert(cons != NULL);
4816
4817 consdata = SCIPconsGetData(cons);
4818
4819 assert(consdata != NULL);
4820
4821 vars = consdata->vars;
4822 vals = consdata->vals;
4823 nvars = consdata->nvars;
4824
4825 assert(vars != NULL || nvars == 0);
4826 assert(vals != NULL || nvars == 0);
4827
4828 assert(-1 <= inferpos && inferpos < nvars);
4829 assert((infervar == NULL) == (inferpos == -1));
4830 assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
4831
4832 /* for each variable, add the bound to the conflict queue, that is responsible for the minimal or maximal
4833 * residual value, depending on whether the left or right hand side is responsible for the bound change:
4834 * - if the right hand side is the reason, the minimal residual activity is responsible
4835 * - if the left hand side is the reason, the maximal residual activity is responsible
4836 */
4837
4838 /* if the variable is integral we only need to add reason bounds until the propagation could be applied */
4839 if( infervar == NULL || SCIPvarIsIntegral(infervar) )
4840 {
4841 SCIP_Real minresactivity;
4842 SCIP_Real maxresactivity;
4843 SCIP_Bool ismintight;
4844 SCIP_Bool ismaxtight;
4845 SCIP_Bool isminsettoinfinity;
4846 SCIP_Bool ismaxsettoinfinity;
4847
4848 minresactivity = -SCIPinfinity(scip);
4849 maxresactivity = SCIPinfinity(scip);
4850
4851 /* calculate the minimal and maximal global activity of all other variables involved in the constraint */
4852 if( infervar != NULL )
4853 {
4854 assert(vals != NULL); /* for flexelint */
4855 if( reasonisrhs )
4856 consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, &minresactivity, NULL,
4857 &ismintight, NULL, &isminsettoinfinity, NULL);
4858 else
4859 consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, NULL, &maxresactivity,
4860 NULL, &ismaxtight, NULL, &ismaxsettoinfinity);
4861 }
4862 else
4863 {
4864 if( reasonisrhs )
4865 consdataGetGlbActivityBounds(scip, consdata, FALSE, &minresactivity, NULL,
4866 &ismintight, NULL, &isminsettoinfinity, NULL);
4867 else
4868 consdataGetGlbActivityBounds(scip, consdata, FALSE, NULL, &maxresactivity,
4869 NULL, &ismaxtight, NULL, &ismaxsettoinfinity);
4870 }
4871
4872 /* we can only do something clever, if the residual activity is finite and not relaxed */
4873 if( (reasonisrhs && !isminsettoinfinity && ismintight) || (!reasonisrhs && !ismaxsettoinfinity && ismaxtight) ) /*lint !e644*/
4874 {
4875 SCIP_Real rescap;
4876 SCIP_Bool resactisinf;
4877
4878 resactisinf = FALSE;
4879
4880 /* calculate the residual capacity that would be left, if the variable would be set to one more / one less
4881 * than its inferred bound
4882 */
4883 if( infervar != NULL )
4884 {
4885 assert(vals != NULL); /* for flexelint */
4886
4887 if( reasonisrhs )
4888 {
4889 if( SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
4890 {
4891 consdataGetReliableResidualActivity(scip, consdata, infervar, &minresactivity, TRUE, TRUE);
4892 if( SCIPisInfinity(scip, -minresactivity) )
4893 resactisinf = TRUE;
4894 }
4895 rescap = consdata->rhs - minresactivity;
4896 }
4897 else
4898 {
4899 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
4900 {
4901 consdataGetReliableResidualActivity(scip, consdata, infervar, &maxresactivity, FALSE, TRUE);
4902 if( SCIPisInfinity(scip, maxresactivity) )
4903 resactisinf = TRUE;
4904 }
4905 rescap = consdata->lhs - maxresactivity;
4906 }
4907
4908 if( reasonisrhs == (vals[inferpos] > 0.0) )
4909 rescap -= vals[inferpos] * (SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) + 1.0);
4910 else
4911 rescap -= vals[inferpos] * (SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) - 1.0);
4912 }
4913 else
4914 rescap = (reasonisrhs ? consdata->rhs - minresactivity : consdata->lhs - maxresactivity);
4915
4916 if( !resactisinf )
4917 {
4918 /* now add bounds as reasons until the residual capacity is exceeded */
4919 for( i = 0; i < nvars; ++i )
4920 {
4921 assert( vars != NULL && vals != NULL ); /* for lint */
4922
4923 /* zero coefficients and the inferred variable can be ignored */
4924 if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
4925 continue;
4926
4927 /* check if the residual capacity is exceeded */
4928 if( (reasonisrhs && SCIPisFeasNegative(scip, rescap))
4929 || (!reasonisrhs && SCIPisFeasPositive(scip, rescap)) )
4930 break;
4931
4932 /* update the residual capacity due to the local bound of this variable */
4933 if( reasonisrhs == (vals[i] > 0.0) )
4934 {
4935 /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound */
4936 SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
4937 rescap -= vals[i] * (SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetLbGlobal(vars[i]));
4938 }
4939 else
4940 {
4941 /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound */
4942 SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
4943 rescap -= vals[i] * (SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetUbGlobal(vars[i]));
4944 }
4945 }
4946 return SCIP_OKAY;
4947 }
4948 }
4949 }
4950
4951 /* for a bound change on a continuous variable, all locally changed bounds are responsible */
4952 for( i = 0; i < nvars; ++i )
4953 {
4954 assert(vars != NULL); /* for flexelint */
4955 assert(vals != NULL); /* for flexelint */
4956
4957 /* zero coefficients and the inferred variable can be ignored */
4958 if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
4959 continue;
4960
4961 if( reasonisrhs == (vals[i] > 0.0) )
4962 {
4963 /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound is responsible */
4964 SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
4965 }
4966 else
4967 {
4968 /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound is responsible */
4969 SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
4970 }
4971 }
4972
4973 return SCIP_OKAY;
4974}
4975
4976/** for each variable in the linear ranged row constraint, except the inferred variable, adds the bounds of all fixed
4977 * variables to the conflict analysis' candidate store; the conflict analysis can be initialized
4978 * with the linear constraint being the conflict detecting constraint by using NULL as inferred variable
4979 */
4980static
4982 SCIP* scip, /**< SCIP data structure */
4983 SCIP_CONS* cons, /**< constraint that inferred the bound change */
4984 SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
4985 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4986 int inferpos /**< position of the inferred variable in the vars array, or -1 */
4987 )
4988{
4989 SCIP_CONSDATA* consdata;
4990 SCIP_VAR** vars;
4991 int nvars;
4992 int v;
4993
4994 assert(scip != NULL);
4995 assert(cons != NULL);
4996
4997 consdata = SCIPconsGetData(cons);
4998 assert(consdata != NULL);
4999 vars = consdata->vars;
5000 nvars = consdata->nvars;
5001 assert(vars != NULL || nvars == 0);
5002 assert(-1 <= inferpos && inferpos < nvars);
5003 assert((infervar == NULL) == (inferpos == -1));
5004 assert(inferpos == -1 || vars != NULL);
5005 assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
5006
5007 /* collect all fixed variables */
5008 for( v = nvars - 1; v >= 0; --v )
5009 {
5010 assert(vars != NULL); /* for flexelint */
5011
5012 /* need to add old bounds before propagation of inferrence variable */
5013 if( vars[v] == infervar )
5014 {
5015 assert(vars[v] != NULL);
5016
5018 {
5019 /* @todo get boundchange index before this last boundchange and correct the index */
5020 SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5021 }
5022
5024 {
5025 /* @todo get boundchange index before this last boundchange and correct the index */
5026 SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5027 }
5028
5029 continue;
5030 }
5031
5032 /* check for fixed variables */
5033 if( SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE)) )
5034 {
5035 /* add all bounds of fixed variables which lead to the boundchange of the given inference variable */
5036 SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5037 SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5038 }
5039 }
5040
5041 return SCIP_OKAY;
5042}
5043
5044/** add reasoning variables to conflict candidate queue which led to the conflict */
5045static
5047 SCIP* scip, /**< SCIP data structure */
5048 SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5049 int nvars, /**< number of variables reasoning the infeasibility */
5050 SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5051 SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5052 )
5053{
5054 int v;
5055
5056 assert(scip != NULL);
5057
5058 /* collect all variables for which the local bounds differ from their global bounds */
5059 for( v = nvars - 1; v >= 0; --v )
5060 {
5061 assert(vars != NULL);
5062
5063 /* check for local bound changes variables */
5065 {
5066 /* add conflict bound */
5068 }
5069
5071 {
5073 }
5074 }
5075
5076 if( var != NULL )
5077 {
5078 if( bound < SCIPvarGetLbLocal(var) )
5079 {
5081 }
5082
5083 if( bound > SCIPvarGetUbLocal(var) )
5084 {
5086 }
5087 }
5088
5089 return SCIP_OKAY;
5090}
5091
5092/** resolves a propagation on the given variable by supplying the variables needed for applying the corresponding
5093 * propagation rule (see propagateCons()):
5094 * (1) activity residuals of all other variables tighten bounds of single variable
5095 */
5096static
5098 SCIP* scip, /**< SCIP data structure */
5099 SCIP_CONS* cons, /**< constraint that inferred the bound change */
5100 SCIP_VAR* infervar, /**< variable that was deduced */
5101 INFERINFO inferinfo, /**< inference information */
5102 SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
5103 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
5104 SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
5105 )
5106{
5107 SCIP_CONSDATA* consdata;
5108 SCIP_VAR** vars;
5109#ifndef NDEBUG
5110 SCIP_Real* vals;
5111#endif
5112 int nvars;
5113 int inferpos;
5114
5115 assert(scip != NULL);
5116 assert(cons != NULL);
5117 assert(result != NULL);
5118
5119 consdata = SCIPconsGetData(cons);
5120 assert(consdata != NULL);
5121 vars = consdata->vars;
5122 nvars = consdata->nvars;
5123#ifndef NDEBUG
5124 vals = consdata->vals;
5125 assert(vars != NULL);
5126 assert(vals != NULL);
5127#endif
5128
5129 /* get the position of the inferred variable in the vars array */
5130 inferpos = inferInfoGetPos(inferinfo);
5131 if( inferpos >= nvars || vars[inferpos] != infervar )
5132 {
5133 /* find inference variable in constraint */
5134 /**@todo use a binary search here; the variables can be sorted by variable index */
5135 for( inferpos = 0; inferpos < nvars && vars[inferpos] != infervar; ++inferpos )
5136 {}
5137 }
5138 assert(inferpos < nvars);
5139 assert(vars[inferpos] == infervar);
5140 assert(!SCIPisZero(scip, vals[inferpos]));
5141
5142 switch( inferInfoGetProprule(inferinfo) )
5143 {
5144 case PROPRULE_1_RHS:
5145 /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5146 * constraint (only taking the other variables into account) didn't leave enough space for a larger
5147 * domain in order to not exceed the right hand side of the inequality
5148 */
5149 assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_UPPER));
5150 SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, TRUE) );
5152 break;
5153
5154 case PROPRULE_1_LHS:
5155 /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5156 * constraint (only taking the other variables into account) didn't leave enough space for a larger
5157 * domain in order to not fall below the left hand side of the inequality
5158 */
5159 assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_LOWER));
5160 SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, FALSE) );
5162 break;
5163
5165 /* the bound of the variable was tightened, because some variables were already fixed and the leftover only allow
5166 * the given inference variable to their bounds in this given ranged row
5167 */
5168
5169 /* check that we really have a ranged row here */
5170 assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5171 SCIP_CALL( addConflictFixedVars(scip, cons, infervar, bdchgidx, inferpos) );
5173 break;
5174
5175 case PROPRULE_INVALID:
5176 default:
5177 SCIPerrorMessage("invalid inference information %d in linear constraint <%s> at position %d for %s bound of variable <%s>\n",
5178 inferInfoGetProprule(inferinfo), SCIPconsGetName(cons), inferInfoGetPos(inferinfo),
5179 boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(infervar));
5180 SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
5181 SCIPinfoMessage(scip, NULL, ";\n");
5182 return SCIP_INVALIDDATA;
5183 }
5184
5185 return SCIP_OKAY;
5186}
5187
5188/** analyzes conflicting bounds on given constraint, and adds conflict constraint to problem */
5189static
5191 SCIP* scip, /**< SCIP data structure */
5192 SCIP_CONS* cons, /**< conflict detecting constraint */
5193 SCIP_Bool reasonisrhs /**< is the right hand side responsible for the conflict? */
5194 )
5195{
5196 /* conflict analysis can only be applied in solving stage and if it is turned on */
5198 return SCIP_OKAY;
5199
5200 /* initialize conflict analysis */
5202
5203 /* add the conflicting bound for each variable of infeasible constraint to conflict candidate queue */
5204 SCIP_CALL( addConflictBounds(scip, cons, NULL, NULL, -1, reasonisrhs) );
5205
5206 /* analyze the conflict */
5208
5209 return SCIP_OKAY;
5210}
5211
5212/** check if there is any hope of tightening some bounds */
5213static
5215 SCIP_CONS* cons /**< linear constraint */
5216 )
5217{
5218 SCIP_CONSDATA* consdata;
5219 int infcountmin;
5220 int infcountmax;
5221
5222 consdata = SCIPconsGetData(cons);
5223 assert(consdata != NULL);
5224
5225 infcountmin = consdata->minactivityneginf
5226 + consdata->minactivityposinf
5227 + consdata->minactivityneghuge
5228 + consdata->minactivityposhuge;
5229 infcountmax = consdata->maxactivityneginf
5230 + consdata->maxactivityposinf
5231 + consdata->maxactivityneghuge
5232 + consdata->maxactivityposhuge;
5233
5234 if( infcountmin > 1 && infcountmax > 1 )
5235 return FALSE;
5236
5237 return TRUE;
5238}
5239
5240/** tighten upper bound */
5241static
5243 SCIP* scip, /**< SCIP data structure */
5244 SCIP_CONS* cons, /**< linear constraint */
5245 int pos, /**< variable position */
5246 PROPRULE proprule, /**< propagation rule that deduced the value */
5247 SCIP_Real newub, /**< new upper bound */
5248 SCIP_Real oldub, /**< old upper bound */
5249 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5250 int* nchgbds, /**< pointer to count the total number of tightened bounds */
5251 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5252 )
5253{
5254 SCIP_CONSDATA* consdata;
5255 SCIP_VAR* var;
5256 SCIP_Real lb;
5257 SCIP_Bool infeasible;
5258 SCIP_Bool tightened;
5259
5260 assert(cons != NULL);
5261 assert(!SCIPisInfinity(scip, newub));
5262
5263 consdata = SCIPconsGetData(cons);
5264 assert(consdata != NULL);
5265 var = consdata->vars[pos];
5266 assert(var != NULL);
5267
5268 lb = SCIPvarGetLbLocal(var);
5269 newub = SCIPadjustedVarUb(scip, var, newub);
5270
5271 if( force || SCIPisUbBetter(scip, newub, lb, oldub) )
5272 {
5273 SCIP_VARTYPE vartype = SCIPvarGetType(var);
5275
5276 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
5277 SCIPconsGetName(cons), SCIPvarGetName(var), lb, oldub, consdata->vals[pos],
5278 QUAD_TO_DBL(consdata->minactivity), QUAD_TO_DBL(consdata->maxactivity), consdata->lhs, consdata->rhs, newub);
5279
5280 /* tighten upper bound */
5281 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5282
5283 if( infeasible )
5284 {
5285 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5286 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5287
5288 /* analyze conflict */
5290
5291 *cutoff = TRUE;
5292 }
5293 else if( tightened )
5294 {
5296 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5298
5299 (*nchgbds)++;
5300
5301 /* if variable type was changed we might be able to upgrade the constraint */
5302 if( SCIPvarGetType(var) != vartype || SCIPvarGetImplType(var) != impltype )
5303 consdata->upgradetried = FALSE;
5304 }
5305 }
5306 return SCIP_OKAY;
5307}
5308
5309/** tighten lower bound */
5310static
5312 SCIP* scip, /**< SCIP data structure */
5313 SCIP_CONS* cons, /**< linear constraint */
5314 int pos, /**< variable position */
5315 PROPRULE proprule, /**< propagation rule that deduced the value */
5316 SCIP_Real newlb, /**< new lower bound */
5317 SCIP_Real oldlb, /**< old lower bound */
5318 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5319 int* nchgbds, /**< pointer to count the total number of tightened bounds */
5320 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5321 )
5322{
5323 SCIP_CONSDATA* consdata;
5324 SCIP_VAR* var;
5325 SCIP_Real ub;
5326 SCIP_Bool infeasible;
5327 SCIP_Bool tightened;
5328
5329 assert(cons != NULL);
5330 assert(!SCIPisInfinity(scip, newlb));
5331
5332 consdata = SCIPconsGetData(cons);
5333 assert(consdata != NULL);
5334 var = consdata->vars[pos];
5335 assert(var != NULL);
5336
5337 ub = SCIPvarGetUbLocal(var);
5338 newlb = SCIPadjustedVarLb(scip, var, newlb);
5339
5340 if( force || SCIPisLbBetter(scip, newlb, oldlb, ub) )
5341 {
5342 SCIP_VARTYPE vartype = SCIPvarGetType(var);
5344
5345 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
5346 SCIPconsGetName(cons), SCIPvarGetName(var), oldlb, ub, consdata->vals[pos],
5347 QUAD_TO_DBL(consdata->minactivity), QUAD_TO_DBL(consdata->maxactivity), consdata->lhs, consdata->rhs, newlb);
5348
5349 /* tighten lower bound */
5350 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5351
5352 if( infeasible )
5353 {
5354 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5355 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5356
5357 /* analyze conflict */
5359
5360 *cutoff = TRUE;
5361 }
5362 else if( tightened )
5363 {
5365 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5367
5368 (*nchgbds)++;
5369
5370 /* if variable type was changed we might be able to upgrade the constraint */
5371 if( SCIPvarGetType(var) != vartype || SCIPvarGetImplType(var) != impltype )
5372 consdata->upgradetried = FALSE;
5373 }
5374 }
5375 return SCIP_OKAY;
5376}
5377
5378/** tightens bounds of a single variable due to activity bounds (easy case) */
5379static
5381 SCIP* scip, /**< SCIP data structure */
5382 SCIP_CONS* cons, /**< linear constraint */
5383 int pos, /**< position of the variable in the vars array */
5384 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5385 int* nchgbds, /**< pointer to count the total number of tightened bounds */
5386 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5387 )
5388{
5389 SCIP_CONSDATA* consdata;
5390 SCIP_VAR* var;
5391 SCIP_Real val;
5392 SCIP_Real lb;
5393 SCIP_Real ub;
5394 SCIP_Real lhs;
5395 SCIP_Real rhs;
5396
5397 assert(scip != NULL);
5398 assert(cons != NULL);
5399 assert(cutoff != NULL);
5400 assert(nchgbds != NULL);
5401
5402 /* we cannot tighten variables' bounds, if the constraint may be not complete */
5403 if( SCIPconsIsModifiable(cons) )
5404 return SCIP_OKAY;
5405
5406 consdata = SCIPconsGetData(cons);
5407 assert(consdata != NULL);
5408 assert(0 <= pos && pos < consdata->nvars);
5409
5410 *cutoff = FALSE;
5411
5412 var = consdata->vars[pos];
5413 assert(var != NULL);
5414
5415 /* we cannot tighten bounds of multi-aggregated variables */
5417 return SCIP_OKAY;
5418
5419 val = consdata->vals[pos];
5420 lhs = consdata->lhs;
5421 rhs = consdata->rhs;
5422 assert(!SCIPisZero(scip, val));
5423 assert(!SCIPisInfinity(scip, lhs));
5424 assert(!SCIPisInfinity(scip, -rhs));
5425
5426 lb = SCIPvarGetLbLocal(var);
5427 ub = SCIPvarGetUbLocal(var);
5428 assert(SCIPisLE(scip, lb, ub));
5429
5430 /* recompute activities if needed */
5431 if( !consdata->validactivities )
5432 consdataCalcActivities(scip, consdata);
5433 assert(consdata->validactivities);
5434 if( !consdata->validminact )
5436 assert(consdata->validminact);
5437
5438 if( val > 0.0 )
5439 {
5440 /* check, if we can tighten the variable's upper bound */
5441 if( !SCIPisInfinity(scip, rhs) )
5442 {
5443 SCIP_Real slack;
5445
5446 /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
5447 assert(consdata->validminact);
5448
5449 /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5450 if( SCIPisFeasLT(scip, rhs, QUAD_TO_DBL(consdata->minactivity)) )
5451 {
5452 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5453 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->minactivity), rhs);
5454
5455 *cutoff = TRUE;
5456 return SCIP_OKAY;
5457 }
5458
5459 slack = rhs - QUAD_TO_DBL(consdata->minactivity);
5460
5461 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5462 * it to zero
5463 */
5464 if( !SCIPisPositive(scip, slack) )
5465 slack = 0.0;
5466
5467 alpha = val * (ub - lb);
5469
5470 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5471 {
5472 SCIP_Real newub;
5473
5474 /* compute new upper bound */
5475 newub = lb + (slack / val);
5476
5477 SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_RHS, newub, ub, cutoff, nchgbds, force) );
5478
5479 if( *cutoff )
5480 {
5481 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5482 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5483
5484 return SCIP_OKAY;
5485 }
5486
5487 /* collect the new upper bound which is needed for the lower bound computation */
5488 ub = SCIPvarGetUbLocal(var);
5489 }
5490 }
5491
5492 /* check, if we can tighten the variable's lower bound */
5493 if( !SCIPisInfinity(scip, -lhs) )
5494 {
5495 SCIP_Real slack;
5497
5498 /* make sure the max activity is reliable */
5499 if( !consdata->validmaxact )
5500 {
5502 }
5503 assert(consdata->validmaxact);
5504
5505 /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5506 if( SCIPisFeasLT(scip, QUAD_TO_DBL(consdata->maxactivity), lhs) )
5507 {
5508 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5509 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->maxactivity), lhs);
5510
5511 *cutoff = TRUE;
5512 return SCIP_OKAY;
5513 }
5514
5515 slack = QUAD_TO_DBL(consdata->maxactivity) - lhs;
5516
5517 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5518 * it to zero
5519 */
5520 if( !SCIPisPositive(scip, slack) )
5521 slack = 0.0;
5522
5523 alpha = val * (ub - lb);
5525
5526 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5527 {
5528 SCIP_Real newlb;
5529
5530 /* compute new lower bound */
5531 newlb = ub - (slack / val);
5532
5533 SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_LHS, newlb, lb, cutoff, nchgbds, force) );
5534
5535 if( *cutoff )
5536 {
5537 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5538 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5539
5540 return SCIP_OKAY;
5541 }
5542 }
5543 }
5544 }
5545 else
5546 {
5547 /* check, if we can tighten the variable's lower bound */
5548 if( !SCIPisInfinity(scip, rhs) )
5549 {
5550 SCIP_Real slack;
5552
5553 /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
5554 assert(consdata->validminact);
5555
5556 /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5557 if( SCIPisFeasLT(scip, rhs, QUAD_TO_DBL(consdata->minactivity)) )
5558 {
5559 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5560 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->minactivity), rhs);
5561
5562 *cutoff = TRUE;
5563 return SCIP_OKAY;
5564 }
5565
5566 slack = rhs - QUAD_TO_DBL(consdata->minactivity);
5567
5568 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5569 * it to zero
5570 */
5571 if( !SCIPisPositive(scip, slack) )
5572 slack = 0.0;
5573
5574 alpha = val * (lb - ub);
5576
5577 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5578 {
5579 SCIP_Real newlb;
5580
5581 /* compute new lower bound */
5582 newlb = ub + slack / val;
5583
5584 SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_RHS, newlb, lb, cutoff, nchgbds, force) );
5585
5586 if( *cutoff )
5587 {
5588 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5589 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5590
5591 return SCIP_OKAY;
5592 }
5593 /* collect the new lower bound which is needed for the upper bound computation */
5594 lb = SCIPvarGetLbLocal(var);
5595 }
5596 }
5597
5598 /* check, if we can tighten the variable's upper bound */
5599 if( !SCIPisInfinity(scip, -lhs) )
5600 {
5601 SCIP_Real slack;
5603
5604 /* make sure the max activity is reliable */
5605 if( !consdata->validmaxact )
5606 {
5608 }
5609 assert(consdata->validmaxact);
5610
5611 /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5612 if( SCIPisFeasLT(scip, QUAD_TO_DBL(consdata->maxactivity), lhs) )
5613 {
5614 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5615 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->maxactivity), lhs);
5616
5617 *cutoff = TRUE;
5618 return SCIP_OKAY;
5619 }
5620
5621 slack = QUAD_TO_DBL(consdata->maxactivity) - lhs;
5622
5623 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5624 * it to zero
5625 */
5626 if( !SCIPisPositive(scip, slack) )
5627 slack = 0.0;
5628
5629 alpha = val * (lb - ub);
5631
5632 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5633 {
5634 SCIP_Real newub;
5635
5636 /* compute new upper bound */
5637 newub = lb - (slack / val);
5638
5639 SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_LHS, newub, ub, cutoff, nchgbds, force) );
5640
5641 if( *cutoff )
5642 {
5643 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5644 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5645
5646 return SCIP_OKAY;
5647 }
5648 }
5649 }
5650 }
5651
5652 return SCIP_OKAY;
5653}
5654
5655/** analyzes conflicting bounds on given ranged row constraint, and adds conflict constraint to problem */
5656static
5658 SCIP* scip, /**< SCIP data structure */
5659 SCIP_CONS* cons, /**< conflict detecting constraint */
5660 SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5661 int nvars, /**< number of variables reasoning the infeasibility */
5662 SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5663 SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5664 )
5665{
5666#ifndef NDEBUG
5667 SCIP_CONSDATA* consdata;
5668
5669 assert(scip != NULL);
5670 assert(cons != NULL);
5671
5672 consdata = SCIPconsGetData(cons);
5673 assert(consdata != NULL);
5674 assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5675#endif
5676
5677 /* conflict analysis can only be applied in solving stage and if it is turned on */
5679 return SCIP_OKAY;
5680
5681 /* initialize conflict analysis */
5683
5684 /* add the conflicting fixed variables of this ranged row constraint to conflict candidate queue */
5686
5687 /* add reasoning variables to conflict candidate queue which led to the conflict */
5689
5690 /* analyze the conflict */
5692
5693 return SCIP_OKAY;
5694}
5695
5696/** propagate ranged rows
5697 *
5698 * Check ranged rows for possible solutions, possibly detect infeasibility, fix variables due to having only one possible
5699 * solution, tighten bounds if having only two possible solutions or add constraints which propagate a subset of
5700 * variables better.
5701 *
5702 * Example:
5703 * c1: 12 x1 + 9 x2 - x3 = 0 with x1, x2 free and 1 <= x3 <= 2
5704 *
5705 * x3 needs to be a multiple of 3, so the instance is infeasible.
5706 *
5707 * Example:
5708 * c1: 12 x1 + 9 x2 - x3 = 1 with x1, x2 free and 1 <= x3 <= 2
5709 *
5710 * The only possible value for x3 is 2, so the variable will be fixed.
5711 *
5712 * @todo add holes if possible
5713 */
5714static
5716 SCIP* scip, /**< SCIP data structure */
5717 SCIP_CONS* cons, /**< linear constraint */
5718 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
5719 int* nfixedvars, /**< pointer to count number of fixed variables */
5720 int* nchgbds, /**< pointer to count the number of bound changes */
5721 int* naddconss /**< pointer to count number of added constraints */
5722 )
5723{
5724 SCIP_CONSHDLRDATA* conshdlrdata;
5725 SCIP_CONSHDLR* conshdlr;
5726 SCIP_CONSDATA* consdata;
5727 SCIP_VAR** infcheckvars;
5728 SCIP_Real* infcheckvals;
5729 SCIP_Real minactinfvars;
5730 SCIP_Real maxactinfvars;
5731 SCIP_Real lb;
5732 SCIP_Real ub;
5733 SCIP_Real feastol;
5734 SCIP_Real fixedact;
5735 SCIP_Real lhs;
5736 SCIP_Real rhs;
5737 SCIP_Real absminbincoef;
5738 SCIP_Longint gcd;
5739 SCIP_Longint gcdtmp;
5740 SCIP_Bool minactinfvarsinvalid;
5741 SCIP_Bool maxactinfvarsinvalid;
5742 SCIP_Bool possiblegcd;
5743 SCIP_Bool gcdisone;
5744 SCIP_Bool addartconss;
5745 int ninfcheckvars;
5746 int nunfixedvars;
5747 int nfixedconsvars;
5748 int ncontvars;
5749 int pos;
5750 int v;
5751
5752 assert(scip != NULL);
5753 assert(cons != NULL);
5754 assert(cutoff != NULL);
5755 assert(nfixedvars != NULL);
5756 assert(nchgbds != NULL);
5757 assert(naddconss != NULL);
5758
5759 /* modifiable constraint can be changed so we do not have all necessary information */
5760 if( SCIPconsIsModifiable(cons) )
5761 return SCIP_OKAY;
5762
5763 consdata = SCIPconsGetData(cons);
5764 assert(consdata != NULL);
5765
5766 /* we already did full ranged row propagation */
5767 if( consdata->rangedrowpropagated == 2 )
5768 return SCIP_OKAY;
5769
5770 /* at least three variables are needed */
5771 if( consdata->nvars < 3 )
5772 return SCIP_OKAY;
5773
5774 /* do nothing on normal inequalities */
5775 if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
5776 return SCIP_OKAY;
5777
5778 /* get constraint handler data */
5779 conshdlr = SCIPconsGetHdlr(cons);
5780 assert(conshdlr != NULL);
5781 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5782 assert(conshdlrdata != NULL);
5783
5784 addartconss = conshdlrdata->rangedrowartcons && SCIPgetDepth(scip) < 1 && !SCIPinProbing(scip) && !SCIPinRepropagation(scip);
5785
5786 /* we may add artificial constraints */
5787 if( addartconss )
5788 consdata->rangedrowpropagated = 2;
5789 /* we are not allowed to add artificial constraints during propagation; if nothing changed on this constraint since
5790 * the last rangedrowpropagation, we can stop; otherwise, we mark this constraint to be rangedrowpropagated without
5791 * artificial constraints
5792 */
5793 else
5794 {
5795 if( consdata->rangedrowpropagated > 0 )
5796 return SCIP_OKAY;
5797
5798 consdata->rangedrowpropagated = 1;
5799 }
5800
5801 fixedact = 0;
5802 nfixedconsvars = 0;
5803
5804 /* calculate fixed activity and number of fixed variables */
5805 for( v = consdata->nvars - 1; v >= 0; --v )
5806 {
5807 /* all zero coefficients should be eliminated */
5808 assert(!SCIPisZero(scip, consdata->vals[v]));
5809
5810 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5811 {
5812 fixedact += SCIPvarGetLbLocal(consdata->vars[v]) * consdata->vals[v];
5813 ++nfixedconsvars;
5814 }
5815 }
5816
5817 /* do not work with huge fixed activities */
5818 if( SCIPisHugeValue(scip, REALABS(fixedact)) )
5819 return SCIP_OKAY;
5820
5821 /* compute lhs and rhs for unfixed variables only and get number of unfixed variables */
5822 assert(!SCIPisInfinity(scip, -fixedact) && !SCIPisInfinity(scip, fixedact));
5823 lhs = consdata->lhs - fixedact;
5824 rhs = consdata->rhs - fixedact;
5825 nunfixedvars = consdata->nvars - nfixedconsvars;
5826
5827 /* allocate temporary memory for variables and coefficients which may lead to infeasibility */
5828 SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvars, nunfixedvars) );
5829 SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvals, nunfixedvars) );
5830
5831 absminbincoef = SCIP_REAL_MAX;
5832 ncontvars = 0;
5833 gcdisone = TRUE;
5834 possiblegcd = TRUE;
5835
5836 /* we now partition all unfixed variables in two groups:
5837 *
5838 * The first one contains all integral variables with integral coefficient so that all variables in this group will
5839 * have a gcd greater than 1. This group will be implicitly given.
5840 *
5841 * The second group will contain all left unfixed variables and will be saved as infcheckvars with corresponding
5842 * coefficients as infcheckvals. The order of these variables should be the same as in the consdata object.
5843 */
5844
5845 /* first find integral variables with integral coefficient greater than 1, thereby collecting all other unfixed
5846 * variables
5847 */
5848 ninfcheckvars = 0;
5849 v = -1;
5850 pos = -1;
5851 do
5852 {
5853 ++v;
5854
5855 /* partition the variables, do not change the order of collection, because it might be used later on */
5856 while( v < consdata->nvars && ( !SCIPvarIsIntegral(consdata->vars[v])
5857 || !SCIPisIntegral(scip, consdata->vals[v]) || SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0) ) )
5858 {
5859 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5860 {
5861 if( !SCIPvarIsIntegral(consdata->vars[v]) )
5862 ++ncontvars;
5863 else if( SCIPvarIsBinary(consdata->vars[v]) )
5864 {
5865 SCIP_Real absval;
5866
5867 absval = REALABS(consdata->vals[v]);
5868
5869 if( absminbincoef > absval )
5870 absminbincoef = absval;
5871 }
5872
5873 gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5874 possiblegcd = FALSE;
5875 infcheckvars[ninfcheckvars] = consdata->vars[v];
5876 infcheckvals[ninfcheckvars] = consdata->vals[v];
5877 ++ninfcheckvars;
5878
5879 if( pos == -1 )
5880 pos = v;
5881 }
5882 ++v;
5883 }
5884 }
5885 while( v < consdata->nvars && SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) );
5886
5887 /* if the first group of variables is empty, we stop */
5888 /* @todo try to propagate/split up a constraint of the form:
5889 * x_1 + ... + x_m + a_1*y_1 + ... + a_n*y_n = k + c,
5890 * 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]
5891 */
5892 if( v == consdata->nvars )
5893 goto TERMINATE;
5894
5895 /* we need at least two non-continuous variables */
5896 if( ncontvars + 2 > nunfixedvars )
5897 goto TERMINATE;
5898
5899 assert(!SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])));
5900 assert(SCIPvarIsIntegral(consdata->vars[v]) && SCIPisIntegral(scip, consdata->vals[v]) && REALABS(consdata->vals[v]) > 1.5);
5901
5902 feastol = SCIPfeastol(scip);
5903
5904 gcd = (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol);
5905 assert(gcd >= 2);
5906
5907 /* go on to partition the variables, do not change the order of collection, because it might be used later on;
5908 * calculate gcd over the first part of variables */
5909 for( ; v < consdata->nvars; ++v )
5910 {
5911 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5912 continue;
5913
5914 if( SCIPvarIsBinary(consdata->vars[v]) )
5915 {
5916 SCIP_Real absval;
5917
5918 absval = REALABS(consdata->vals[v]);
5919
5920 if( absminbincoef > absval )
5921 absminbincoef = absval;
5922 }
5923
5924 if( !SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v])
5925 || SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0) )
5926 {
5927 if( !SCIPvarIsIntegral(consdata->vars[v]) )
5928 ++ncontvars;
5929
5930 gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5931 possiblegcd = FALSE;
5932 infcheckvars[ninfcheckvars] = consdata->vars[v];
5933 infcheckvals[ninfcheckvars] = consdata->vals[v];
5934
5935 ++ninfcheckvars;
5936
5937 if( pos == -1 )
5938 pos = v;
5939 }
5940 else
5941 {
5942 assert(REALABS(consdata->vals[v]) > 1.5);
5943
5944 gcdtmp = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol));
5945 assert(gcdtmp >= 1);
5946
5947 if( gcdtmp == 1 )
5948 {
5949 infcheckvars[ninfcheckvars] = consdata->vars[v];
5950 infcheckvals[ninfcheckvars] = consdata->vals[v];
5951
5952 ++ninfcheckvars;
5953
5954 if( pos == -1 )
5955 pos = v;
5956 }
5957 else
5958 gcd = gcdtmp;
5959 }
5960 }
5961 assert(gcd >= 2);
5962
5963 /* it should not happen that all variables are of integral type and have a gcd >= 2, this should be done by
5964 * normalizeCons() */
5965 if( ninfcheckvars == 0 )
5966 goto TERMINATE;
5967
5968 assert(pos >= 0);
5969
5970 minactinfvarsinvalid = FALSE;
5971 maxactinfvarsinvalid = FALSE;
5972 maxactinfvars = 0.0;
5973 minactinfvars = 0.0;
5974
5975 /* calculate activities over all infcheckvars */
5976 for( v = ninfcheckvars - 1; v >= 0; --v )
5977 {
5978 lb = SCIPvarGetLbLocal(infcheckvars[v]);
5979 ub = SCIPvarGetUbLocal(infcheckvars[v]);
5980
5981 if( SCIPisInfinity(scip, -lb) )
5982 {
5983 if( infcheckvals[v] < 0.0 )
5984 maxactinfvarsinvalid = TRUE;
5985 else
5986 minactinfvarsinvalid = TRUE;
5987 }
5988 else
5989 {
5990 if( infcheckvals[v] < 0.0 )
5991 maxactinfvars += infcheckvals[v] * lb;
5992 else
5993 minactinfvars += infcheckvals[v] * lb;
5994 }
5995
5996 if( SCIPisInfinity(scip, ub) )
5997 {
5998 if( infcheckvals[v] > 0.0 )
5999 maxactinfvarsinvalid = TRUE;
6000 else
6001 minactinfvarsinvalid = TRUE;
6002 }
6003 else
6004 {
6005 if( infcheckvals[v] > 0.0 )
6006 maxactinfvars += infcheckvals[v] * ub;
6007 else
6008 minactinfvars += infcheckvals[v] * ub;
6009 }
6010
6011 /* better abort on to big values */
6012 if( SCIPisHugeValue(scip, -minactinfvars) )
6013 minactinfvarsinvalid = TRUE;
6014 if( SCIPisHugeValue(scip, maxactinfvars) )
6015 maxactinfvarsinvalid = TRUE;
6016
6017 if( minactinfvarsinvalid || maxactinfvarsinvalid )
6018 goto TERMINATE;
6019 }
6020 assert(!minactinfvarsinvalid && !maxactinfvarsinvalid);
6021
6022 SCIPdebugMsg(scip, "minactinfvarsinvalid = %u, minactinfvars = %g, maxactinfvarsinvalid = %u, maxactinfvars = %g, gcd = %lld, ninfcheckvars = %d, ncontvars = %d\n",
6023 minactinfvarsinvalid, minactinfvars, maxactinfvarsinvalid, maxactinfvars, gcd, ninfcheckvars, ncontvars);
6024
6025 /* @todo maybe we took the wrong variables as infcheckvars - we could try to exchange integer variables */
6026 /* @todo if minactinfvarsinvalid or maxactinfvarsinvalid are true, try to exchange both partitions to maybe get valid
6027 * activities */
6028 /* @todo calculate minactivity and maxactivity for all non-intcheckvars, and use this for better bounding,
6029 * !!!note!!!
6030 * that therefore the conflict variables in addConflictFixedVars() need to be extended by all variables which
6031 * are not at their global bound
6032 */
6033
6034 /* check if between left hand side and right hand side there exists a feasible point, if not, the constraint leads to
6035 * infeasibility */
6036 if( !SCIPisIntegral(scip, (lhs - maxactinfvars) / gcd) &&
6037 SCIPisGT(scip, SCIPceil(scip, (lhs - maxactinfvars) / gcd) * gcd, rhs - minactinfvars) )
6038 {
6039 SCIPdebugMsg(scip, "no feasible value exists, constraint <%s> leads to infeasibility", SCIPconsGetName(cons));
6041
6042 /* start conflict analysis */
6043 /* @todo improve conflict analysis by adding relaxed bounds */
6044 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6045
6046 *cutoff = TRUE;
6047 }
6048 else if( ncontvars == 0 )
6049 {
6050 SCIP_Longint gcdinfvars = -1;
6051
6052 /* check for gcd over all infcheckvars */
6053 if( possiblegcd )
6054 {
6055 v = ninfcheckvars - 1;
6056 gcdinfvars = (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol);
6057 assert(gcdinfvars >= 2);
6058
6059 for( ; v >= 0 && gcdinfvars >= 2; --v )
6060 {
6061 gcdinfvars = SCIPcalcGreComDiv(gcdinfvars, (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol));
6062 }
6063 }
6064 else if( gcdisone )
6065 gcdinfvars = 1;
6066
6067 SCIPdebugMsg(scip, "gcdinfvars =%lld, possiblegcd = %u\n", gcdinfvars, possiblegcd);
6068
6069 /* compute solutions for this ranged row, if all variables are of integral type with integral coefficients */
6070 if( gcdinfvars >= 1 )
6071 {
6072 SCIP_Real value;
6073 SCIP_Real value2;
6074 SCIP_Real minvalue = SCIP_INVALID;
6075 SCIP_Real maxvalue = SCIP_INVALID;
6076 int nsols = 0;
6077
6078 value = SCIPceil(scip, minactinfvars - SCIPfeastol(scip));
6079
6080 /* check how many possible solutions exist */
6081 while( SCIPisLE(scip, value, maxactinfvars) )
6082 {
6083 value2 = value + gcd * (SCIPceil(scip, (lhs - value) / gcd));
6084
6085 /* value2 might violate lhs due to numerics, in this case take the next divisible number */
6086 if( !SCIPisGE(scip, value2, lhs) )
6087 {
6088 value2 += gcd;
6089 }
6090
6091 if( SCIPisLE(scip, value2, rhs) )
6092 {
6093 ++nsols;
6094
6095 /* early termination if we found more than two solutions */
6096 if( nsols == 3 )
6097 break;
6098
6099 if( minvalue == SCIP_INVALID ) /*lint !e777*/
6100 minvalue = value;
6101
6102 maxvalue = value;
6103 }
6104 value += gcdinfvars;
6105 }
6106 assert(nsols < 2 || minvalue <= maxvalue);
6107
6108 /* determine last possible solution for better bounding */
6109 if( nsols == 3 )
6110 {
6111#ifndef NDEBUG
6112 SCIP_Real secondsolval = maxvalue;
6113#endif
6114 value = SCIPfloor(scip, maxactinfvars + SCIPfeastol(scip));
6115
6116 /* check how many possible solutions exist */
6117 while( SCIPisGE(scip, value, minactinfvars) )
6118 {
6119 value2 = value + gcd * (SCIPfloor(scip, (rhs - value) / gcd));
6120
6121 /* value2 might violate rhs due to numerics, in this case take the next divisible number */
6122 if( !SCIPisLE(scip, value2, rhs) )
6123 {
6124 value2 -= gcd;
6125 }
6126
6127 if( SCIPisGE(scip, value2, lhs) )
6128 {
6129 maxvalue = value;
6130 assert(maxvalue > minvalue);
6131 break;
6132 }
6133 value -= gcdinfvars;
6134 }
6135 assert(maxvalue > secondsolval);
6136 }
6137
6138 SCIPdebugMsg(scip, "here nsols %s %d, minsolvalue = %g, maxsolvalue = %g, ninfcheckvars = %d, nunfixedvars = %d\n",
6139 nsols > 2 ? ">=" : "=", nsols, minvalue, maxvalue, ninfcheckvars, nunfixedvars);
6140
6141 /* no possible solution found */
6142 if( nsols == 0 )
6143 {
6144 SCIPdebugMsg(scip, "gcdinfvars = %lld, gcd = %lld, correctedlhs = %g, correctedrhs = %g\n",
6145 gcdinfvars, gcd, lhs, rhs);
6146 SCIPdebugMsg(scip, "no solution found; constraint <%s> leads to infeasibility\n", SCIPconsGetName(cons));
6148
6149 /* start conflict analysis */
6150 /* @todo improve conflict analysis by adding relaxed bounds */
6151 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6152
6153 *cutoff = TRUE;
6154 }
6155 /* if only one solution exists, we can extract a new constraint or fix variables */
6156 else if( nsols == 1 )
6157 {
6158 assert(minvalue == maxvalue); /*lint !e777*/
6159
6160 /* we can fix the only variable in our second set of variables */
6161 if( ninfcheckvars == 1 )
6162 {
6163 SCIP_Bool fixed;
6164
6165 assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6166
6167 SCIPdebugMsg(scip, "fixing single variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6168 SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]),
6169 SCIPvarGetUbLocal(infcheckvars[0]), maxvalue/infcheckvals[0]);
6170
6171 /* fix variable to only possible value */
6172 SCIP_CALL( SCIPinferVarFixCons(scip, infcheckvars[0], maxvalue/infcheckvals[0], cons,
6173 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &fixed) );
6174
6175 if( *cutoff )
6176 {
6177 /* start conflict analysis */
6178 /* @todo improve conflict analysis by adding relaxed bounds */
6179 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6180 }
6181
6182 if( fixed )
6183 ++(*nfixedvars);
6184 }
6185 else
6186 {
6187 /* check for exactly one unfixed variable which is not part of the infcheckvars */
6188 if( ninfcheckvars == nunfixedvars - 1 )
6189 {
6191 SCIP_Bool foundvar = FALSE;
6192 SCIP_Bool fixed;
6193 int w = 0;
6194
6195 assert(ninfcheckvars > 0);
6196
6197 /* find variable which is not an infcheckvar and fix it */
6198 for( v = 0; v < consdata->nvars - 1; ++v )
6199 {
6200 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6201 {
6202 if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6203 {
6204#ifndef NDEBUG
6205 int v2 = v + 1;
6206 int w2 = w;
6207
6208 assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6209
6210 for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6211 {
6212 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6213 continue;
6214
6215 assert(consdata->vars[v2] == infcheckvars[w2]);
6216 ++w2;
6217 }
6218 assert(w2 == ninfcheckvars);
6219#endif
6220 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6221
6222 foundvar = TRUE;
6223
6224 if( consdata->vals[v] < 0 )
6225 {
6226 bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6227 }
6228 else
6229 {
6230 bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6231 }
6232
6233 SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6234 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6235 SCIPvarGetUbLocal(consdata->vars[v]), bound);
6236
6237 /* fix variable to only possible value */
6238 SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6240
6241 if( *cutoff )
6242 {
6243 /* start conflict analysis */
6244 /* @todo improve conflict analysis by adding relaxed bounds */
6245 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6246 consdata->vars[v], bound) );
6247 }
6248
6249 if( fixed )
6250 ++(*nfixedvars);
6251
6252 break;
6253 }
6254
6255 ++w;
6256 }
6257 }
6258
6259 /* maybe last variable was the not infcheckvar */
6260 if( !foundvar )
6261 {
6262 assert(v == consdata->nvars - 1);
6263 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6264
6265 if( consdata->vals[v] < 0 )
6266 {
6267 bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6268 }
6269 else
6270 {
6271 bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6272 }
6273
6274 SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6275 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6276 SCIPvarGetUbLocal(consdata->vars[v]), bound);
6277
6278 /* fix variable to only possible value */
6279 SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6281
6282 if( *cutoff )
6283 {
6284 /* start conflict analysis */
6285 /* @todo improve conflict analysis by adding relaxed bounds */
6286 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6287 consdata->vars[v], bound) );
6288 }
6289
6290 if( fixed )
6291 ++(*nfixedvars);
6292 }
6293 }
6294 else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6295 {
6296 /* aggregation possible if we have two variables, but this will be done later on */
6297 SCIP_CONS* newcons;
6298 char name[SCIP_MAXSTRLEN];
6299
6300 /* create, add, and release new artificial constraint */
6301 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6302 ++conshdlrdata->naddconss;
6303
6304 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6305
6306 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals,
6307 maxvalue, maxvalue, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6308 SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6309
6310 SCIPdebugPrintCons(scip, newcons, NULL);
6311
6312 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6313
6314 ++(*naddconss);
6315 }
6316 }
6317 }
6318 /* at least two solutions */
6319 else
6320 {
6321 /* @todo If we found more than one solution, can we reduce domains due to dualpresolving? */
6322
6323 /* only one variable in the second set, so we can bound this variables */
6324 if( ninfcheckvars == 1 )
6325 {
6326 SCIP_Bool tightened;
6327 SCIP_Real newlb;
6328 SCIP_Real newub;
6329
6330 assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6331
6332 if( infcheckvals[0] < 0 )
6333 {
6334 newlb = maxvalue/infcheckvals[0];
6335 newub = minvalue/infcheckvals[0];
6336 }
6337 else
6338 {
6339 newlb = minvalue/infcheckvals[0];
6340 newub = maxvalue/infcheckvals[0];
6341 }
6342 assert(newlb < newub);
6343
6344 if( newlb > SCIPvarGetLbLocal(infcheckvars[0]) )
6345 {
6346 /* update lower bound of variable */
6347 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6348 SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]), newlb);
6349
6350 /* tighten variable lower bound to minimal possible value */
6351 SCIP_CALL( SCIPinferVarLbCons(scip, infcheckvars[0], newlb, cons,
6352 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6353
6354 if( *cutoff )
6355 {
6356 /* start conflict analysis */
6357 /* @todo improve conflict analysis by adding relaxed bounds */
6358 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6359 }
6360
6361 if( tightened )
6362 ++(*nchgbds);
6363 }
6364
6365 if( newub < SCIPvarGetUbLocal(infcheckvars[0]) )
6366 {
6367 /* update upper bound of variable */
6368 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6369 SCIPvarGetName(infcheckvars[0]), SCIPvarGetUbLocal(infcheckvars[0]), newub);
6370
6371 /* tighten variable upper bound to maximal possible value */
6372 SCIP_CALL( SCIPinferVarUbCons(scip, infcheckvars[0], newub, cons,
6373 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6374
6375 if( *cutoff )
6376 {
6377 /* start conflict analysis */
6378 /* @todo improve conflict analysis by adding relaxed bounds */
6379 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6380 }
6381
6382 if( tightened )
6383 ++(*nchgbds);
6384 }
6385 }
6386 /* check if we have only one variable not in infcheckvars, if so we can tighten this variable */
6387 else if( ninfcheckvars == nunfixedvars - 1 )
6388 {
6389 SCIP_Bool foundvar = FALSE;
6390 SCIP_Bool tightened;
6391 SCIP_Real newlb;
6392 SCIP_Real newub;
6393 int w = 0;
6394
6395 assert(ninfcheckvars > 0);
6396 assert(minvalue < maxvalue);
6397
6398 /* find variable which is not an infcheckvar and fix it */
6399 for( v = 0; v < consdata->nvars - 1; ++v )
6400 {
6401 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6402 {
6403 if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6404 {
6405#ifndef NDEBUG
6406 int v2 = v + 1;
6407 int w2 = w;
6408
6409 assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6410
6411 for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6412 {
6413 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6414 continue;
6415
6416 assert(consdata->vars[v2] == infcheckvars[w2]);
6417 ++w2;
6418 }
6419 assert(w2 == ninfcheckvars);
6420#endif
6421
6422 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6423 foundvar = TRUE;
6424
6425 if( consdata->vals[v] < 0 )
6426 {
6427 newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6428 newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6429 }
6430 else
6431 {
6432 newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6433 newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6434 }
6435 assert(SCIPisLE(scip, newlb, newub));
6436
6437 if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6438 {
6439 /* update lower bound of variable */
6440 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6441 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6442
6443 /* tighten variable lower bound to minimal possible value */
6444 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6445 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6446
6447 if( *cutoff )
6448 {
6449 /* start conflict analysis */
6450 /* @todo improve conflict analysis by adding relaxed bounds */
6451 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6452 consdata->vars[v], newlb) );
6453 }
6454
6455 if( tightened )
6456 ++(*nchgbds);
6457 }
6458
6459 if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6460 {
6461 /* update upper bound of variable */
6462 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6463 SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6464
6465 /* tighten variable upper bound to maximal possible value */
6466 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6467 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6468
6469 if( *cutoff )
6470 {
6471 /* start conflict analysis */
6472 /* @todo improve conflict analysis by adding relaxed bounds */
6473 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6474 consdata->vars[v], newub) );
6475 }
6476
6477 if( tightened )
6478 ++(*nchgbds);
6479 }
6480
6481 break;
6482 }
6483
6484 ++w;
6485 }
6486 }
6487
6488 /* maybe last variable was the not infcheckvar */
6489 if( !foundvar )
6490 {
6491 assert(v == consdata->nvars - 1);
6492 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6493
6494 if( consdata->vals[v] < 0 )
6495 {
6496 newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6497 newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6498 }
6499 else
6500 {
6501 newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6502 newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6503 }
6504 assert(SCIPisLE(scip, newlb, newub));
6505
6506 if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6507 {
6508 /* update lower bound of variable */
6509 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6510 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6511
6512 /* tighten variable lower bound to minimal possible value */
6513 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6514 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6515
6516 if( *cutoff )
6517 {
6518 /* start conflict analysis */
6519 /* @todo improve conflict analysis by adding relaxed bounds */
6520 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newlb) );
6521 }
6522
6523 if( tightened )
6524 ++(*nchgbds);
6525 }
6526
6527 if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6528 {
6529 /* update upper bound of variable */
6530 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6531 SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6532
6533 /* tighten variable upper bound to maximal possible value */
6534 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6535 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6536
6537 if( *cutoff )
6538 {
6539 /* start conflict analysis */
6540 /* @todo improve conflict analysis by adding relaxed bounds */
6541 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newub) );
6542 }
6543
6544 if( tightened )
6545 ++(*nchgbds);
6546 }
6547 }
6548 }
6549 /* at least two solutions and more than one variable, so we add a new constraint which bounds the feasible
6550 * region for our infcheckvars, if possible
6551 */
6552 else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6553 {
6554 SCIP_CONS* newcons;
6555 char name[SCIP_MAXSTRLEN];
6556 SCIP_Real newlhs;
6557 SCIP_Real newrhs;
6558
6559 assert(maxvalue > minvalue);
6560
6561 if( SCIPisGT(scip, minvalue, minactinfvars) )
6562 newlhs = minvalue;
6563 else
6564 newlhs = -SCIPinfinity(scip);
6565
6566 if( SCIPisLT(scip, maxvalue, maxactinfvars) )
6567 newrhs = maxvalue;
6568 else
6569 newrhs = SCIPinfinity(scip);
6570
6571 if( !SCIPisInfinity(scip, -newlhs) || !SCIPisInfinity(scip, newrhs) )
6572 {
6573 /* create, add, and release new artificial constraint */
6574 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons1_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6575 ++conshdlrdata->naddconss;
6576
6577 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6578
6579 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6581 SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6582
6583 SCIPdebugPrintCons(scip, newcons, NULL);
6584 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6585
6586 ++(*naddconss);
6587 }
6588 /* @todo maybe add constraint for all variables which are not infcheckvars, lhs should be minvalue, rhs
6589 * should be maxvalue */
6590 }
6591 }
6592 }
6593 }
6594 else if( addartconss && ncontvars < ninfcheckvars )
6595 {
6596 SCIP_Real maxact = 0.0;
6597 SCIP_Real minact = 0.0;
6598 int w = 0;
6599
6600 /* compute activities of non-infcheckvars */
6601 for( v = 0; v < consdata->nvars; ++v )
6602 {
6603 if( w < ninfcheckvars && consdata->vars[v] == infcheckvars[w] )
6604 {
6605 ++w;
6606 continue;
6607 }
6608
6609 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6610 {
6611 if( SCIPvarIsBinary(consdata->vars[v]) )
6612 {
6613 if( consdata->vals[v] > 0.0 )
6614 maxact += consdata->vals[v];
6615 else
6616 minact += consdata->vals[v];
6617 }
6618 else
6619 {
6620 SCIP_Real tmpval;
6621
6622 assert(SCIPvarIsIntegral(consdata->vars[v]));
6623
6624 if( consdata->vals[v] > 0.0 )
6625 {
6626 tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6627
6628 if( SCIPisHugeValue(scip, -tmpval) )
6629 break;
6630
6631 minact += tmpval;
6632
6633 tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6634
6635 if( SCIPisHugeValue(scip, tmpval) )
6636 break;
6637
6638 maxact += tmpval;
6639 }
6640 else
6641 {
6642 tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6643
6644 if( SCIPisHugeValue(scip, -tmpval) )
6645 break;
6646
6647 minact += tmpval;
6648
6649 tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6650
6651 if( SCIPisHugeValue(scip, tmpval) )
6652 break;
6653
6654 maxact += tmpval;
6655 }
6656 }
6657 }
6658 }
6659
6660 if( v == consdata->nvars && !SCIPisHugeValue(scip, -minact) && !SCIPisHugeValue(scip, maxact) )
6661 {
6662 SCIP_CONS* newcons;
6663 char name[SCIP_MAXSTRLEN];
6664 SCIP_Real newlhs;
6665 SCIP_Real newrhs;
6666
6667 assert(maxact > minact);
6668 assert(w == ninfcheckvars);
6669
6670 newlhs = lhs - maxact;
6671 newrhs = rhs - minact;
6672 assert(newlhs < newrhs);
6673
6674 /* create, add, and release new artificial constraint */
6675 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons2_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6676 ++conshdlrdata->naddconss;
6677
6678 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6679
6680 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6682 SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6683
6684 SCIPdebugPrintCons(scip, newcons, NULL);
6685 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6686
6687 ++(*naddconss);
6688 }
6689 }
6690
6691 TERMINATE:
6692 SCIPfreeBufferArray(scip, &infcheckvals);
6693 SCIPfreeBufferArray(scip, &infcheckvars);
6694
6695 return SCIP_OKAY;
6696}
6697
6698/** tightens bounds of a single variable due to activity bounds */
6699static
6701 SCIP* scip, /**< SCIP data structure */
6702 SCIP_CONS* cons, /**< linear constraint */
6703 int pos, /**< position of the variable in the vars array */
6704 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6705 int* nchgbds, /**< pointer to count the total number of tightened bounds */
6706 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
6707 )
6708{
6709 SCIP_CONSDATA* consdata;
6710 SCIP_VAR* var;
6711 SCIP_Real val;
6712 SCIP_Real lb;
6713 SCIP_Real ub;
6714 SCIP_Real minresactivity;
6715 SCIP_Real maxresactivity;
6716 SCIP_Real lhs;
6717 SCIP_Real rhs;
6718 SCIP_Bool infeasible;
6719 SCIP_Bool tightened;
6720 SCIP_Bool ismintight;
6721 SCIP_Bool ismaxtight;
6722 SCIP_Bool isminsettoinfinity;
6723 SCIP_Bool ismaxsettoinfinity;
6724
6725 assert(scip != NULL);
6726 assert(cons != NULL);
6727 assert(cutoff != NULL);
6728 assert(nchgbds != NULL);
6729
6730 /* we cannot tighten variables' bounds, if the constraint may be not complete */
6731 if( SCIPconsIsModifiable(cons) )
6732 return SCIP_OKAY;
6733
6734 consdata = SCIPconsGetData(cons);
6735 assert(consdata != NULL);
6736 assert(0 <= pos && pos < consdata->nvars);
6737
6738 *cutoff = FALSE;
6739
6740 var = consdata->vars[pos];
6741
6742 /* we cannot tighten bounds of multi-aggregated variables */
6744 return SCIP_OKAY;
6745
6746 val = consdata->vals[pos];
6747 lhs = consdata->lhs;
6748 rhs = consdata->rhs;
6749 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
6750 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
6751 assert(var != NULL);
6752 assert(!SCIPisZero(scip, val));
6753 assert(!SCIPisInfinity(scip, lhs));
6754 assert(!SCIPisInfinity(scip, -rhs));
6755
6756 lb = SCIPvarGetLbLocal(var);
6757 ub = SCIPvarGetUbLocal(var);
6758 assert(SCIPisLE(scip, lb, ub));
6759
6760 if( val > 0.0 )
6761 {
6762 /* check, if we can tighten the variable's bounds reliably, therefore only consider sides which are small or
6763 * relatively different to the residual activity bound to avoid cancellation leading to numerical difficulties
6764 */
6765 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && ismintight
6766 && ( SCIPisLT(scip, ABS(rhs), 1.0) || !SCIPisEQ(scip, minresactivity / rhs, 1.0) ) )
6767 {
6768 SCIP_Real newub;
6769
6770 newub = (rhs - minresactivity)/val;
6771
6772 if( !SCIPisInfinity(scip, newub) &&
6773 ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6774 {
6775 SCIP_Bool activityunreliable;
6776 activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6777
6778 /* check minresactivities for reliability */
6779 if( activityunreliable )
6780 {
6781 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6782 newub = (rhs - minresactivity)/val;
6783 activityunreliable = SCIPisInfinity(scip, -minresactivity) ||
6784 (!SCIPisUbBetter(scip, newub, lb, ub) && (!SCIPisFeasLT(scip, newub, ub) || !SCIPvarIsIntegral(var))
6785 && (!force || !SCIPisLT(scip, newub, ub)));
6786 }
6787
6788 if( !activityunreliable )
6789 {
6790 /* tighten upper bound */
6791 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
6792 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6793 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6794 &infeasible, &tightened) );
6795 if( infeasible )
6796 {
6797 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6798 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6799
6800 /* analyze conflict */
6802
6803 *cutoff = TRUE;
6804 return SCIP_OKAY;
6805 }
6806 if( tightened )
6807 {
6808 ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6809 assert(SCIPisFeasLE(scip, ub, newub));
6810 (*nchgbds)++;
6811
6812 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6813 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6814 }
6815 }
6816 }
6817 }
6818
6819 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && ismaxtight
6820 && ( SCIPisLT(scip, ABS(lhs), 1.0) || !SCIPisEQ(scip, maxresactivity / lhs, 1.0) ) )
6821 {
6822 SCIP_Real newlb;
6823
6824 newlb = (lhs - maxresactivity)/val;
6825 if( !SCIPisInfinity(scip, -newlb) &&
6826 ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6827 {
6828 /* check maxresactivities for reliability */
6829 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6830 {
6831 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6832 newlb = (lhs - maxresactivity)/val;
6833
6834 if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisLbBetter(scip, newlb, lb, ub)
6835 && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6836 && (!force || !SCIPisGT(scip, newlb, lb))) )
6837 return SCIP_OKAY;
6838 }
6839
6840 /* tighten lower bound */
6841 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6842 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6843 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6844 &infeasible, &tightened) );
6845 if( infeasible )
6846 {
6847 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6848 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6849
6850 /* analyze conflict */
6852
6853 *cutoff = TRUE;
6854 return SCIP_OKAY;
6855 }
6856 if( tightened )
6857 {
6858 lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6859 assert(SCIPisFeasGE(scip, lb, newlb));
6860 (*nchgbds)++;
6861 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6862 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6863 }
6864 }
6865 }
6866 }
6867 else
6868 {
6869 /* check, if we can tighten the variable's bounds reliably, therefore only consider sides which are small or
6870 * relatively different to the residual activity bound to avoid cancellation leading to numerical difficulties
6871 */
6872 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && ismintight
6873 && ( SCIPisLT(scip, ABS(rhs), 1.0) || !SCIPisEQ(scip, minresactivity / rhs, 1.0) ) )
6874 {
6875 SCIP_Real newlb;
6876
6877 newlb = (rhs - minresactivity)/val;
6878 if( !SCIPisInfinity(scip, -newlb) &&
6879 ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6880 {
6881 SCIP_Bool activityunreliable;
6882 activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6883 /* check minresactivities for reliability */
6884 if( activityunreliable )
6885 {
6886 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6887 newlb = (rhs - minresactivity)/val;
6888
6889 activityunreliable = SCIPisInfinity(scip, -minresactivity)
6890 || (!SCIPisLbBetter(scip, newlb, lb, ub) && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6891 && (!force || !SCIPisGT(scip, newlb, lb)));
6892 }
6893
6894 if( !activityunreliable )
6895 {
6896 /* tighten lower bound */
6897 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6898 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6899 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6900 &infeasible, &tightened) );
6901 if( infeasible )
6902 {
6903 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6904 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6905
6906 /* analyze conflict */
6908
6909 *cutoff = TRUE;
6910 return SCIP_OKAY;
6911 }
6912 if( tightened )
6913 {
6914 lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6915 assert(SCIPisFeasGE(scip, lb, newlb));
6916 (*nchgbds)++;
6917 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6918 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6919 }
6920 }
6921 }
6922 }
6923
6924 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && ismaxtight
6925 && ( SCIPisLT(scip, ABS(lhs), 1.0) || !SCIPisEQ(scip, maxresactivity / lhs, 1.0) ) )
6926 {
6927 SCIP_Real newub;
6928
6929 newub = (lhs - maxresactivity)/val;
6930 if( !SCIPisInfinity(scip, newub) &&
6931 ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6932 {
6933 /* check maxresactivities for reliability */
6934 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6935 {
6936 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6937 newub = (lhs - maxresactivity)/val;
6938
6939 if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisUbBetter(scip, newub, lb, ub)
6940 && (!SCIPisFeasLT(scip, newub, ub) && !SCIPvarIsIntegral(var))
6941 && (!force || !SCIPisLT(scip, newub, ub))) )
6942 return SCIP_OKAY;
6943 }
6944
6945 /* tighten upper bound */
6946 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g], newub=%.15g\n",
6947 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6948 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6949 &infeasible, &tightened) );
6950 if( infeasible )
6951 {
6952 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6953 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6954
6955 /* analyze conflict */
6957
6958 *cutoff = TRUE;
6959 return SCIP_OKAY;
6960 }
6961 if( tightened )
6962 {
6963 ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6964 assert(SCIPisFeasLE(scip, ub, newub));
6965 (*nchgbds)++;
6966 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6967 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6968 }
6969 }
6970 }
6971 }
6972
6973 return SCIP_OKAY;
6974}
6975
6976#define MAXTIGHTENROUNDS 10
6977
6978/** tightens bounds of variables in constraint due to activity bounds */
6979static
6981 SCIP* scip, /**< SCIP data structure */
6982 SCIP_CONS* cons, /**< linear constraint */
6983 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
6984 SCIP_Bool sortvars, /**< should variables be used in sorted order? */
6985 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6986 int* nchgbds /**< pointer to count the total number of tightened bounds */
6987 )
6988{
6989 SCIP_CONSDATA* consdata;
6990 unsigned int tightenmode;
6991 int nvars;
6992 int nrounds;
6993 int lastchange;
6994 int oldnchgbds;
6995#ifndef SCIP_DEBUG
6996 int oldnchgbdstotal;
6997#endif
6998 int v;
6999 SCIP_Bool force;
7000 SCIP_Bool easycase;
7001
7002 assert(scip != NULL);
7003 assert(cons != NULL);
7004 assert(nchgbds != NULL);
7005 assert(cutoff != NULL);
7006
7007 *cutoff = FALSE;
7008
7009 /* we cannot tighten variables' bounds, if the constraint may be not complete */
7010 if( SCIPconsIsModifiable(cons) )
7011 return SCIP_OKAY;
7012
7013 /* if a constraint was created after presolve, then it may hold fixed variables
7014 * if there are even multi-aggregated variables, then we cannot do bound tightening on these
7015 * thus, ensure here again that variable fixings have been applied
7016 */
7017 SCIP_CALL( applyFixings(scip, cons, cutoff) );
7018 if( *cutoff )
7019 return SCIP_OKAY;
7020
7021 /* check if constraint has any chances of tightening bounds */
7022 if( !canTightenBounds(cons) )
7023 return SCIP_OKAY;
7024
7025 consdata = SCIPconsGetData(cons);
7026 assert(consdata != NULL);
7027
7028 nvars = consdata->nvars;
7029 force = (nvars == 1) && !SCIPconsIsModifiable(cons);
7030
7031 /* we are at the root node or during presolving */
7032 if( SCIPgetDepth(scip) < 1 )
7033 tightenmode = 2;
7034 else
7035 tightenmode = 1;
7036
7037 /* stop if we already tightened the constraint and the tightening is not forced */
7038 if( !force && (consdata->boundstightened >= tightenmode) ) /*lint !e574*/
7039 return SCIP_OKAY;
7040
7041 /* ensure that the variables are properly sorted */
7042 if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7043 {
7044 SCIP_CALL( consdataSort(scip, consdata) );
7045 assert(consdata->coefsorted);
7046 }
7047
7048 /* update maximal activity delta if necessary */
7049 if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
7051
7052 assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
7053 assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
7054 checkMaxActivityDelta(scip, consdata);
7055
7056 /* this may happen if all variables are fixed */
7057 if( SCIPisFeasZero(scip, consdata->maxactdelta) )
7058 return SCIP_OKAY;
7059
7060 if( !SCIPisInfinity(scip, consdata->maxactdelta) )
7061 {
7062 SCIP_Real slack;
7063 SCIP_Real surplus;
7064 SCIP_Real minactivity;
7065 SCIP_Real maxactivity;
7066 SCIP_Bool ismintight;
7067 SCIP_Bool ismaxtight;
7068 SCIP_Bool isminsettoinfinity;
7069 SCIP_Bool ismaxsettoinfinity;
7070
7071 /* use maximal activity delta to skip propagation (cannot deduce anything) */
7072 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &ismintight, &ismaxtight,
7073 &isminsettoinfinity, &ismaxsettoinfinity);
7074 assert(!SCIPisInfinity(scip, minactivity));
7075 assert(!SCIPisInfinity(scip, -maxactivity));
7076
7077 slack = (SCIPisInfinity(scip, consdata->rhs) || isminsettoinfinity) ? SCIPinfinity(scip) : (consdata->rhs - minactivity);
7078 surplus = (SCIPisInfinity(scip, -consdata->lhs) || ismaxsettoinfinity) ? SCIPinfinity(scip) : (maxactivity - consdata->lhs);
7079
7080 /* check if the constraint will propagate */
7081 if( SCIPisLE(scip, consdata->maxactdelta, MIN(slack, surplus)) )
7082 return SCIP_OKAY;
7083 }
7084
7085 /* check if we can use fast implementation for easy and numerically well behaved cases */
7086 easycase = SCIPisLT(scip, consdata->maxactdelta, maxeasyactivitydelta);
7087
7088 /* as long as the bounds might be tightened again, try to tighten them; abort after a maximal number of rounds */
7089 lastchange = -1;
7090
7091#ifndef SCIP_DEBUG
7092 oldnchgbds = 0;
7093 oldnchgbdstotal = *nchgbds;
7094#endif
7095
7096 for( nrounds = 0; (force || consdata->boundstightened < tightenmode) && nrounds < MAXTIGHTENROUNDS; ++nrounds ) /*lint !e574*/
7097 {
7098 /* ensure that the variables are properly sorted
7099 *
7100 * note: it might happen that integer variables become binary during bound tightening at the root node
7101 */
7102 if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7103 {
7104 SCIP_CALL( consdataSort(scip, consdata) );
7105 assert(consdata->coefsorted);
7106 }
7107
7108 /* mark the constraint to have the variables' bounds tightened */
7109 consdata->boundstightened = (unsigned int)tightenmode;
7110
7111 /* try to tighten the bounds of each variable in the constraint. During solving process, the binary variable
7112 * sorting enables skipping variables
7113 */
7114 v = 0;
7115 while( v < nvars && v != lastchange && !(*cutoff) )
7116 {
7117 oldnchgbds = *nchgbds;
7118
7119 if( easycase )
7120 {
7121 SCIP_CALL( tightenVarBoundsEasy(scip, cons, v, cutoff, nchgbds, force) );
7122 }
7123 else
7124 {
7125 SCIP_CALL( tightenVarBounds(scip, cons, v, cutoff, nchgbds, force) );
7126 }
7127
7128 /* if there was no progress, skip the rest of the binary variables */
7129 if( *nchgbds > oldnchgbds )
7130 {
7131 lastchange = v;
7132 ++v;
7133 }
7134 else if( consdata->coefsorted && v < consdata->nbinvars - 1
7135 && !SCIPisFeasEQ(scip, SCIPvarGetUbLocal(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v])) )
7136 v = consdata->nbinvars;
7137 else
7138 ++v;
7139 }
7140
7141#ifndef SCIP_DEBUG
7142 SCIPdebugMessage("linear constraint <%s> found %d bound changes in round %d\n", SCIPconsGetName(cons),
7143 *nchgbds - oldnchgbdstotal, nrounds);
7144 oldnchgbdstotal += oldnchgbds;
7145#endif
7146 }
7147
7148#ifndef NDEBUG
7149 if( force && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
7150 assert(*cutoff || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->vars[0]), SCIPvarGetUbLocal(consdata->vars[0])));
7151#endif
7152
7153 return SCIP_OKAY;
7154}
7155
7156/** checks linear constraint for feasibility of given solution or current solution */
7157static
7159 SCIP* scip, /**< SCIP data structure */
7160 SCIP_CONS* cons, /**< linear constraint */
7161 SCIP_SOL* sol, /**< solution to be checked, or NULL for current solution */
7162 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
7163 SCIP_Bool checkrelmaxabs, /**< Should the violation for a constraint with side 0.0 be checked relative
7164 * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
7165 SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
7166 )
7167{
7168 SCIP_CONSDATA* consdata;
7169 SCIP_Real activity;
7170 SCIP_Real absviol;
7171 SCIP_Real relviol;
7172 SCIP_Real lhsviol;
7173 SCIP_Real rhsviol;
7174
7175 assert(scip != NULL);
7176 assert(cons != NULL);
7177 assert(violated != NULL);
7178
7179 SCIPdebugMsg(scip, "checking linear constraint <%s>\n", SCIPconsGetName(cons));
7181
7182 consdata = SCIPconsGetData(cons);
7183 assert(consdata != NULL);
7184
7185 *violated = FALSE;
7186
7187 if( consdata->row != NULL )
7188 {
7189 if( !checklprows && SCIProwIsInLP(consdata->row) )
7190 return SCIP_OKAY;
7191 else if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
7192 activity = consdataComputePseudoActivity(scip, consdata);
7193 else
7194 activity = SCIPgetRowSolActivity(scip, consdata->row, sol);
7195 }
7196 else
7197 activity = consdataGetActivity(scip, consdata, sol);
7198
7199 SCIPdebugMsg(scip, " consdata activity=%.15g (lhs=%.15g, rhs=%.15g, row=%p, checklprows=%u, rowinlp=%u, sol=%p, hascurrentnodelp=%u)\n",
7200 activity, consdata->lhs, consdata->rhs, (void*)consdata->row, checklprows,
7201 consdata->row == NULL ? 0 : SCIProwIsInLP(consdata->row), (void*)sol,
7202 consdata->row == NULL ? FALSE : SCIPhasCurrentNodeLP(scip));
7203
7204 /* calculate absolute and relative bound violations */
7205 lhsviol = consdata->lhs - activity;
7206 rhsviol = activity - consdata->rhs;
7207
7208 absviol = 0.0;
7209 relviol = 0.0;
7210 if( (lhsviol > 0) && (lhsviol > rhsviol) )
7211 {
7212 absviol = lhsviol;
7213 relviol = SCIPrelDiff(consdata->lhs, activity);
7214 }
7215 else if( rhsviol > 0 )
7216 {
7217 absviol = rhsviol;
7218 relviol = SCIPrelDiff(activity, consdata->rhs);
7219 }
7220
7221 /* the activity of pseudo solutions may be invalid if it comprises positive and negative infinity contributions; we
7222 * return infeasible for safety
7223 */
7224 if( activity == SCIP_INVALID ) /*lint !e777*/
7225 {
7226 assert(sol == NULL);
7227 *violated = TRUE;
7228
7229 /* set violation of invalid pseudo solutions */
7230 absviol = SCIP_INVALID;
7231 relviol = SCIP_INVALID;
7232
7233 /* reset constraint age since we are in enforcement */
7235 }
7236 /* check with relative tolerances (the default) */
7237 else if( !consdata->checkabsolute && (SCIPisFeasLT(scip, activity, consdata->lhs) || SCIPisFeasGT(scip, activity, consdata->rhs)) )
7238 {
7239 /* the "normal" check: one of the two sides is violated */
7240 if( !checkrelmaxabs )
7241 {
7242 *violated = TRUE;
7243
7244 /* only reset constraint age if we are in enforcement */
7245 if( sol == NULL )
7246 {
7248 }
7249 }
7250 /* the (much) more complicated check: we try to disregard random noise and violations of a 0.0 side which are
7251 * small compared to the absolute values occurring in the activity
7252 */
7253 else
7254 {
7255 SCIP_Real maxabs;
7256 SCIP_Real coef;
7257 SCIP_Real absval;
7258 SCIP_Real solval;
7259 int v;
7260
7261 maxabs = 1.0;
7262
7263 /* compute maximum absolute value */
7264 for( v = 0; v < consdata->nvars; ++v )
7265 {
7266 if( consdata->vals != NULL )
7267 {
7268 coef = consdata->vals[v];
7269 }
7270 else
7271 coef = 1.0;
7272
7273 solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
7274 absval = REALABS( coef * solval );
7275 maxabs = MAX( maxabs, absval );
7276 }
7277
7278 /* regard left hand side, first */
7279 if( SCIPisFeasLT(scip, activity, consdata->lhs) )
7280 {
7281 /* check whether violation is random noise */
7282 if( (consdata->lhs - activity) <= (1e-15 * maxabs) )
7283 {
7284 SCIPdebugMsg(scip, " lhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7285 consdata->lhs - activity, maxabs);
7287
7288 /* only increase constraint age if we are in enforcement */
7289 if( sol == NULL )
7290 {
7291 SCIP_CALL( SCIPincConsAge(scip, cons) );
7292 }
7293 }
7294 /* lhs is violated and lhs is 0.0: use relative tolerance w.r.t. largest absolute value */
7295 else if( SCIPisZero(scip, consdata->lhs) )
7296 {
7297 if( (consdata->lhs - activity) <= (SCIPfeastol(scip) * maxabs) )
7298 {
7299 SCIPdebugMsg(scip, " lhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7300 consdata->lhs - activity, maxabs);
7302
7303 /* only increase constraint age if we are in enforcement */
7304 if( sol == NULL )
7305 {
7306 SCIP_CALL( SCIPincConsAge(scip, cons) );
7307 }
7308 }
7309 else
7310 {
7311 *violated = TRUE;
7312
7313 /* only reset constraint age if we are in enforcement */
7314 if( sol == NULL )
7315 {
7317 }
7318 }
7319 }
7320 else
7321 {
7322 *violated = TRUE;
7323
7324 /* only reset constraint age if we are in enforcement */
7325 if( sol == NULL )
7326 {
7328 }
7329 }
7330 }
7331
7332 /* now regard right hand side */
7333 if( SCIPisFeasGT(scip, activity, consdata->rhs) )
7334 {
7335 /* check whether violation is random noise */
7336 if( (activity - consdata->rhs) <= (1e-15 * maxabs) )
7337 {
7338 SCIPdebugMsg(scip, " rhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7339 activity - consdata->rhs, maxabs);
7341
7342 /* only increase constraint age if we are in enforcement */
7343 if( sol == NULL )
7344 {
7345 SCIP_CALL( SCIPincConsAge(scip, cons) );
7346 }
7347 }
7348 /* rhs is violated and rhs is 0.0, use relative tolerance w.r.t. largest absolute value */
7349 else if( SCIPisZero(scip, consdata->rhs) )
7350 {
7351 if( (activity - consdata->rhs) <= (SCIPfeastol(scip) * maxabs) )
7352 {
7353 SCIPdebugMsg(scip, " rhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7354 activity - consdata->rhs, maxabs);
7356
7357 /* only increase constraint age if we are in enforcement */
7358 if( sol == NULL )
7359 {
7360 SCIP_CALL( SCIPincConsAge(scip, cons) );
7361 }
7362 }
7363 else
7364 {
7365 *violated = TRUE;
7366
7367 /* only reset constraint age if we are in enforcement */
7368 if( sol == NULL )
7369 {
7371 }
7372 }
7373 }
7374 else
7375 {
7376 *violated = TRUE;
7377
7378 /* only reset constraint age if we are in enforcement */
7379 if( sol == NULL )
7380 {
7382 }
7383 }
7384 }
7385 }
7386 }
7387 /* check with absolute tolerances */
7388 else if( consdata->checkabsolute &&
7389 ((!SCIPisInfinity(scip, -consdata->lhs) && SCIPisGT(scip, consdata->lhs-activity, SCIPfeastol(scip))) ||
7390 (!SCIPisInfinity(scip, consdata->rhs) && SCIPisGT(scip, activity-consdata->rhs, SCIPfeastol(scip)))) )
7391 {
7392 *violated = TRUE;
7393
7394 /* only reset constraint age if we are in enforcement */
7395 if( sol == NULL )
7396 {
7398 }
7399 }
7400 else
7401 {
7402 /* only increase constraint age if we are in enforcement */
7403 if( sol == NULL )
7404 {
7405 SCIP_CALL( SCIPincConsAge(scip, cons) );
7406 }
7407 }
7408
7409 /* update absolute and relative violation of the solution */
7410 if( sol != NULL )
7411 SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
7412
7413 return SCIP_OKAY;
7414}
7415
7416/** creates an LP row in a linear constraint data */
7417static
7419 SCIP* scip, /**< SCIP data structure */
7420 SCIP_CONS* cons /**< linear constraint */
7421 )
7422{
7423 SCIP_CONSDATA* consdata;
7424
7425 assert(scip != NULL);
7426 assert(cons != NULL);
7427
7428 consdata = SCIPconsGetData(cons);
7429 assert(consdata != NULL);
7430 assert(consdata->row == NULL);
7431
7432 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
7434
7435 SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) );
7436
7437 return SCIP_OKAY;
7438}
7439
7440/** adds linear constraint as cut to the LP */
7441static
7443 SCIP* scip, /**< SCIP data structure */
7444 SCIP_CONS* cons, /**< linear constraint */
7445 SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7446 )
7447{
7448 SCIP_CONSDATA* consdata;
7449
7450 assert(scip != NULL);
7451 assert(cons != NULL);
7452
7453 consdata = SCIPconsGetData(cons);
7454 assert(consdata != NULL);
7455
7456 if( consdata->row == NULL )
7457 {
7458 if( !SCIPconsIsModifiable(cons) )
7459 {
7460 /* 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
7461 * removing this here will make test cons/linear/fixedvar.c fail (as of 2018-12-03)
7462 */
7463 SCIP_CALL( applyFixings(scip, cons, cutoff) );
7464 if( *cutoff )
7465 return SCIP_OKAY;
7466 }
7467
7468 /* convert consdata object into LP row */
7469 SCIP_CALL( createRow(scip, cons) );
7470 }
7471 assert(consdata->row != NULL);
7472
7473 if( consdata->nvars == 0 )
7474 {
7475 SCIPdebugMsg(scip, "Empty linear constraint enters LP: <%s>\n", SCIPconsGetName(cons));
7476 }
7477
7478 /* insert LP row as cut */
7479 if( !SCIProwIsInLP(consdata->row) )
7480 {
7481 SCIPdebugMsg(scip, "adding relaxation of linear constraint <%s>: ", SCIPconsGetName(cons));
7482 SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL)) );
7483 /* if presolving is turned off, the row might be trivial */
7484 if ( ! SCIPisInfinity(scip, -consdata->lhs) || ! SCIPisInfinity(scip, consdata->rhs) )
7485 {
7486 SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, cutoff) );
7487 }
7488 }
7489
7490 return SCIP_OKAY;
7491}
7492
7493/** adds linear constraint as row to the NLP, if not added yet */
7494static
7496 SCIP* scip, /**< SCIP data structure */
7497 SCIP_CONS* cons /**< linear constraint */
7498 )
7499{
7500 SCIP_CONSDATA* consdata;
7501
7503
7504 /* skip deactivated, redundant, or local linear constraints (the NLP does not allow for local rows at the moment) */
7505 if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsLocal(cons) )
7506 return SCIP_OKAY;
7507
7508 consdata = SCIPconsGetData(cons);
7509 assert(consdata != NULL);
7510
7511 if( consdata->nlrow == NULL )
7512 {
7513 assert(consdata->lhs <= consdata->rhs);
7514
7515 SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons),
7516 0.0, consdata->nvars, consdata->vars, consdata->vals, NULL, consdata->lhs, consdata->rhs, SCIP_EXPRCURV_LINEAR) );
7517
7518 assert(consdata->nlrow != NULL);
7519 }
7520
7521 if( !SCIPnlrowIsInNLP(consdata->nlrow) )
7522 {
7523 SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow) );
7524 }
7525
7526 return SCIP_OKAY;
7527}
7528
7529/** separates linear constraint: adds linear constraint as cut, if violated by given solution */
7530static
7532 SCIP* scip, /**< SCIP data structure */
7533 SCIP_CONS* cons, /**< linear constraint */
7534 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
7535 SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
7536 SCIP_Bool separatecards, /**< should knapsack cardinality cuts be generated? */
7537 SCIP_Bool separateall, /**< should all constraints be subject to cardinality cut generation instead of only
7538 * the ones with non-zero dual value? */
7539 int* ncuts, /**< pointer to add up the number of found cuts */
7540 SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7541 )
7542{
7543 SCIP_CONSDATA* consdata;
7544 SCIP_Bool violated;
7545 int oldncuts;
7546
7547 assert(scip != NULL);
7548 assert(conshdlrdata != NULL);
7549 assert(cons != NULL);
7550 assert(cutoff != NULL);
7551
7552 consdata = SCIPconsGetData(cons);
7553 assert(ncuts != NULL);
7554 assert(consdata != NULL);
7555
7556 oldncuts = *ncuts;
7557 *cutoff = FALSE;
7558
7559 SCIP_CALL( checkCons(scip, cons, sol, (sol != NULL), conshdlrdata->checkrelmaxabs, &violated) );
7560
7561 if( violated )
7562 {
7563 /* insert LP row as cut */
7565 (*ncuts)++;
7566 }
7567 else if( !SCIPconsIsModifiable(cons) && separatecards && consdata->nvars > 0 )
7568 {
7569 /* relax linear constraint into knapsack constraint and separate lifted cardinality cuts */
7570 if( !separateall && sol == NULL )
7571 {
7572 /* we only want to call the knapsack cardinality cut separator for rows that have a non-zero dual solution */
7573 if( consdata->row != NULL && SCIProwIsInLP(consdata->row) )
7574 {
7575 SCIP_Real dualsol;
7576
7577 dualsol = SCIProwGetDualsol(consdata->row);
7578 if( SCIPisFeasNegative(scip, dualsol) )
7579 {
7580 if( !SCIPisInfinity(scip, consdata->rhs) )
7581 {
7582 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7583 consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7584 }
7585 }
7586 else if( SCIPisFeasPositive(scip, dualsol) )
7587 {
7588 if( !SCIPisInfinity(scip, -consdata->lhs) )
7589 {
7590 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7591 consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7592 }
7593 }
7594 }
7595 }
7596 else
7597 {
7598 if( !SCIPisInfinity(scip, consdata->rhs) )
7599 {
7600 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7601 consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7602 }
7603 if( !SCIPisInfinity(scip, -consdata->lhs) )
7604 {
7605 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7606 consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7607 }
7608 }
7609 }
7610
7611 if( *ncuts > oldncuts )
7612 {
7614 }
7615
7616 return SCIP_OKAY;
7617}
7618
7619/** propagation method for linear constraints */
7620static
7622 SCIP* scip, /**< SCIP data structure */
7623 SCIP_CONS* cons, /**< linear constraint */
7624 SCIP_Bool tightenbounds, /**< should the variable's bounds be tightened? */
7625 SCIP_Bool rangedrowpropagation,/**< should ranged row propagation be performed? */
7626 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7627 SCIP_Bool sortvars, /**< should variable sorting for faster propagation be used? */
7628 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7629 int* nchgbds, /**< pointer to count the number of bound changes */
7630 int* naddconss /**< pointer to count number of added constraints */
7631 )
7632{
7633 SCIP_CONSDATA* consdata;
7634 SCIP_Real minactivity;
7635 SCIP_Real maxactivity;
7636 SCIP_Bool isminacttight;
7637 SCIP_Bool ismaxacttight;
7638 SCIP_Bool isminsettoinfinity;
7639 SCIP_Bool ismaxsettoinfinity;
7640
7641 assert(scip != NULL);
7642 assert(cons != NULL);
7643 assert(cutoff != NULL);
7644 assert(nchgbds != NULL);
7645
7646 /*SCIPdebugMsg(scip, "propagating linear constraint <%s>\n", SCIPconsGetName(cons));*/
7647
7648 consdata = SCIPconsGetData(cons);
7649 assert(consdata != NULL);
7650
7651 if( consdata->eventdata == NULL )
7652 {
7653 SCIP_CONSHDLR* conshdlr;
7654 SCIP_CONSHDLRDATA* conshdlrdata;
7655
7656 conshdlr = SCIPconsGetHdlr(cons);
7657 assert(conshdlr != NULL);
7658
7659 conshdlrdata = SCIPconshdlrGetData(conshdlr);
7660 assert(conshdlrdata != NULL);
7661
7662 /* catch bound change events of variables */
7663 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
7664 assert(consdata->eventdata != NULL);
7665 }
7666
7667 *cutoff = FALSE;
7668
7669 /* we can only infer activity bounds of the linear constraint, if it is not modifiable */
7670 if( !SCIPconsIsModifiable(cons) )
7671 {
7672 /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
7674 {
7675 SCIP_CALL( SCIPincConsAge(scip, cons) );
7676 }
7677
7678 /* tighten the variable's bounds */
7679 if( tightenbounds )
7680 {
7681 int oldnchgbds;
7682
7683 oldnchgbds = *nchgbds;
7684
7685 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
7686
7687 if( *nchgbds > oldnchgbds )
7688 {
7690 }
7691 }
7692
7693 /* propagate ranged rows */
7694 if( rangedrowpropagation && tightenbounds && !(*cutoff) )
7695 {
7696 int nfixedvars = 0;
7697
7698 SCIPdebug( int oldnchgbds = *nchgbds; )
7699
7700 SCIP_CALL( rangedRowPropagation(scip, cons, cutoff, &nfixedvars, nchgbds, naddconss) );
7701
7702 if( *cutoff )
7703 {
7704 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible\n", SCIPconsGetName(cons));
7705 }
7706 else
7707 {
7708 SCIPdebug( SCIPdebugMsg(scip, "linear constraint <%s> found %d bound changes and %d fixings\n", SCIPconsGetName(cons), *nchgbds - oldnchgbds, nfixedvars); )
7709 }
7710
7711 if( nfixedvars > 0 )
7712 *nchgbds += 2 * nfixedvars;
7713 } /*lint !e438*/
7714
7715 /* check constraint for infeasibility and redundancy */
7716 if( !(*cutoff) )
7717 {
7718 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
7719 &isminsettoinfinity, &ismaxsettoinfinity);
7720
7721 if( SCIPisFeasGT(scip, minactivity, consdata->rhs) )
7722 {
7723 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (rhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7724 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7725
7726 /* analyze conflict */
7728
7730 *cutoff = TRUE;
7731 }
7732 else if( SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
7733 {
7734 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (lhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7735 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7736
7737 /* analyze conflict */
7739
7741 *cutoff = TRUE;
7742 }
7743 else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
7744 {
7745 SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7746 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7747
7748 /* remove the constraint locally unless it has become empty, in which case it is removed globally */
7749 if( consdata->nvars > 0 )
7751 else
7752 SCIP_CALL( SCIPdelCons(scip, cons) );
7753 }
7754 }
7755 }
7756
7757 return SCIP_OKAY;
7758}
7759
7760
7761/*
7762 * Presolving methods
7763 */
7764
7765/** converts all variables with fixed domain into FIXED variables */
7766static
7768 SCIP* scip, /**< SCIP data structure */
7769 SCIP_CONS* cons, /**< linear constraint */
7770 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
7771 int* nfixedvars /**< pointer to count the total number of fixed variables */
7772 )
7773{
7774 SCIP_CONSDATA* consdata;
7775 SCIP_VAR* var;
7776 SCIP_VARSTATUS varstatus;
7777 SCIP_Real lb;
7778 SCIP_Real ub;
7779 SCIP_Bool fixed;
7780 SCIP_Bool infeasible;
7781 int v;
7782
7783 assert(scip != NULL);
7784 assert(cons != NULL);
7785 assert(cutoff != NULL);
7786 assert(nfixedvars != NULL);
7787
7788 consdata = SCIPconsGetData(cons);
7789 assert(consdata != NULL);
7790
7791 for( v = 0; v < consdata->nvars; ++v )
7792 {
7793 assert(consdata->vars != NULL);
7794 var = consdata->vars[v];
7795 varstatus = SCIPvarGetStatus(var);
7796
7797 if( varstatus != SCIP_VARSTATUS_FIXED )
7798 {
7799 lb = SCIPvarGetLbGlobal(var);
7800 ub = SCIPvarGetUbGlobal(var);
7801 if( SCIPisEQ(scip, lb, ub) )
7802 {
7803 SCIP_Real fixval;
7804
7805 fixval = SCIPselectSimpleValue(lb, ub, MAXDNOM);
7806 SCIPdebugMsg(scip, "converting variable <%s> with fixed bounds [%.15g,%.15g] into fixed variable fixed at %.15g\n",
7807 SCIPvarGetName(var), lb, ub, fixval);
7808 SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
7809 if( infeasible )
7810 {
7811 SCIPdebugMsg(scip, " -> infeasible fixing\n");
7812 *cutoff = TRUE;
7813 return SCIP_OKAY;
7814 }
7815 if( fixed )
7816 (*nfixedvars)++;
7817 }
7818 }
7819 }
7820
7821 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
7822
7823 if( infeasible )
7824 {
7825 SCIPdebugMsg(scip, " -> infeasible fixing\n");
7826 *cutoff = TRUE;
7827 return SCIP_OKAY;
7828 }
7829
7830 assert(consdata->removedfixings);
7831
7832 return SCIP_OKAY;
7833}
7834
7835#define MAX_CLIQUE_NONZEROS_PER_CONS 1000000
7836
7837/** extracts cliques of the constraint and adds them to SCIP
7838 *
7839 * The following clique extraction mechanism are implemeneted
7840 *
7841 * 1. collect binary variables and sort them in non increasing order, then
7842 *
7843 * a) if the constraint has a finite right hand side and the negative infinity counters for the minactivity are zero
7844 * then add the variables as a clique for which all successive pairs of coefficients fullfill the following
7845 * condition
7846 *
7847 * minactivity + vals[i] + vals[i+1] > rhs
7848 *
7849 * and also add the binary to binary implication also for non-successive variables for which the same argument
7850 * holds
7851 *
7852 * minactivity + vals[i] + vals[j] > rhs
7853 *
7854 * 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
7855 * binary to binary implications x1 = 1 => x4 = 0 and x2 = 1 => x4 = 0
7856 *
7857 * b) if the constraint has a finite left hand side and the positive infinity counters for the maxactivity are zero
7858 * then add the variables as a clique for which all successive pairs of coefficients fullfill the follwoing
7859 * condition
7860 *
7861 * maxactivity + vals[i] + vals[i-1] < lhs
7862 *
7863 * and also add the binary to binary implication also for non-successive variables for which the same argument
7864 * holds
7865 *
7866 * maxactivity + vals[i] + vals[j] < lhs
7867 *
7868 * e.g. you could multiply the above example by -1
7869 *
7870 * c) the constraint has a finite right hand side and a finite minactivity then add the variables as a negated
7871 * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7872 * condition
7873 *
7874 * minactivity - vals[i] - vals[i-1] > rhs
7875 *
7876 * and also add the binary to binary implication also for non-successive variables for which the
7877 * same argument holds
7878 *
7879 * minactivity - vals[i] - vals[j] > rhs
7880 *
7881 * e.g. -4 x1 -3 x2 - 2 x3 + 2 x4 <= -4 would lead to the (negated) clique (~x1, ~x2) and the binary to binary
7882 * implication x1 = 0 => x3 = 1
7883 *
7884 * d) the constraint has a finite left hand side and a finite maxactivity then add the variables as a negated
7885 * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7886 * condition
7887 *
7888 * maxactivity - vals[i] - vals[i+1] < lhs
7889 *
7890 * and also add the binary to binary implication also for non-successive variables for which the same argument
7891 * holds
7892 *
7893 * maxactivity - vals[i] - vals[j] < lhs
7894 *
7895 * e.g. you could multiply the above example by -1
7896 *
7897 * 2. if the linear constraint represents a set-packing or set-partitioning constraint, the whole constraint is added
7898 * as clique, (this part is done at the end of the method)
7899 *
7900 */
7901static
7903 SCIP* scip, /**< SCIP data structure */
7904 SCIP_CONS* cons, /**< linear constraint */
7905 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7906 SCIP_Bool sortvars, /**< should variables be used in sorted order? */
7907 int* nfixedvars, /**< pointer to count number of fixed variables */
7908 int* nchgbds, /**< pointer to count the total number of tightened bounds */
7909 SCIP_Bool* cutoff /**< pointer to store TRUE, if a cutoff was found */
7910 )
7911{
7912 SCIP_VAR** vars;
7913 SCIP_Real* vals;
7914 SCIP_CONSDATA* consdata;
7915 SCIP_Bool lhsclique;
7916 SCIP_Bool rhsclique;
7917 SCIP_Bool finitelhs;
7918 SCIP_Bool finiterhs;
7919 SCIP_Bool finiteminact;
7920 SCIP_Bool finitemaxact;
7921 SCIP_Bool finitenegminact;
7922 SCIP_Bool finitenegmaxact;
7923 SCIP_Bool finiteposminact;
7924 SCIP_Bool finiteposmaxact;
7925 SCIP_Bool infeasible;
7926 SCIP_Bool stopped;
7927 int cliquenonzerosadded;
7928 int v;
7929 int i;
7930 int nposcoefs;
7931 int nnegcoefs;
7932 int nvars;
7933
7934 assert(scip != NULL);
7935 assert(cons != NULL);
7936 assert(nfixedvars != NULL);
7937 assert(nchgbds != NULL);
7938 assert(cutoff != NULL);
7939 assert(!SCIPconsIsDeleted(cons));
7940
7941 consdata = SCIPconsGetData(cons);
7942 assert(consdata != NULL);
7943
7944 if( consdata->nvars < 2 )
7945 return SCIP_OKAY;
7946
7947 /* add implications if possible
7948 *
7949 * for now we only add binary to non-binary implications, and this is only done for the binary variable with the
7950 * maximal absolute contribution and also only if this variable would force all other variables to their bound
7951 * corresponding to the global minimal activity of the constraint
7952 */
7953 if( !consdata->implsadded )
7954 {
7955 /* sort variables by variable type */
7956 SCIP_CALL( consdataSort(scip, consdata) );
7957
7958 /* @todo we might extract implications/cliques if SCIPvarIsBinary() variables exist and we have integer variables
7959 * up front, might change sorting correspondingly
7960 */
7961 /* fast abort if no binaries seem to exist
7962 * "seem to", because there are rare situations in which variables may actually not be sorted by type, even though consdataSort has been called
7963 * this situation can occur if, e.g., the type of consdata->vars[1] has been changed to binary, but the corresponding variable event has
7964 * not been executed yet, because it is the eventExecLinear() which marks the variables array as unsorted (set consdata->indexsorted to FALSE),
7965 * which is the requirement for consdataSort() to actually resort the variables
7966 * we assume that in this situation the below code may be executed in a future presolve round, after the variable events have been executed
7967 */
7968 if( !SCIPvarIsBinary(consdata->vars[0]) )
7969 return SCIP_OKAY;
7970
7971 nvars = consdata->nvars;
7972 vars = consdata->vars;
7973 vals = consdata->vals;
7974
7975 /* recompute activities if needed */
7976 if( !consdata->validactivities )
7977 consdataCalcActivities(scip, consdata);
7978 assert(consdata->validactivities);
7979
7980 finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
7981 finiterhs = !SCIPisInfinity(scip, consdata->rhs);
7982 finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
7983 finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
7984 finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
7985 finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
7986 finiteminact = (finitenegminact && finiteposminact);
7987 finitemaxact = (finitenegmaxact && finiteposmaxact);
7988
7989 if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
7990 {
7991 SCIP_Real maxabscontrib = -1.0;
7992 SCIP_Bool posval = FALSE;
7993 SCIP_Bool allbinary = TRUE;
7994 int oldnchgbds = *nchgbds;
7995 int nbdchgs = 0;
7996 int nimpls = 0;
7997 int position = -1;
7998
7999 /* we need a valid minimal/maximal activity to add cliques */
8000 if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8001 {
8003 assert(consdata->validglbminact);
8004 }
8005
8006 if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8007 {
8009 assert(consdata->validglbmaxact);
8010 }
8011 assert(consdata->validglbminact || consdata->validglbmaxact);
8012
8013 /* @todo extend this to local/constraint probing */
8014
8015 /* determine maximal contribution to the activity */
8016 for( v = nvars - 1; v >= 0; --v )
8017 {
8018 if( SCIPvarIsBinary(vars[v]) )
8019 {
8020 if( vals[v] > 0 )
8021 {
8022 SCIP_Real value = vals[v] * SCIPvarGetUbGlobal(vars[v]);
8023
8024 if( value > maxabscontrib )
8025 {
8026 maxabscontrib = value;
8027 position = v;
8028 posval = TRUE;
8029 }
8030 }
8031 else
8032 {
8033 SCIP_Real value = vals[v] * SCIPvarGetLbGlobal(vars[v]);
8034
8035 value = REALABS(value);
8036
8037 if( value > maxabscontrib )
8038 {
8039 maxabscontrib = value;
8040 position = v;
8041 posval = FALSE;
8042 }
8043 }
8044 }
8045 else
8046 allbinary = FALSE;
8047 }
8048 assert(0 <= position && position < nvars);
8049
8050 if( !SCIPisEQ(scip, maxabscontrib, 1.0) && !allbinary )
8051 {
8052 /* if the right hand side and the minimal activity are finite and changing the variable with the biggest
8053 * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8054 * implications
8055 */
8056 if( finiterhs && finiteminact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbminactivity), consdata->rhs - maxabscontrib) )
8057 {
8058 for( v = nvars - 1; v >= 0; --v )
8059 {
8060 /* binary to binary implications will be collected when extrating cliques */
8061 if( !SCIPvarIsBinary(vars[v]) )
8062 {
8063 if( v != position )
8064 {
8065 if( vals[v] > 0 )
8066 {
8067 /* add implications */
8068 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8069 ++nimpls;
8070 *nchgbds += nbdchgs;
8071 }
8072 else
8073 {
8074 /* add implications */
8075 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8076 ++nimpls;
8077 *nchgbds += nbdchgs;
8078 }
8079
8080 if( infeasible )
8081 {
8082 *cutoff = TRUE;
8083 break;
8084 }
8085 }
8086 }
8087 /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8089 break;
8090 }
8091 }
8092
8093 /* if the left hand side and the maximal activity are finite and changing the variable with the biggest
8094 * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8095 * implications
8096 */
8097 if( finitelhs && finitemaxact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbmaxactivity), consdata->lhs - maxabscontrib) )
8098 {
8099 for( v = nvars - 1; v >= 0; --v )
8100 {
8101 /* binary to binary implications will be collected when extrating cliques */
8102 if( !SCIPvarIsBinary(vars[v]) )
8103 {
8104 if( v != position )
8105 {
8106 if( vals[v] > 0 )
8107 {
8108 /* add implications */
8109 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8110 ++nimpls;
8111 *nchgbds += nbdchgs;
8112 }
8113 else
8114 {
8115 /* add implications */
8116 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8117 ++nimpls;
8118 *nchgbds += nbdchgs;
8119 }
8120
8121 if( infeasible )
8122 {
8123 *cutoff = TRUE;
8124 break;
8125 }
8126 }
8127 }
8128 /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8129 else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8130 break;
8131 }
8132 }
8133
8134 /* did we find some implications */
8135 if( nimpls > 0 )
8136 {
8137 SCIPdebugMsg(scip, "extracted %d implications from constraint %s which led to %d bound changes, %scutoff detetcted\n", nimpls, SCIPconsGetName(cons), *nchgbds - oldnchgbds, *cutoff ? "" : "no ");
8138
8139 if( *cutoff )
8140 return SCIP_OKAY;
8141
8142 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8143 if( *nchgbds - oldnchgbds > 0 )
8144 {
8145 /* check for fixed variables */
8146 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8147 if( *cutoff )
8148 return SCIP_OKAY;
8149
8150 /* tighten variable's bounds */
8151 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8152 if( *cutoff )
8153 return SCIP_OKAY;
8154
8155 /* check for fixed variables */
8156 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8157 if( *cutoff )
8158 return SCIP_OKAY;
8159 }
8160 }
8161 }
8162 }
8163
8164 consdata->implsadded = TRUE;
8165 }
8166
8167 /* check if we already added the cliques of this constraint */
8168 if( consdata->cliquesadded )
8169 return SCIP_OKAY;
8170
8171 consdata->cliquesadded = TRUE;
8172 cliquenonzerosadded = 0;
8173 stopped = FALSE;
8174
8175 /* sort variables by variable type */
8176 SCIP_CALL( consdataSort(scip, consdata) );
8177
8178 nvars = consdata->nvars;
8179 vars = consdata->vars;
8180 vals = consdata->vals;
8181
8182 /**@todo extract more cliques, implications and variable bounds from linear constraints */
8183
8184 /* recompute activities if needed */
8185 if( !consdata->validactivities )
8186 consdataCalcActivities(scip, consdata);
8187 assert(consdata->validactivities);
8188
8189 finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8190 finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8191 finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8192 finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8193 finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8194 finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8195 finiteminact = (finitenegminact && finiteposminact);
8196 finitemaxact = (finitenegmaxact && finiteposmaxact);
8197
8198 /* 1. we wheck whether some variables do not fit together into this constraint and add the corresponding clique
8199 * information
8200 */
8201 if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
8202 {
8203 SCIP_VAR** binvars;
8204 SCIP_Real* binvarvals;
8205 int nposbinvars = 0;
8206 int nnegbinvars = 0;
8207 int allonebinary = 0;
8208
8210 SCIP_CALL( SCIPallocBufferArray(scip, &binvarvals, nvars) );
8211
8212 /* collect binary variables */
8213 for( i = 0; i < nvars; ++i )
8214 {
8215 if( SCIPvarIsBinary(vars[i]) )
8216 {
8217 assert(!SCIPisZero(scip, vals[i]));
8218
8219 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8220 ++allonebinary;
8221
8222 binvars[nposbinvars + nnegbinvars] = vars[i];
8223 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8224
8225 if( SCIPisPositive(scip, vals[i]) )
8226 ++nposbinvars;
8227 else
8228 ++nnegbinvars;
8229
8230 assert(nposbinvars + nnegbinvars <= nvars);
8231 }
8232 /* stop searching for binary variables, because the constraint data is sorted */
8233 else if( !SCIPvarIsIntegral(vars[i]) )
8234 break;
8235 }
8236 assert(nposbinvars + nnegbinvars <= nvars);
8237
8238 /* setppc constraints will be handled later; we need at least two binary variables with same sign to extract
8239 * cliques
8240 */
8241 if( allonebinary < nvars && (nposbinvars >= 2 || nnegbinvars >= 2) )
8242 {
8243 SCIP_Real threshold;
8244 int oldnchgbds = *nchgbds;
8245 int nbdchgs;
8246 int jstart;
8247 int j;
8248
8249 /* we need a valid minimal/maximal activity to add cliques */
8250 if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8251 {
8253 assert(consdata->validglbminact);
8254 }
8255
8256 if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8257 {
8259 assert(consdata->validglbmaxact);
8260 }
8261 assert(consdata->validglbminact || consdata->validglbmaxact);
8262
8263 /* sort coefficients non-increasing to be faster in the clique search */
8264 SCIPsortDownRealPtr(binvarvals, (void**) binvars, nposbinvars + nnegbinvars);
8265
8266 /* case a) */
8267 if( finiterhs && finitenegminact && nposbinvars >= 2 )
8268 {
8269 /* compute value that needs to be exceeded */
8270 threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
8271
8272 j = 1;
8273#ifdef SCIP_DISABLED_CODE /* assertion should only hold when constraints were fully propagated and boundstightened */
8274 /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8275 assert(SCIPisFeasLE(scip, binvarvals[0], threshold));
8276#endif
8277 /* check if at least two variables are in a clique */
8278 if( SCIPisFeasGT(scip, binvarvals[0] + binvarvals[j], threshold) )
8279 {
8280 ++j;
8281 /* check for extending the clique */
8282 while( j < nposbinvars )
8283 {
8284 if( !SCIPisFeasGT(scip, binvarvals[j-1] + binvarvals[j], threshold) )
8285 break;
8286 ++j;
8287 }
8288 assert(j >= 2);
8289
8290 /* add clique with at least two variables */
8291 SCIP_CALL( SCIPaddClique(scip, binvars, NULL, j, FALSE, &infeasible, &nbdchgs) );
8292
8293 if( infeasible )
8294 *cutoff = TRUE;
8295
8296 *nchgbds += nbdchgs;
8297
8298 cliquenonzerosadded += j;
8299 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8300 stopped = TRUE;
8301
8302 /* exchange the last variable in the clique if possible and add all new ones */
8303 if( !stopped && !(*cutoff) && j < nposbinvars )
8304 {
8305 SCIP_VAR** clqvars;
8306 int lastfit = j - 2;
8307 assert(lastfit >= 0);
8308
8309 /* copy all 'main'-clique variables */
8310 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
8311
8312 /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8313 while( lastfit >= 0 && j < nposbinvars )
8314 {
8315 /* check if two variables are in a clique */
8316 if( SCIPisFeasGT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8317 {
8318 clqvars[lastfit + 1] = binvars[j];
8319
8320 /* add clique with at least two variables */
8321 SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8322
8323 if( infeasible )
8324 {
8325 *cutoff = TRUE;
8326 break;
8327 }
8328
8329 *nchgbds += nbdchgs;
8330
8331 cliquenonzerosadded += (lastfit + 2);
8332 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8333 {
8334 stopped = TRUE;
8335 break;
8336 }
8337
8338 ++j;
8339 }
8340 else
8341 --lastfit;
8342 }
8343
8344 SCIPfreeBufferArray(scip, &clqvars);
8345 }
8346 }
8347 }
8348
8349 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8350 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8351 {
8352 /* check for fixed variables */
8353 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8354
8355 if( !*cutoff )
8356 {
8357 /* tighten variable's bounds */
8358 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8359
8360 if( !*cutoff )
8361 {
8362 /* check for fixed variables */
8363 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8364
8365 if( !*cutoff )
8366 {
8367 /* sort variables by variable type */
8368 SCIP_CALL( consdataSort(scip, consdata) );
8369
8370 /* recompute activities if needed */
8371 if( !consdata->validactivities )
8372 consdataCalcActivities(scip, consdata);
8373 assert(consdata->validactivities);
8374
8375 nvars = consdata->nvars;
8376 vars = consdata->vars;
8377 vals = consdata->vals;
8378 nposbinvars = 0;
8379 nnegbinvars = 0;
8380 allonebinary = 0;
8381
8382 /* update binary variables */
8383 for( i = 0; i < nvars; ++i )
8384 {
8385 if( SCIPvarIsBinary(vars[i]) )
8386 {
8387 assert(!SCIPisZero(scip, vals[i]));
8388
8389 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8390 ++allonebinary;
8391
8392 binvars[nposbinvars + nnegbinvars] = vars[i];
8393 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8394
8395 if( SCIPisPositive(scip, vals[i]) )
8396 ++nposbinvars;
8397 else
8398 ++nnegbinvars;
8399
8400 assert(nposbinvars + nnegbinvars <= nvars);
8401 }
8402 /* stop searching for binary variables, because the constraint data is sorted */
8403 else if( !SCIPvarIsIntegral(vars[i]) )
8404 break;
8405 }
8406 assert(nposbinvars + nnegbinvars <= nvars);
8407 }
8408 }
8409 }
8410
8411 oldnchgbds = *nchgbds;
8412 }
8413
8414 /* case b) */
8415 if( !stopped && !(*cutoff) && finitelhs && finiteposmaxact && nnegbinvars >= 2 )
8416 {
8417 /* compute value that needs to be deceeded */
8418 threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
8419
8420 i = nposbinvars + nnegbinvars - 1;
8421 j = i - 1;
8422#ifdef SCIP_DISABLED_CODE
8423 /* assertion should only hold when constraints were fully propagated and boundstightened */
8424 /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8425 assert(SCIPisFeasGE(scip, binvarvals[i], threshold));
8426#endif
8427 /* check if two variables are in a clique */
8428 if( SCIPisFeasLT(scip, binvarvals[i] + binvarvals[j], threshold) )
8429 {
8430 --j;
8431 /* check for extending the clique */
8432 while( j >= nposbinvars )
8433 {
8434 if( !SCIPisFeasLT(scip, binvarvals[j+1] + binvarvals[j], threshold) )
8435 break;
8436 --j;
8437 }
8438 jstart = j;
8439
8440 assert(i - j >= 2);
8441 /* add clique with at least two variables */
8442 SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), NULL, i - j, FALSE, &infeasible, &nbdchgs) );
8443
8444 if( infeasible )
8445 *cutoff = TRUE;
8446
8447 *nchgbds += nbdchgs;
8448
8449 cliquenonzerosadded += (i - j);
8450 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8451 stopped = TRUE;
8452
8453 /* exchange the last variable in the clique if possible and add all new ones */
8454 if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8455 {
8456 SCIP_VAR** clqvars;
8457 int lastfit = jstart + 1;
8458 assert(lastfit < i);
8459
8460 /* copy all 'main'-clique variables */
8461 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8462 ++lastfit;
8463
8464 /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8465 while( lastfit <= i && j >= nposbinvars )
8466 {
8467 /* check if two variables are in a clique */
8468 if( SCIPisFeasLT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8469 {
8470 assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8471 clqvars[lastfit - jstart - 2] = binvars[j];
8472
8473 assert(i - lastfit + 2 >= 2);
8474 /* add clique with at least two variables */
8475 SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), NULL, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8476
8477 if( infeasible )
8478 {
8479 *cutoff = TRUE;
8480 break;
8481 }
8482
8483 *nchgbds += nbdchgs;
8484
8485 cliquenonzerosadded += (i - lastfit + 2);
8486 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8487 {
8488 stopped = TRUE;
8489 break;
8490 }
8491
8492 --j;
8493 }
8494 else
8495 ++lastfit;
8496 }
8497
8498 SCIPfreeBufferArray(scip, &clqvars);
8499 }
8500 }
8501 }
8502
8503 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8504 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8505 {
8506 /* check for fixed variables */
8507 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8508
8509 if( !*cutoff )
8510 {
8511 /* tighten variable's bounds */
8512 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8513
8514 if( !*cutoff )
8515 {
8516 /* check for fixed variables */
8517 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8518
8519 if( !*cutoff )
8520 {
8521 /* sort variables by variable type */
8522 SCIP_CALL( consdataSort(scip, consdata) );
8523
8524 /* recompute activities if needed */
8525 if( !consdata->validactivities )
8526 consdataCalcActivities(scip, consdata);
8527 assert(consdata->validactivities);
8528
8529 nvars = consdata->nvars;
8530 vars = consdata->vars;
8531 vals = consdata->vals;
8532 nposbinvars = 0;
8533 nnegbinvars = 0;
8534 allonebinary = 0;
8535
8536 /* update binary variables */
8537 for( i = 0; i < nvars; ++i )
8538 {
8539 if( SCIPvarIsBinary(vars[i]) )
8540 {
8541 assert(!SCIPisZero(scip, vals[i]));
8542
8543 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8544 ++allonebinary;
8545
8546 binvars[nposbinvars + nnegbinvars] = vars[i];
8547 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8548
8549 if( SCIPisPositive(scip, vals[i]) )
8550 ++nposbinvars;
8551 else
8552 ++nnegbinvars;
8553
8554 assert(nposbinvars + nnegbinvars <= nvars);
8555 }
8556 /* stop searching for binary variables, because the constraint data is sorted */
8557 else if( !SCIPvarIsIntegral(vars[i]) )
8558 break;
8559 }
8560 assert(nposbinvars + nnegbinvars <= nvars);
8561 }
8562 }
8563 }
8564
8565 oldnchgbds = *nchgbds;
8566 }
8567
8568 /* case c) */
8569 if( !(*cutoff) && finiterhs && finiteminact && nnegbinvars >= 2 )
8570 {
8571 SCIP_Bool* values;
8572
8573 /* initialize clique values array for adding a negated clique */
8574 SCIP_CALL( SCIPallocBufferArray(scip, &values, nnegbinvars) );
8575 BMSclearMemoryArray(values, nnegbinvars);
8576
8577 /* compute value that needs to be exceeded */
8578 threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
8579
8580 i = nposbinvars + nnegbinvars - 1;
8581 j = i - 1;
8582
8583#ifdef SCIP_DISABLED_CODE
8584 /* assertion should only hold when constraints were fully propagated and boundstightened */
8585 /* check if the variable should not have already been fixed to one */
8586 assert(!SCIPisFeasGT(scip, binvarvals[i], threshold));
8587#endif
8588
8589 if( SCIPisFeasGT(scip, -binvarvals[i] - binvarvals[j], threshold) )
8590 {
8591 --j;
8592 /* check for extending the clique */
8593 while( j >= nposbinvars )
8594 {
8595 if( !SCIPisFeasGT(scip, -binvarvals[j+1] - binvarvals[j], threshold) )
8596 break;
8597 --j;
8598 }
8599 jstart = j;
8600
8601 assert(i - j >= 2);
8602 /* add negated clique with at least two variables */
8603 SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), values, i - j, FALSE, &infeasible, &nbdchgs) );
8604
8605 if( infeasible )
8606 *cutoff = TRUE;
8607
8608 *nchgbds += nbdchgs;
8609
8610 cliquenonzerosadded += (i - j);
8611 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8612 stopped = TRUE;
8613
8614 /* exchange the last variable in the clique if possible and add all new ones */
8615 if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8616 {
8617 SCIP_VAR** clqvars;
8618 int lastfit = j + 1;
8619 assert(lastfit < i);
8620
8621 /* copy all 'main'-clique variables */
8622 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8623 ++lastfit;
8624
8625 /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8626 while( lastfit <= i && j >= nposbinvars )
8627 {
8628 /* check if two variables are in a negated clique */
8629 if( SCIPisFeasGT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8630 {
8631 assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8632 clqvars[lastfit - jstart - 2] = binvars[j];
8633
8634 assert(i - lastfit + 2 >= 2);
8635 /* add clique with at least two variables */
8636 SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), values, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8637
8638 if( infeasible )
8639 {
8640 *cutoff = TRUE;
8641 break;
8642 }
8643
8644 *nchgbds += nbdchgs;
8645
8646 cliquenonzerosadded += (i - lastfit + 2);
8647 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8648 {
8649 stopped = TRUE;
8650 break;
8651 }
8652
8653 --j;
8654 }
8655 else
8656 ++lastfit;
8657 }
8658
8659 SCIPfreeBufferArray(scip, &clqvars);
8660 }
8661 }
8662
8663 SCIPfreeBufferArray(scip, &values);
8664 }
8665
8666 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8667 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8668 {
8669 /* check for fixed variables */
8670 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8671
8672 if( !*cutoff )
8673 {
8674 /* tighten variable's bounds */
8675 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8676
8677 if( !*cutoff )
8678 {
8679 /* check for fixed variables */
8680 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8681
8682 if( !*cutoff )
8683 {
8684 /* sort variables by variable type */
8685 SCIP_CALL( consdataSort(scip, consdata) );
8686
8687 /* recompute activities if needed */
8688 if( !consdata->validactivities )
8689 consdataCalcActivities(scip, consdata);
8690 assert(consdata->validactivities);
8691
8692 nvars = consdata->nvars;
8693 vars = consdata->vars;
8694 vals = consdata->vals;
8695 nposbinvars = 0;
8696 nnegbinvars = 0;
8697 allonebinary = 0;
8698
8699 /* update binary variables */
8700 for( i = 0; i < nvars; ++i )
8701 {
8702 if( SCIPvarIsBinary(vars[i]) )
8703 {
8704 assert(!SCIPisZero(scip, vals[i]));
8705
8706 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8707 ++allonebinary;
8708
8709 binvars[nposbinvars + nnegbinvars] = vars[i];
8710 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8711
8712 if( SCIPisPositive(scip, vals[i]) )
8713 ++nposbinvars;
8714 else
8715 ++nnegbinvars;
8716
8717 assert(nposbinvars + nnegbinvars <= nvars);
8718 }
8719 /* stop searching for binary variables, because the constraint data is sorted */
8720 else if( !SCIPvarIsIntegral(vars[i]) )
8721 break;
8722 }
8723 assert(nposbinvars + nnegbinvars <= nvars);
8724 }
8725 }
8726 }
8727 }
8728
8729 /* case d) */
8730 if( !stopped && !(*cutoff) && finitelhs && finitemaxact && nposbinvars >= 2 )
8731 {
8732 SCIP_Bool* values;
8733
8734 /* initialize clique values array for adding a negated clique */
8735 SCIP_CALL( SCIPallocBufferArray(scip, &values, nposbinvars) );
8736 BMSclearMemoryArray(values, nposbinvars);
8737
8738 /* compute value that needs to be exceeded */
8739 threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
8740
8741 j = 1;
8742
8743#ifdef SCIP_DISABLED_CODE
8744 /* assertion should only hold when constraints were fully propagated and boundstightened */
8745 /* check if the variable should not have already been fixed to one */
8746 assert(!SCIPisFeasLT(scip, -binvarvals[0], threshold));
8747#endif
8748
8749 if( SCIPisFeasLT(scip, -binvarvals[0] - binvarvals[j], threshold) )
8750 {
8751 ++j;
8752 /* check for extending the clique */
8753 while( j < nposbinvars )
8754 {
8755 if( !SCIPisFeasLT(scip, -binvarvals[j-1] - binvarvals[j], threshold) )
8756 break;
8757 ++j;
8758 }
8759 assert(j >= 2);
8760
8761 /* add negated clique with at least two variables */
8762 SCIP_CALL( SCIPaddClique(scip, binvars, values, j, FALSE, &infeasible, &nbdchgs) );
8763
8764 if( infeasible )
8765 *cutoff = TRUE;
8766
8767 *nchgbds += nbdchgs;
8768
8769 cliquenonzerosadded += j;
8770 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8771 stopped = TRUE;
8772
8773 /* exchange the last variable in the clique if possible and add all new ones */
8774 if( !stopped && !(*cutoff) && j < nposbinvars )
8775 {
8776 SCIP_VAR** clqvars;
8777 int lastfit = j - 2;
8778 assert(lastfit >= 0);
8779
8780 /* copy all 'main'-clique variables */
8781 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
8782
8783 /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8784 while( lastfit >= 0 && j < nposbinvars )
8785 {
8786 /* check if two variables are in a negated clique */
8787 if( SCIPisFeasLT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8788 {
8789 clqvars[lastfit + 1] = binvars[j];
8790
8791 /* add clique with at least two variables */
8792 SCIP_CALL( SCIPaddClique(scip, clqvars, values, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8793
8794 if( infeasible )
8795 {
8796 *cutoff = TRUE;
8797 break;
8798 }
8799
8800 *nchgbds += nbdchgs;
8801
8802 cliquenonzerosadded += lastfit + 2;
8803 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8804 break;
8805
8806 ++j;
8807 }
8808 else
8809 --lastfit;
8810 }
8811
8812 SCIPfreeBufferArray(scip, &clqvars);
8813 }
8814 }
8815
8816 SCIPfreeBufferArray(scip, &values);
8817 }
8818 }
8819
8820 SCIPfreeBufferArray(scip, &binvarvals);
8821 SCIPfreeBufferArray(scip, &binvars);
8822
8823 if( *cutoff )
8824 return SCIP_OKAY;
8825 }
8826
8827 /* 2. we only check if the constraint is a set packing / partitioning constraint */
8828
8829 /* check if all variables are binary, if the coefficients are +1 or -1, and if the right hand side is equal
8830 * to 1 - number of negative coefficients, or if the left hand side is equal to number of positive coefficients - 1
8831 */
8832 nposcoefs = 0;
8833 nnegcoefs = 0;
8834 for( i = 0; i < nvars; ++i )
8835 {
8836 if( !SCIPvarIsBinary(vars[i]) )
8837 return SCIP_OKAY;
8838 else if( SCIPisEQ(scip, vals[i], +1.0) )
8839 nposcoefs++;
8840 else if( SCIPisEQ(scip, vals[i], -1.0) )
8841 nnegcoefs++;
8842 else
8843 return SCIP_OKAY;
8844 }
8845
8846 lhsclique = SCIPisEQ(scip, consdata->lhs, (SCIP_Real)nposcoefs - 1.0);
8847 rhsclique = SCIPisEQ(scip, consdata->rhs, 1.0 - (SCIP_Real)nnegcoefs);
8848
8849 if( lhsclique || rhsclique )
8850 {
8851 SCIP_Bool* values;
8852 int nbdchgs;
8853
8854 SCIPdebugMsg(scip, "linear constraint <%s>: adding clique with %d vars (%d pos, %d neg)\n",
8855 SCIPconsGetName(cons), nvars, nposcoefs, nnegcoefs);
8857
8858 for( i = 0; i < nvars; ++i )
8859 values[i] = (rhsclique == (vals[i] > 0.0));
8860
8861 SCIP_CALL( SCIPaddClique(scip, vars, values, nvars, SCIPisEQ(scip, consdata->lhs, consdata->rhs), &infeasible, &nbdchgs) );
8862
8863 if( infeasible )
8864 *cutoff = TRUE;
8865
8866 *nchgbds += nbdchgs;
8867 SCIPfreeBufferArray(scip, &values);
8868 }
8869
8870 return SCIP_OKAY;
8871}
8872
8873/** tightens left and right hand side of constraint due to integrality */
8874static
8876 SCIP* scip, /**< SCIP data structure */
8877 SCIP_CONS* cons, /**< linear constraint */
8878 int* nchgsides, /**< pointer to count number of side changes */
8879 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
8880 )
8881{
8882 SCIP_CONSDATA* consdata;
8883 SCIP_Real newlhs;
8884 SCIP_Real newrhs;
8885 SCIP_Bool chglhs;
8886 SCIP_Bool chgrhs;
8887 SCIP_Bool integral;
8888 int i;
8889
8890 assert(scip != NULL);
8891 assert(cons != NULL);
8892 assert(nchgsides != NULL);
8893 assert(infeasible != NULL);
8894
8895 consdata = SCIPconsGetData(cons);
8896 assert(consdata != NULL);
8897
8898 *infeasible = FALSE;
8899
8900 chglhs = FALSE;
8901 chgrhs = FALSE;
8902 newlhs = -SCIPinfinity(scip);
8903 newrhs = SCIPinfinity(scip);
8904
8905 if( !SCIPisIntegral(scip, consdata->lhs) || !SCIPisIntegral(scip, consdata->rhs) )
8906 {
8907 integral = TRUE;
8908 for( i = 0; i < consdata->nvars && integral; ++i )
8909 integral = SCIPvarIsIntegral(consdata->vars[i]) && SCIPisIntegral(scip, consdata->vals[i]);
8910 if( integral )
8911 {
8912 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisIntegral(scip, consdata->lhs) )
8913 {
8914 newlhs = SCIPfeasCeil(scip, consdata->lhs);
8915 chglhs = TRUE;
8916 }
8917 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisIntegral(scip, consdata->rhs) )
8918 {
8919 newrhs = SCIPfeasFloor(scip, consdata->rhs);
8920 chgrhs = TRUE;
8921 }
8922
8923 /* check whether rounding would lead to an unsatisfiable constraint */
8924 if( SCIPisGT(scip, newlhs, newrhs) )
8925 {
8926 SCIPdebugMsg(scip, "rounding sides=[%.15g,%.15g] of linear constraint <%s> with integral coefficients and variables only "
8927 "is infeasible\n", consdata->lhs, consdata->rhs, SCIPconsGetName(cons));
8928
8929 *infeasible = TRUE;
8930 return SCIP_OKAY;
8931 }
8932
8933 SCIPdebugMsg(scip, "linear constraint <%s>: make sides integral: sides=[%.15g,%.15g]\n",
8934 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
8935
8936 if( chglhs )
8937 {
8938 assert(!SCIPisInfinity(scip, -newlhs));
8939
8940 SCIP_CALL( chgLhs(scip, cons, newlhs) );
8941 if( !consdata->upgraded )
8942 (*nchgsides)++;
8943 }
8944 if( chgrhs )
8945 {
8946 assert(!SCIPisInfinity(scip, newrhs));
8947
8948 SCIP_CALL( chgRhs(scip, cons, newrhs) );
8949 if( !consdata->upgraded )
8950 (*nchgsides)++;
8951 }
8952 SCIPdebugMsg(scip, "linear constraint <%s>: new integral sides: sides=[%.15g,%.15g]\n",
8953 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
8954 }
8955 }
8956
8957 return SCIP_OKAY;
8958}
8959
8960/** tightens coefficients of binary, integer, and implied integral variables due to activity bounds in presolving:
8961 * given an inequality lhs <= a*x + ai*xi <= rhs, with a non-continuous variable li <= xi <= ui
8962 * let minact := min{a*x + ai*xi}, maxact := max{a*x + ai*xi}
8963 * (i) ai >= 0:
8964 * if minact + ai >= lhs and maxact - ai <= rhs: (**)
8965 * - a deviation from the lower/upper bound of xi would make the left/right hand side redundant
8966 * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
8967 * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
8968 * - change coefficients:
8969 * ai' := max(lhs - minact, maxact - rhs, 0)
8970 * lhs' := lhs - (ai - ai')*li
8971 * rhs' := rhs - (ai - ai')*ui
8972 * (ii) ai < 0:
8973 * if minact - ai >= lhs and maxact + ai <= rhs: (***)
8974 * - a deviation from the upper/lower bound of xi would make the left/right hand side redundant
8975 * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
8976 * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
8977 * - change coefficients:
8978 * ai' := min(rhs - maxact, minact - lhs, 0)
8979 * lhs' := lhs - (ai - ai')*ui
8980 * rhs' := rhs - (ai - ai')*li
8981 *
8982 * We further try to remove variables from the constraint;
8983 * Variables which fulfill conditions (**) or (***) are called relevant variables.
8984 * A deviation of only one from their bound makes the lhs/rhs feasible (i.e., redundant), even if all other
8985 * variables are set to their "worst" bound. If all variables which are not relevant cannot make the lhs/rhs
8986 * redundant, even if they are set to their "best" bound, they can be removed from the constraint. E.g., for binary
8987 * variables and an inequality x_1 +x_2 +10y_1 +10y_2 >= 5, setting either of the y_i to one suffices to fulfill the
8988 * inequality, whereas the x_i do not contribute to feasibility and can be removed.
8989 *
8990 * @todo use also some tightening procedures for (knapsack) constraints with non-integer coefficients, see
8991 * cons_knapsack.c the following methods detectRedundantVars() and tightenWeights()
8992 */
8993static
8995 SCIP* scip, /**< SCIP data structure */
8996 SCIP_CONS* cons, /**< linear constraint */
8997 int* nchgcoefs, /**< pointer to count total number of changed coefficients */
8998 int* nchgsides /**< pointer to count number of side changes */
8999 )
9000{
9001 SCIP_CONSDATA* consdata;
9002 SCIP_VAR* var;
9003 SCIP_Bool* isvarrelevant;
9004 SCIP_Real minactivity; /* minimal value w.r.t. the variable's local bounds for the constraint's
9005 * activity, ignoring the coefficients contributing with infinite value */
9006 SCIP_Real maxactivity; /* maximal value w.r.t. the variable's local bounds for the constraint's
9007 * activity, ignoring the coefficients contributing with infinite value */
9008 SCIP_Bool isminacttight; /* are all contributions to the minactivity non-huge or non-contradicting? */
9009 SCIP_Bool ismaxacttight; /* are all contributions to the maxactivity non-huge or non-contradicting? */
9010 SCIP_Bool isminsettoinfinity;
9011 SCIP_Bool ismaxsettoinfinity;
9012 SCIP_Real minleftactivity; /* minimal activity without relevant variables */
9013 SCIP_Real maxleftactivity; /* maximal activity without relevant variables */
9014 SCIP_Real aggrlhs; /* lhs without minimal activity of relevant variables */
9015 SCIP_Real aggrrhs; /* rhs without maximal activity of relevant variables */
9016 SCIP_Real lval; /* candidate for new value arising from considering the left hand side */
9017 SCIP_Real rval; /* candidate for new value arising from considering the left hand side */
9018 SCIP_Real val;
9019 SCIP_Real newval;
9020 SCIP_Real newlhs;
9021 SCIP_Real newrhs;
9022 SCIP_Real lb;
9023 SCIP_Real ub;
9024 int i;
9025
9026 assert(scip != NULL);
9027 assert(cons != NULL);
9028 assert(nchgcoefs != NULL);
9029 assert(nchgsides != NULL);
9030
9031 consdata = SCIPconsGetData(cons);
9032 assert(consdata != NULL);
9033
9034 /* allocate relevance flags */
9035 SCIP_CALL( SCIPallocBufferArray(scip, &isvarrelevant, consdata->nvars) );
9036
9037 /* get the minimal and maximal activity of the constraint */
9038 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
9039 &isminsettoinfinity, &ismaxsettoinfinity);
9040 assert(( isminsettoinfinity && !SCIPisInfinity(scip, -consdata->lhs) )
9041 || SCIPisLT(scip, minactivity, consdata->lhs)
9042 || ( ismaxsettoinfinity && !SCIPisInfinity(scip, consdata->rhs) )
9043 || SCIPisGT(scip, maxactivity, consdata->rhs));
9044
9045 minleftactivity = 0.0;
9046 maxleftactivity = 0.0;
9047
9048 /* try to tighten each coefficient */
9049 i = 0;
9050 while( i < consdata->nvars )
9051 {
9052 /* get coefficient and variable's bounds */
9053 var = consdata->vars[i];
9054 val = consdata->vals[i];
9055 assert(!SCIPisZero(scip, val));
9056 lb = SCIPvarGetLbLocal(var);
9057 ub = SCIPvarGetUbLocal(var);
9058
9059 /* check sign of coefficient */
9060 if( val >= 0.0 )
9061 {
9062 /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9063 isvarrelevant[i] = SCIPvarIsIntegral(var)
9064 && SCIPisGE(scip, minactivity + val, consdata->lhs) && SCIPisLE(scip, maxactivity - val, consdata->rhs);
9065
9066 if( isvarrelevant[i] )
9067 {
9068 /* change coefficients:
9069 * ai' := max(lhs - minact, maxact - rhs)
9070 * lhs' := lhs - (ai - ai')*li
9071 * rhs' := rhs - (ai - ai')*ui
9072 */
9073
9074 lval = consdata->lhs - minactivity;
9075 rval = maxactivity - consdata->rhs;
9076
9077 /* Try to avoid cancellation, if there are only two variables */
9078 if( consdata->nvars == 2 )
9079 {
9080 SCIP_Real otherval;
9081 otherval = consdata->vals[1-i];
9082
9083 if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9084 {
9085 lval = consdata->lhs - val*lb;
9086 lval -= otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9087 }
9088
9089 if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9090 {
9091 rval = val*ub - consdata->rhs;
9092 rval += otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9093 }
9094 }
9095
9096 newval = MAX3(lval, rval, 0.0);
9097 assert(SCIPisSumRelLE(scip, newval, val));
9098
9099 /* Try to avoid cancellation in computation of lhs/rhs */
9100 newlhs = consdata->lhs - val * lb;
9101 newlhs += newval * lb;
9102 newrhs = consdata->rhs - val * ub;
9103 newrhs += newval * ub;
9104
9105 if( !SCIPisSumRelEQ(scip, newval, val) )
9106 {
9107 SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9108 SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var), minactivity,
9109 maxactivity, consdata->lhs, consdata->rhs);
9110
9111 /* update the coefficient and the activity bounds */
9112 if( SCIPisZero(scip, newval) )
9113 {
9114 SCIP_CALL( delCoefPos(scip, cons, i) );
9115 --i;
9116 }
9117 else
9118 {
9119 SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9120 }
9121 ++(*nchgcoefs);
9122
9123 /* get the new minimal and maximal activity of the constraint */
9124 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight,
9125 &ismaxacttight, &isminsettoinfinity, &ismaxsettoinfinity);
9126
9127 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9128 {
9129 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons),
9130 consdata->lhs, newlhs);
9131
9132 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9133 (*nchgsides)++;
9134 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9135 }
9136
9137 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9138 {
9139 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons),
9140 consdata->rhs, newrhs);
9141
9142 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9143 (*nchgsides)++;
9144 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9145 }
9146 }
9147 }
9148 else
9149 {
9150 if( !SCIPisInfinity(scip, -minleftactivity) )
9151 {
9152 assert(!SCIPisInfinity(scip, val));
9153 assert(!SCIPisInfinity(scip, lb));
9154 if( SCIPisInfinity(scip, -lb) )
9155 minleftactivity = -SCIPinfinity(scip);
9156 else
9157 minleftactivity += val * lb;
9158 }
9159
9160 if( !SCIPisInfinity(scip, maxleftactivity) )
9161 {
9162 assert(!SCIPisInfinity(scip, val));
9163 assert(!SCIPisInfinity(scip, -ub));
9164 if( SCIPisInfinity(scip,ub) )
9165 maxleftactivity = SCIPinfinity(scip);
9166 else
9167 maxleftactivity += val * ub;
9168 }
9169 }
9170 }
9171 else
9172 {
9173 /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9174 isvarrelevant[i] = SCIPvarIsIntegral(var)
9175 && SCIPisGE(scip, minactivity - val, consdata->lhs) && SCIPisLE(scip, maxactivity + val, consdata->rhs);
9176
9177 if( isvarrelevant[i] )
9178 {
9179 /* change coefficients:
9180 * ai' := min(rhs - maxact, minact - lhs)
9181 * lhs' := lhs - (ai - ai')*ui
9182 * rhs' := rhs - (ai - ai')*li
9183 */
9184
9185 lval = minactivity - consdata->lhs;
9186 rval = consdata->rhs - maxactivity;
9187
9188 /* Try to avoid cancellation, if there are only two variables */
9189 if( consdata->nvars == 2 )
9190 {
9191 SCIP_Real otherval;
9192 otherval = consdata->vals[1-i];
9193
9194 if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9195 {
9196 lval = val*ub - consdata->lhs;
9197 lval += otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9198 }
9199
9200 if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9201 {
9202 rval = consdata->rhs - val*lb;
9203 rval -= otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9204 }
9205 }
9206
9207 newval = MIN3(lval, rval, 0.0);
9208 assert(SCIPisSumRelGE(scip, newval, val));
9209
9210 /* Try to avoid cancellation in computation of lhs/rhs */
9211 newlhs = consdata->lhs - val * ub;
9212 newlhs += newval * ub;
9213 newrhs = consdata->rhs - val * lb;
9214 newrhs += newval * lb;
9215
9216 if( !SCIPisSumRelEQ(scip, newval, val) )
9217 {
9218 SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9219 SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var), minactivity,
9220 maxactivity, consdata->lhs, consdata->rhs);
9221
9222 /* update the coefficient and the activity bounds */
9223 if( SCIPisZero(scip, newval) )
9224 {
9225 SCIP_CALL( delCoefPos(scip, cons, i) );
9226 --i;
9227 }
9228 else
9229 {
9230 SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9231 }
9232 ++(*nchgcoefs);
9233
9234 /* get the new minimal and maximal activity of the constraint */
9235 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight,
9236 &ismaxacttight, &isminsettoinfinity, &ismaxsettoinfinity);
9237
9238 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9239 {
9240 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons),
9241 consdata->lhs, newlhs);
9242
9243 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9244 (*nchgsides)++;
9245 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9246 }
9247
9248 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9249 {
9250 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons),
9251 consdata->rhs, newrhs);
9252
9253 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9254 (*nchgsides)++;
9255 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9256 }
9257 }
9258 }
9259 else
9260 {
9261 if( !SCIPisInfinity(scip, -minleftactivity) )
9262 {
9263 assert(!SCIPisInfinity(scip, -val));
9264 assert(!SCIPisInfinity(scip, -ub));
9265 if( SCIPisInfinity(scip, ub) )
9266 minleftactivity = -SCIPinfinity(scip);
9267 else
9268 minleftactivity += val * ub;
9269 }
9270
9271 if( !SCIPisInfinity(scip, maxleftactivity) )
9272 {
9273 assert(!SCIPisInfinity(scip, -val));
9274 assert(!SCIPisInfinity(scip, lb));
9275 if( SCIPisInfinity(scip, -lb) )
9276 maxleftactivity = SCIPinfinity(scip);
9277 else
9278 maxleftactivity += val * lb;
9279 }
9280 }
9281 }
9282
9283 ++i;
9284 }
9285
9286 SCIPdebugMsg(scip, "minleftactivity = %.15g, rhs = %.15g\n",
9287 minleftactivity, consdata->rhs);
9288 SCIPdebugMsg(scip, "maxleftactivity = %.15g, lhs = %.15g\n",
9289 maxleftactivity, consdata->lhs);
9290
9291 /* minleft == \infty ==> minactivity == \infty */
9292 assert(!SCIPisInfinity(scip, -minleftactivity) || SCIPisInfinity(scip, -minactivity));
9293 assert(!SCIPisInfinity(scip, maxleftactivity) || SCIPisInfinity(scip, maxactivity));
9294
9295 /* if the lhs is finite, we will check in the following whether the not relevant variables can make lhs feasible;
9296 * this is not valid, if the minactivity is -\infty (aggrlhs would be minus infinity in the following computation)
9297 * or if huge values contributed to the minactivity, because the minactivity is then just a relaxation
9298 * (<= the exact minactivity), and we might falsely remove coefficients in the following
9299 */
9300 assert(!SCIPisInfinity(scip, minactivity));
9301 if( !SCIPisInfinity(scip, -consdata->lhs) && (SCIPisInfinity(scip, -minactivity) || !isminacttight) )
9302 goto TERMINATE;
9303
9304 /* if the rhs is finite, we will check in the following whether the not relevant variables can make rhs feasible;
9305 * this is not valid, if the maxactivity is \infty (aggrrhs would be infinity in the following computation)
9306 * or if huge values contributed to the maxactivity, because the maxactivity is then just a relaxation
9307 * (>= the exact maxactivity), and we might falsely remove coefficients in the following
9308 */
9309 assert(!SCIPisInfinity(scip, -maxactivity));
9310 if( !SCIPisInfinity(scip, consdata->rhs) && (SCIPisInfinity(scip, maxactivity) || !ismaxacttight) )
9311 goto TERMINATE;
9312
9313 /* correct lhs and rhs by min/max activity of relevant variables
9314 * relevant variables are all those where a deviation from the bound makes the lhs/rhs redundant
9315 */
9316 aggrlhs = consdata->lhs - minactivity + minleftactivity;
9317 aggrrhs = consdata->rhs - maxactivity + maxleftactivity;
9318
9319 /* check if the constraint contains variables whose coefficient can be removed. The reasoning is the following:
9320 * Each relevant variable can make the lhs/rhs feasible with a deviation of only one in the bound. If _all_ not
9321 * relevant variables together cannot make lhs/rhs redundant, they can be removed from the constraint. aggrrhs may
9322 * contain some near-infinity value, but only if rhs is infinity.
9323 */
9324 if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasLT(scip, maxleftactivity, aggrlhs))
9325 && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasGT(scip, minleftactivity, aggrrhs)) )
9326 {
9327 SCIP_Real minleftactivitypart;
9328 SCIP_Real maxleftactivitypart;
9329
9330 assert(!SCIPisInfinity(scip, -consdata->lhs) || !SCIPisInfinity(scip, consdata->rhs));
9331
9332 /* remove redundant variables from constraint */
9333 i = 0;
9334 while( i < consdata->nvars )
9335 {
9336 /* consider redundant variable */
9337 if( !isvarrelevant[i] )
9338 {
9339 /* get coefficient and variable's bounds */
9340 var = consdata->vars[i];
9341 val = consdata->vals[i];
9342 assert(!SCIPisZero(scip, val));
9343 lb = SCIPvarGetLbLocal(var);
9344 ub = SCIPvarGetUbLocal(var);
9345
9346 SCIPdebugMsg(scip, "val = %g\tlhs = %g\trhs = %g\n", val, consdata->lhs, consdata->rhs);
9347 SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> from constraint since it is redundant\n",
9348 SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]));
9349
9350 /* check sign of coefficient */
9351 if( val >= 0.0 )
9352 {
9353 minleftactivitypart = val * lb;
9354 maxleftactivitypart = val * ub;
9355 }
9356 else
9357 {
9358 minleftactivitypart = val * ub;
9359 maxleftactivitypart = val * lb;
9360 }
9361
9362 /* remove redundant variable */
9363 isvarrelevant[i] = isvarrelevant[consdata->nvars - 1];
9364 SCIP_CALL( delCoefPos(scip, cons, i) );
9365 --i;
9366
9367 /* adjust lhs and right hand side */
9368 newlhs = consdata->lhs - minleftactivitypart;
9369 newrhs = consdata->rhs - maxleftactivitypart;
9370
9371 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9372 {
9373 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons),
9374 consdata->lhs, newlhs);
9375
9376 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9377 ++(*nchgsides);
9378 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9379 }
9380
9381 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9382 {
9383 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons),
9384 consdata->rhs, newrhs);
9385
9386 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9387 ++(*nchgsides);
9388 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9389 }
9390 }
9391
9392 ++i;
9393 }
9394 }
9395
9396TERMINATE:
9397 /* free relevance flags */
9398 SCIPfreeBufferArray(scip, &isvarrelevant);
9399
9400 return SCIP_OKAY;
9401}
9402
9403/** processes equality with only one variable by fixing the variable and deleting the constraint */
9404static
9406 SCIP* scip, /**< SCIP data structure */
9407 SCIP_CONS* cons, /**< linear constraint */
9408 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9409 int* nfixedvars, /**< pointer to count number of fixed variables */
9410 int* ndelconss /**< pointer to count number of deleted constraints */
9411 )
9412{
9413 SCIP_CONSDATA* consdata;
9414 SCIP_VAR* var;
9415 SCIP_Real val;
9416 SCIP_Real fixval;
9417 SCIP_Bool infeasible;
9418 SCIP_Bool fixed;
9419
9420 assert(scip != NULL);
9421 assert(cons != NULL);
9422 assert(cutoff != NULL);
9423 assert(nfixedvars != NULL);
9424 assert(ndelconss != NULL);
9425
9426 consdata = SCIPconsGetData(cons);
9427 assert(consdata != NULL);
9428 assert(consdata->nvars == 1);
9429 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9430
9431 /* calculate the value to fix the variable to */
9432 var = consdata->vars[0];
9433 val = consdata->vals[0];
9434 assert(!SCIPisZero(scip, val));
9435 fixval = SCIPselectSimpleValue(consdata->lhs/val - 0.9 * SCIPepsilon(scip),
9436 consdata->rhs/val + 0.9 * SCIPepsilon(scip), MAXDNOM);
9437 SCIPdebugMsg(scip, "linear equality <%s>: fix <%s> == %.15g\n",
9438 SCIPconsGetName(cons), SCIPvarGetName(var), fixval);
9439
9440 /* fix variable */
9441 SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
9442 if( infeasible )
9443 {
9444 SCIPdebugMsg(scip, " -> infeasible fixing\n");
9445 *cutoff = TRUE;
9446 return SCIP_OKAY;
9447 }
9448 if( fixed )
9449 (*nfixedvars)++;
9450
9451 /* disable constraint */
9452 SCIP_CALL( SCIPdelCons(scip, cons) );
9453 if( !consdata->upgraded )
9454 (*ndelconss)++;
9455
9456 return SCIP_OKAY;
9457}
9458
9459/** processes equality with exactly two variables by aggregating one of the variables and deleting the constraint */
9460static
9462 SCIP* scip, /**< SCIP data structure */
9463 SCIP_CONS* cons, /**< linear constraint */
9464 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9465 int* naggrvars, /**< pointer to count number of aggregated variables */
9466 int* ndelconss /**< pointer to count number of deleted constraints */
9467 )
9468{
9469 SCIP_CONSDATA* consdata;
9470 SCIP_Bool infeasible;
9471 SCIP_Bool redundant;
9472 SCIP_Bool aggregated;
9473
9474 assert(scip != NULL);
9475 assert(cons != NULL);
9476 assert(cutoff != NULL);
9477 assert(naggrvars != NULL);
9478 assert(ndelconss != NULL);
9479
9480 consdata = SCIPconsGetData(cons);
9481 assert(consdata != NULL);
9482 assert(consdata->nvars == 2);
9483 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9484
9485 SCIPdebugMsg(scip, "linear constraint <%s>: aggregate %.15g<%s> + %.15g<%s> == %.15g\n",
9486 SCIPconsGetName(cons), consdata->vals[0], SCIPvarGetName(consdata->vars[0]),
9487 consdata->vals[1], SCIPvarGetName(consdata->vars[1]), consdata->rhs);
9488
9489 /* aggregate the equality */
9490 SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], consdata->vals[0], consdata->vals[1],
9491 consdata->rhs, &infeasible, &redundant, &aggregated) );
9492
9493 /* check for infeasibility of aggregation */
9494 if( infeasible )
9495 {
9496 SCIPdebugMsg(scip, " -> infeasible aggregation\n");
9497 *cutoff = TRUE;
9498 return SCIP_OKAY;
9499 }
9500
9501 /* count the aggregation */
9502 if( aggregated )
9503 (*naggrvars)++;
9504
9505 /* delete the constraint, if it is redundant */
9506 if( redundant )
9507 {
9508 SCIP_CALL( SCIPdelCons(scip, cons) );
9509
9510 if( !consdata->upgraded )
9511 (*ndelconss)++;
9512 }
9513
9514 return SCIP_OKAY;
9515}
9516
9517/** calculates the new lhs and rhs of the constraint after the given variable is aggregated out */
9518static
9520 SCIP* scip, /**< SCIP data structure */
9521 SCIP_CONSDATA* consdata, /**< linear constraint data */
9522 SCIP_VAR* slackvar, /**< variable to be aggregated out */
9523 SCIP_Real slackcoef, /**< coefficient of variable in constraint */
9524 SCIP_Real* newlhs, /**< pointer to store new lhs of constraint */
9525 SCIP_Real* newrhs /**< pointer to store new rhs of constraint */
9526 )
9527{
9528 SCIP_Real slackvarlb;
9529 SCIP_Real slackvarub;
9530
9531 assert(scip != NULL);
9532 assert(consdata != NULL);
9533 assert(newlhs != NULL);
9534 assert(newrhs != NULL);
9535 assert(!SCIPisInfinity(scip, -consdata->lhs));
9536 assert(!SCIPisInfinity(scip, consdata->rhs));
9537
9538 slackvarlb = SCIPvarGetLbGlobal(slackvar);
9539 slackvarub = SCIPvarGetUbGlobal(slackvar);
9540 if( slackcoef > 0.0 )
9541 {
9542 if( SCIPisInfinity(scip, -slackvarlb) )
9543 *newrhs = SCIPinfinity(scip);
9544 else
9545 *newrhs = consdata->rhs - slackcoef * slackvarlb;
9546 if( SCIPisInfinity(scip, slackvarub) )
9547 *newlhs = -SCIPinfinity(scip);
9548 else
9549 *newlhs = consdata->lhs - slackcoef * slackvarub;
9550 }
9551 else
9552 {
9553 if( SCIPisInfinity(scip, -slackvarlb) )
9554 *newlhs = -SCIPinfinity(scip);
9555 else
9556 *newlhs = consdata->rhs - slackcoef * slackvarlb;
9557 if( SCIPisInfinity(scip, slackvarub) )
9558 *newrhs = SCIPinfinity(scip);
9559 else
9560 *newrhs = consdata->lhs - slackcoef * slackvarub;
9561 }
9562 assert(SCIPisLE(scip, *newlhs, *newrhs));
9563}
9564
9565/** processes equality with more than two variables by multi-aggregating one of the variables and converting the equality
9566 * into an inequality; if multi-aggregation is not possible, tries to identify one continuous or integer variable that
9567 * is implied integral by this constraint
9568 *
9569 * @todo Check whether a more clever way of avoiding aggregation of variables containing implied integral variables
9570 * can help.
9571 */
9572static
9574 SCIP* scip, /**< SCIP data structure */
9575 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
9576 SCIP_CONS* cons, /**< linear constraint */
9577 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9578 int* naggrvars, /**< pointer to count number of aggregated variables */
9579 int* ndelconss, /**< pointer to count number of deleted constraints */
9580 int* nchgvartypes /**< pointer to count number of changed variable types */
9581 )
9582{
9583 SCIP_CONSDATA* consdata;
9584 SCIP_VAR** vars;
9585 SCIP_Real* vals;
9586 SCIP_VARTYPE bestslacktype;
9587 SCIP_VARTYPE slacktype;
9588 SCIP_IMPLINTTYPE impltype;
9589 SCIP_Real lhs;
9590 SCIP_Real rhs;
9591 SCIP_Real bestslackdomrng;
9592 SCIP_Real minabsval;
9593 SCIP_Real maxabsval;
9594 SCIP_Bool bestremovescons;
9595 SCIP_Bool coefszeroone;
9596 SCIP_Bool coefsintegral;
9597 SCIP_Bool varsintegral;
9598 SCIP_Bool infeasible;
9599 int maxnlocksstay;
9600 int maxnlocksremove;
9601 int bestslackpos;
9602 int bestnlocks;
9603 int ncontvars;
9604 int contvarpos;
9605 int nintvars;
9606 int nweakimplvars;
9607 int nimplvars;
9608 int intvarpos;
9609 int v;
9610
9611 assert(scip != NULL);
9612 assert(cons != NULL);
9613 assert(cutoff != NULL);
9614 assert(naggrvars != NULL);
9615
9616 consdata = SCIPconsGetData(cons);
9617 assert(consdata != NULL);
9618 assert(consdata->nvars > 2);
9619 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9620
9621 SCIPdebugMsg(scip, "linear constraint <%s>: try to multi-aggregate equality\n", SCIPconsGetName(cons));
9622
9623 /* We do not want to increase the total number of non-zeros due to the multi-aggregation.
9624 * Therefore, we have to restrict the number of locks of a variable that is aggregated out.
9625 * maxnlocksstay: maximal sum of lock numbers if the constraint does not become redundant after the aggregation
9626 * maxnlocksremove: maximal sum of lock numbers if the constraint can be deleted after the aggregation
9627 */
9628 lhs = consdata->lhs;
9629 rhs = consdata->rhs;
9630 maxnlocksstay = 0;
9631 if( consdata->nvars == 3 )
9632 {
9633 /* If the constraint becomes redundant, 3 non-zeros are removed, and we get 1 additional non-zero for each
9634 * constraint the variable appears in. Thus, the variable must appear in at most 3 other constraints.
9635 */
9636 maxnlocksremove = 3;
9637 }
9638 else if( consdata->nvars == 4 )
9639 {
9640 /* If the constraint becomes redundant, 4 non-zeros are removed, and we get 2 additional non-zeros for each
9641 * constraint the variable appears in. Thus, the variable must appear in at most 2 other constraints.
9642 */
9643 maxnlocksremove = 2;
9644 }
9645 else
9646 {
9647 /* If the constraint is redundant but has more than 4 variables, we can only accept one other constraint. */
9648 maxnlocksremove = 1;
9649 }
9650
9651 /* the locks on this constraint can be ignored */
9652 if( SCIPconsIsChecked(cons) )
9653 {
9654 if( !SCIPisInfinity(scip, -lhs) )
9655 {
9656 maxnlocksstay++;
9657 maxnlocksremove++;
9658 }
9659 if( !SCIPisInfinity(scip, rhs) )
9660 {
9661 maxnlocksstay++;
9662 maxnlocksremove++;
9663 }
9664 }
9665
9666 /* look for a slack variable s to convert a*x + s == b into lhs <= a*x <= rhs */
9667 vars = consdata->vars;
9668 vals = consdata->vals;
9669 bestslackpos = -1;
9670 bestslacktype = SCIP_VARTYPE_BINARY;
9671 bestnlocks = INT_MAX;
9672 bestremovescons = FALSE;
9673 bestslackdomrng = 0.0;
9674 coefszeroone = TRUE;
9675 coefsintegral = TRUE;
9676 varsintegral = TRUE;
9677 ncontvars = 0;
9678 contvarpos = -1;
9679 nintvars = 0;
9680 nweakimplvars = 0;
9681 nimplvars = 0;
9682 intvarpos = -1;
9683 minabsval = SCIPinfinity(scip);
9684 maxabsval = -1.0;
9685 for( v = 0; v < consdata->nvars; ++v )
9686 {
9687 SCIP_VAR* var;
9688 SCIP_Real val;
9689 SCIP_Real absval;
9690 SCIP_Real varlb;
9691 SCIP_Real varub;
9692 SCIP_Bool iscont;
9693 int nlocks;
9694
9695 assert(vars != NULL);
9696 assert(vals != NULL);
9697
9698 var = vars[v];
9699 assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= 1); /* because variable is locked in this equality */
9701 varlb = SCIPvarGetLbGlobal(var);
9702 varub = SCIPvarGetUbGlobal(var);
9703
9704 val = vals[v];
9705 absval = REALABS(val);
9706 assert(SCIPisPositive(scip, absval));
9707
9708 /* calculate minimal and maximal absolute value */
9709 if( absval < minabsval )
9710 minabsval = absval;
9711 if( absval > maxabsval )
9712 maxabsval = absval;
9713
9714 /** @todo Do not exit here, but continue if we may still detect implied integrality. */
9715 /* do not try to multi aggregate, when numerical bad */
9716 if( maxabsval / minabsval > conshdlrdata->maxmultaggrquot )
9717 return SCIP_OKAY;
9718
9719 impltype = SCIPvarGetImplType(var);
9721 coefszeroone = coefszeroone && SCIPisEQ(scip, absval, 1.0);
9722 coefsintegral = coefsintegral && SCIPisIntegral(scip, val);
9723 varsintegral = varsintegral && (slacktype != SCIP_VARTYPE_CONTINUOUS);
9724 iscont = (slacktype == SCIP_VARTYPE_CONTINUOUS || slacktype == SCIP_DEPRECATED_VARTYPE_IMPLINT);
9725
9726 /* update candidates for continuous -> implint and integer -> implint conversion */
9727 if( slacktype == SCIP_VARTYPE_CONTINUOUS )
9728 {
9729 ncontvars++;
9730 contvarpos = v;
9731 }
9732 else if( slacktype == SCIP_DEPRECATED_VARTYPE_IMPLINT )
9733 {
9734 ++nimplvars;
9735 assert(impltype != SCIP_IMPLINTTYPE_NONE);
9736 if( impltype == SCIP_IMPLINTTYPE_WEAK )
9737 ++nweakimplvars;
9738 }
9739 else if( slacktype == SCIP_VARTYPE_INTEGER )
9740 {
9741 nintvars++;
9742 intvarpos = v;
9743 }
9744
9745 /* check, if variable is already fixed or aggregated */
9746 if( !SCIPvarIsActive(var) )
9747 continue;
9748
9749 /* check, if variable is used in too many other constraints, even if this constraint could be deleted */
9751
9752 if( nlocks > maxnlocksremove )
9753 continue;
9754
9755 /* check, if variable can be used as a slack variable */
9756 if( (iscont || (coefsintegral && varsintegral && SCIPisEQ(scip, absval, 1.0))) &&
9758 {
9759 SCIP_Bool better;
9760 SCIP_Bool equal;
9761 SCIP_Real slackdomrng;
9762
9763 if( SCIPisInfinity(scip, varub) || SCIPisInfinity(scip, -varlb) )
9764 slackdomrng = SCIPinfinity(scip);
9765 /* we do not want to perform multi-aggregation due to numerics, if the bounds are huge */
9766 else if( SCIPisHugeValue(scip, varub) || SCIPisHugeValue(scip, -varlb) )
9767 return SCIP_OKAY;
9768 else
9769 {
9770 slackdomrng = (varub - varlb)*absval;
9771 assert(!SCIPisInfinity(scip, slackdomrng));
9772 }
9773 equal = FALSE;
9774
9775 /* continuous > implied > integer > binary */
9776 better = (slacktype > bestslacktype) || (bestslackpos == -1);
9777 if( !better && slacktype == bestslacktype )
9778 {
9779 better = (nlocks < bestnlocks);
9780 if( nlocks == bestnlocks && !bestremovescons )
9781 {
9782 better = SCIPisGT(scip, slackdomrng, bestslackdomrng);
9783 equal = !better && SCIPisGE(scip, slackdomrng, bestslackdomrng);
9784 }
9785 }
9786
9787 if( better || equal )
9788 {
9789 SCIP_Real minresactivity;
9790 SCIP_Real maxresactivity;
9791 SCIP_Real newlhs;
9792 SCIP_Real newrhs;
9793 SCIP_Bool removescons;
9794 SCIP_Bool ismintight;
9795 SCIP_Bool ismaxtight;
9796 SCIP_Bool isminsettoinfinity;
9797 SCIP_Bool ismaxsettoinfinity;
9798
9799 /* check if the constraint becomes redundant after multi-aggregation */
9800 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
9801 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
9802
9803 /* do not perform the multi-aggregation due to numerics, if we have huge contributions in the residual
9804 * activity
9805 */
9806 if( !ismintight || !ismaxtight )
9807 continue;
9808
9809 getNewSidesAfterAggregation(scip, consdata, var, val, &newlhs, &newrhs);
9810 removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9811
9812 /* check resactivities for reliability */
9813 if( removescons )
9814 {
9815 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
9816 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
9817
9818 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity)
9819 && SCIPisFeasLE(scip, newlhs, minresactivity))
9820 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
9821
9822 removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9823 }
9824
9825 /* if parameter multaggrremove is set to TRUE, only aggregate when this removes constraint */
9826 if( conshdlrdata->multaggrremove && !removescons )
9827 continue;
9828
9829 /* if the constraint does not become redundant, only accept the variable if it does not appear in
9830 * other constraints
9831 */
9832 if( !removescons && nlocks > maxnlocksstay )
9833 continue;
9834
9835 /* prefer variables that make the constraints redundant
9836 * unless there is a continuous better slack
9837 */
9838 if( !bestremovescons && removescons )
9839 better = TRUE;
9840 else if( bestremovescons && !removescons && (bestslacktype > SCIP_VARTYPE_INTEGER || slacktype <= SCIP_VARTYPE_INTEGER) )
9841 better = FALSE;
9842 if( better )
9843 {
9844 bestslackpos = v;
9845 bestslacktype = slacktype;
9846 bestnlocks = nlocks;
9847 bestslackdomrng = slackdomrng;
9848 bestremovescons = removescons;
9849 }
9850 }
9851 }
9852 }
9853
9854 /* if all coefficients and variables are integral, the right hand side must also be integral */
9855 if( coefsintegral && varsintegral && !SCIPisFeasIntegral(scip, consdata->rhs) )
9856 {
9857 SCIPdebugMsg(scip, "linear equality <%s> is integer infeasible\n", SCIPconsGetName(cons));
9859 *cutoff = TRUE;
9860 return SCIP_OKAY;
9861 }
9862
9863 /* if the slack variable is of integer type, and the constraint itself may take fractional values,
9864 * we cannot aggregate the variable, because the integrality condition would get lost
9865 * Similarly, if there are implied integral variables, we cannot aggregate since we might
9866 * loose the integrality condition for this variable.
9867 */
9868 if( bestslackpos >= 0
9869 && (bestslacktype == SCIP_VARTYPE_CONTINUOUS || bestslacktype == SCIP_DEPRECATED_VARTYPE_IMPLINT
9870 || (coefsintegral && varsintegral && nimplvars == 0)) )
9871 {
9872 SCIP_VAR** aggrvars;
9873 SCIP_VAR* slackvar;
9875 SCIP_Real slackcoef;
9876 SCIP_Real aggrconst;
9877 SCIP_Real newlhs;
9878 SCIP_Real newrhs;
9879 SCIP_Bool aggregated;
9880
9881 /* we found a slack variable that only occurs in at most one other constraint:
9882 * a_1*x_1 + ... + a_k*x_k + a'*s == rhs -> s == rhs - a_1/a'*x_1 - ... - a_k/a'*x_k
9883 */
9884 assert(bestslackpos < consdata->nvars);
9885
9886 /* do not multi aggregate binary variables */
9887 if( SCIPvarIsBinary(vars[bestslackpos]) )
9888 return SCIP_OKAY;
9889
9890 /* convert equality into inequality by deleting the slack variable:
9891 * x + a*s == b, l <= s <= u -> b - a*u <= x <= b - a*l
9892 */
9893 slackvar = vars[bestslackpos];
9894 slackcoef = vals[bestslackpos];
9895 assert(!SCIPisZero(scip, slackcoef));
9896 aggrconst = consdata->rhs/slackcoef;
9897
9898 /* allocate temporary memory */
9899 SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars - 1) );
9900 SCIP_CALL( SCIPallocBufferArray(scip, &scalars, consdata->nvars - 1) );
9901
9902 /* set up the multi-aggregation */
9903 SCIPdebugMsg(scip, "linear constraint <%s>: multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(slackvar));
9904 for( v = 0; v < consdata->nvars - 1; ++v )
9905 {
9906 if( v == bestslackpos )
9907 {
9908 aggrvars[v] = vars[consdata->nvars - 1];
9909 scalars[v] = -consdata->vals[consdata->nvars - 1] / slackcoef;
9910 }
9911 else
9912 {
9913 aggrvars[v] = vars[v];
9914 scalars[v] = -consdata->vals[v] / slackcoef;
9915 }
9916 SCIPdebugMsgPrint(scip, " %+.15g<%s>", scalars[v], SCIPvarGetName(aggrvars[v]));
9917 }
9918 SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g], nlocks=%d, maxnlocks=%d, removescons=%u\n",
9919 aggrconst, SCIPvarGetName(slackvar), SCIPvarGetLbGlobal(slackvar), SCIPvarGetUbGlobal(slackvar),
9920 bestnlocks, bestremovescons ? maxnlocksremove : maxnlocksstay, bestremovescons);
9921
9922 /* perform the multi-aggregation */
9923 SCIP_CALL( SCIPmultiaggregateVar(scip, slackvar, consdata->nvars - 1, aggrvars, scalars, aggrconst,
9924 &infeasible, &aggregated) );
9925
9926 /* free temporary memory */
9928 SCIPfreeBufferArray(scip, &aggrvars);
9929
9930 /* check for infeasible aggregation */
9931 if( infeasible )
9932 {
9933 SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
9934 *cutoff = TRUE;
9935 return SCIP_OKAY;
9936 }
9937
9938 /* check for applied aggregation */
9939 if( !aggregated )
9940 {
9941 SCIPdebugMsg(scip, "linear constraint <%s>: multi-aggregation not applicable\n", SCIPconsGetName(cons));
9942 return SCIP_OKAY;
9943 }
9944
9945 ++(*naggrvars);
9946
9947 getNewSidesAfterAggregation(scip, consdata, slackvar, slackcoef, &newlhs, &newrhs);
9948 assert(SCIPisLE(scip, newlhs, newrhs));
9949 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9950 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9951 SCIP_CALL( delCoefPos(scip, cons, bestslackpos) );
9952
9953 /* delete the constraint if it became redundant */
9954 if( bestremovescons )
9955 {
9956 SCIPdebugMsg(scip, "linear constraint <%s>: redundant after multi-aggregation\n", SCIPconsGetName(cons));
9957 SCIP_CALL( SCIPdelCons(scip, cons) );
9958
9959 if( !consdata->upgraded )
9960 (*ndelconss)++;
9961 }
9962 }
9963 else if( ncontvars == 1 )
9964 {
9965 SCIP_VAR* var;
9966
9967 assert(0 <= contvarpos && contvarpos < consdata->nvars);
9968 var = vars[contvarpos];
9970
9971 if( coefsintegral && SCIPisFeasIntegral(scip, consdata->rhs) )
9972 {
9973 /* upgrade continuous variable to an implied integral one, if the absolute value of the coefficient is one */
9974 if( SCIPisEQ(scip, REALABS(vals[contvarpos]), 1.0) )
9975 {
9976 /* convert the continuous variable with coefficient 1.0 into an implied integral variable */
9977 SCIPdebugMsg(scip, "linear constraint <%s>: converting continuous variable <%s> to implied integral variable\n",
9979 /* if the integrality does not depend on weak implied integrality, the variable becomes strongly implied integral */
9980 impltype = nweakimplvars == 0 ? SCIP_IMPLINTTYPE_STRONG : SCIP_IMPLINTTYPE_WEAK;
9981 SCIP_CALL( SCIPchgVarImplType(scip, var, impltype, &infeasible) );
9982 (*nchgvartypes)++;
9983 if( infeasible )
9984 {
9985 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
9986 *cutoff = TRUE;
9987
9988 return SCIP_OKAY;
9989 }
9990 }
9991 /* aggregate continuous variable to an implied integral one if the absolute coefficient is unequal to one */
9992 /* @todo check if the aggregation coefficient should be in some range(, which is not too big) */
9993 else if( !SCIPdoNotAggr(scip) )
9994 {
9995 SCIP_VAR* newvar;
9996 SCIP_Real absval;
9997 char newvarname[SCIP_MAXSTRLEN];
9998 SCIP_Bool redundant;
9999 SCIP_Bool aggregated;
10000
10001 absval = REALABS(vals[contvarpos]);
10002
10003 (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_impl", SCIPvarGetName(var));
10004
10005 /* create new implied integral variable for aggregation */
10006 SCIP_CALL( SCIPcreateVarImpl(scip, &newvar, newvarname, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0,
10009
10010 /* add new variable to problem */
10011 SCIP_CALL( SCIPaddVar(scip, newvar) );
10012
10013#ifdef WITH_DEBUG_SOLUTION
10014 if( SCIPdebugIsMainscip(scip) )
10015 {
10016 SCIP_Real varval;
10017 SCIP_CALL( SCIPdebugGetSolVal(scip, var, &varval) );
10018 SCIP_CALL( SCIPdebugAddSolVal(scip, newvar, absval * varval) );
10019 }
10020#endif
10021
10022 /* convert the continuous variable with coefficient 1.0 into an implied integral variable */
10023 SCIPdebugMsg(scip, "linear constraint <%s>: aggregating continuous variable <%s> to newly created implied integral variable <%s>, aggregation factor = %g\n",
10024 SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(newvar), absval);
10025
10026 /* aggregate continuous and implied integral variable */
10027 SCIP_CALL( SCIPaggregateVars(scip, var, newvar, absval, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
10028
10029 if( infeasible )
10030 {
10031 SCIPdebugMsg(scip, "infeasible aggregation of variable <%s> to implied integral variable <%s>, domain is empty\n",
10033 *cutoff = TRUE;
10034
10035 /* release implied integral variable */
10036 SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10037
10038 return SCIP_OKAY;
10039 }
10040
10041 /* release implied integral variable */
10042 SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10043
10044 if( aggregated )
10045 (*naggrvars)++;
10046 else
10047 return SCIP_OKAY;
10048 }
10049
10050 /* we do not have any event on vartype changes, so we need to manually force this constraint to be presolved
10051 * again
10052 */
10053 consdata->boundstightened = 0;
10054 consdata->rangedrowpropagated = 0;
10055 consdata->presolved = FALSE;
10056 }
10057 }
10058 else if( ncontvars == 0 && nimplvars == 0 && nintvars == 1 && !coefszeroone )
10059 {
10060 SCIP_VAR* var;
10061
10062 /* this seems to help for rococo instances, but does not for rout (where all coefficients are +/- 1.0)
10063 * -> we don't convert integers into implints if the row is a 0/1-row
10064 */
10065 assert(varsintegral);
10066 assert(0 <= intvarpos && intvarpos < consdata->nvars);
10067 var = vars[intvarpos];
10069
10070 if( coefsintegral
10071 && SCIPisEQ(scip, REALABS(vals[intvarpos]), 1.0)
10072 && SCIPisFeasIntegral(scip, consdata->rhs) )
10073 {
10074 /* convert the integer variable with coefficient 1.0 into an implied integral variable */
10075 SCIPdebugMsg(scip, "linear constraint <%s>: converting integer variable <%s> to implied integral variable\n",
10078 (*nchgvartypes)++;
10079 if( infeasible )
10080 {
10081 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10082 *cutoff = TRUE;
10083
10084 return SCIP_OKAY;
10085 }
10086 }
10087 }
10088
10089 return SCIP_OKAY;
10090}
10091
10092/** checks if the given variables and their coefficient are equal (w.r.t. scaling factor) to the objective function */
10093static
10095 SCIP* scip, /**< SCIP data structure */
10096 SCIP_CONSDATA* consdata, /**< linear constraint data */
10097 SCIP_Real* scale, /**< pointer to store the scaling factor between the constraint and the
10098 * objective function */
10099 SCIP_Real* offset /**< pointer to store the offset of the objective function resulting by
10100 * this constraint */
10101 )
10102{
10103 SCIP_VAR** vars;
10104 SCIP_VAR* var;
10106 SCIP_Bool negated;
10107 int nvars;
10108 int v;
10109
10110 vars = consdata->vars;
10111 nvars = consdata->nvars;
10112
10113 assert(vars != NULL);
10114
10115 for( v = 0; v < nvars; ++v )
10116 {
10117 negated = FALSE;
10118 var = vars[v];
10119 assert(var != NULL);
10120
10121 if( SCIPvarIsNegated(var) )
10122 {
10123 negated = TRUE;
10125 assert(var != NULL);
10126 }
10127
10129
10130 /* if a variable has a zero objective coefficient the linear constraint is not a subset of the objective
10131 * function
10132 */
10133 if( SCIPisZero(scip, objval) )
10134 return FALSE;
10135 else
10136 {
10137 SCIP_Real val;
10138
10139 val = consdata->vals[v];
10140
10141 if( negated )
10142 {
10143 if( v == 0 )
10144 {
10145 /* the first variable defines the scale */
10146 (*scale) = val / -objval;
10147
10148 (*offset) += val;
10149 }
10150 else if( SCIPisEQ(scip, -objval * (*scale), val) )
10151 (*offset) += val;
10152 else
10153 return FALSE;
10154 }
10155 else if( v == 0 )
10156 {
10157 /* the first variable defines the scale */
10158 (*scale) = val / objval;
10159 }
10160 else if( !SCIPisEQ(scip, objval * (*scale), val) )
10161 return FALSE;
10162 }
10163 }
10164
10165 return TRUE;
10166}
10167
10168/** check if the linear equality constraint is equal to a subset of the objective function; if so we can remove the
10169 * objective coefficients and add an objective offset
10170 */
10171static
10173 SCIP* scip, /**< SCIP data structure */
10174 SCIP_CONS* cons, /**< linear equation constraint */
10175 SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10176 )
10177{
10178 SCIP_CONSDATA* consdata;
10179 SCIP_Real offset;
10180 SCIP_Real scale;
10181 SCIP_Bool applicable;
10182 int nobjvars;
10183 int nvars;
10184 int v;
10185
10186 assert(scip != NULL);
10187 assert(cons != NULL);
10188 assert(conshdlrdata != NULL);
10189
10190 consdata = SCIPconsGetData(cons);
10191 assert(consdata != NULL);
10192 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
10193
10194 nvars = consdata->nvars;
10195 nobjvars = SCIPgetNObjVars(scip);
10196
10197 /* check if the linear equality constraints does not have more variables than the objective function */
10198 if( nvars > nobjvars || nvars == 0 )
10199 return SCIP_OKAY;
10200
10201 /* check for allowance of algorithm */
10202 if( (nvars < nobjvars && !conshdlrdata->detectpartialobjective) ||
10203 (nvars == nobjvars && (!conshdlrdata->detectcutoffbound || !conshdlrdata->detectlowerbound)) )
10204 return SCIP_OKAY;
10205
10206 offset = consdata->rhs;
10207 scale = 1.0;
10208
10209 /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10210 applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10211
10212 if( applicable )
10213 {
10214 SCIP_VAR** vars;
10215
10216 vars = consdata->vars;
10217 assert(vars != NULL);
10218
10219 offset /= scale;
10220
10221 SCIPdebugMsg(scip, "linear equality constraint <%s> == %g (offset %g) is a subset of the objective function\n",
10222 SCIPconsGetName(cons), consdata->rhs, offset);
10223
10224 /* make equality a model constraint to ensure optimality in this direction */
10227
10228 /* set all objective coefficient to zero */
10229 for( v = 0; v < nvars; ++v )
10230 {
10231 SCIP_CALL( SCIPchgVarObj(scip, vars[v], 0.0) );
10232 }
10233
10234 /* add an objective offset */
10235 SCIP_CALL( SCIPaddObjoffset(scip, offset) );
10236 }
10237
10238 return SCIP_OKAY;
10239}
10240
10241/** updates the cutoff if the given primal bound (which is implied by the given constraint) is better */
10242static
10244 SCIP* scip, /**< SCIP data structure */
10245 SCIP_CONS* cons, /**< constraint */
10246 SCIP_Real primalbound /**< feasible primal bound */
10247 )
10248{
10249 SCIP_Real cutoffbound;
10250
10251 /* increase the cutoff bound value by an epsilon to ensue that solution with the value of the cutoff bound are still
10252 * accepted
10253 */
10254 cutoffbound = primalbound + SCIPcutoffbounddelta(scip);
10255
10256 if( cutoffbound < SCIPgetCutoffbound(scip) )
10257 {
10258 SCIPdebugMsg(scip, "update cutoff bound <%g>\n", cutoffbound);
10259
10260 SCIP_CALL( SCIPupdateCutoffbound(scip, cutoffbound) );
10261 }
10262 else
10263 {
10264 SCIP_CONSDATA* consdata;
10265
10266 consdata = SCIPconsGetData(cons);
10267 assert(consdata != NULL);
10268
10269 /* we cannot disable the enforcement and propagation on ranged rows, because the cutoffbound could only have
10270 * resulted from one side
10271 */
10272 if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
10273 {
10274 /* in case the cutoff bound is worse then the currently known one, we additionally avoid enforcement and
10275 * propagation
10276 */
10279 }
10280 }
10281
10282 return SCIP_OKAY;
10283}
10284
10285/** check if the linear constraint is parallel to objective function; if so update the cutoff bound and avoid that the
10286 * constraint enters the LP by setting the initial and separated flag to FALSE
10287 */
10288static
10290 SCIP* scip, /**< SCIP data structure */
10291 SCIP_CONS* cons, /**< linear constraint */
10292 SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10293 )
10294{
10295 SCIP_CONSDATA* consdata;
10296 SCIP_Real offset;
10297 SCIP_Real scale;
10298 SCIP_Bool applicable;
10299 int nobjvars;
10300 int nvars;
10301
10302 assert(scip != NULL);
10303 assert(cons != NULL);
10304 assert(conshdlrdata != NULL);
10305
10306 consdata = SCIPconsGetData(cons);
10307 assert(consdata != NULL);
10308
10309 /* ignore equalities since these are covered by the method checkPartialObjective() */
10310 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10311 return SCIP_OKAY;
10312
10313 nvars = consdata->nvars;
10314 nobjvars = SCIPgetNObjVars(scip);
10315
10316 /* check if the linear inequality constraints has the same number of variables as the objective function and if the
10317 * initial and/or separated flag is set to FALSE
10318 */
10319 if( nvars != nobjvars || (!SCIPconsIsInitial(cons) && !SCIPconsIsSeparated(cons)) )
10320 return SCIP_OKAY;
10321
10322 offset = 0.0;
10323 scale = 1.0;
10324
10325 /* There are no variables in the objective function and in the constraint. Thus, the constraint is redundant or proves
10326 * infeasibility. Since we have a pure feasibility problem, we do not want to set a cutoff or lower bound.
10327 */
10328 if( nobjvars == 0 )
10329 return SCIP_OKAY;
10330
10331 /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10332 applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10333
10334 if( applicable )
10335 {
10336 SCIP_Bool rhsfinite = !SCIPisInfinity(scip, consdata->rhs);
10337 SCIP_Bool lhsfinite = !SCIPisInfinity(scip, -consdata->lhs);
10338
10339 assert(scale != 0.0);
10340
10341 if( scale > 0.0 )
10342 {
10343 if( conshdlrdata->detectcutoffbound && rhsfinite )
10344 {
10345 SCIP_Real primalbound;
10346
10347 primalbound = (consdata->rhs - offset) / scale;
10348
10349 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10350 SCIPconsGetName(cons), primalbound);
10351
10352 SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10353 }
10354
10355 if( conshdlrdata->detectlowerbound && lhsfinite )
10356 {
10357 SCIP_Real lowerbound;
10358
10359 lowerbound = (consdata->lhs - offset) / scale;
10360
10361 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10362 SCIPconsGetName(cons), lowerbound);
10363
10365 }
10366
10367 if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !lhsfinite)) ||
10368 (conshdlrdata->detectlowerbound && !rhsfinite) )
10369 {
10370 /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10373 }
10374 }
10375 else
10376 {
10377 if( conshdlrdata->detectlowerbound && rhsfinite )
10378 {
10379 SCIP_Real lowerbound;
10380
10381 lowerbound = (consdata->rhs - offset) / scale;
10382
10383 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10384 SCIPconsGetName(cons), lowerbound);
10385
10387 }
10388
10389 if( conshdlrdata->detectcutoffbound && lhsfinite )
10390 {
10391 SCIP_Real primalbound;
10392
10393 primalbound = (consdata->lhs - offset) / scale;
10394
10395 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10396 SCIPconsGetName(cons), primalbound);
10397
10398 SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10399 }
10400
10401 if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !rhsfinite)) ||
10402 (conshdlrdata->detectlowerbound && !lhsfinite) )
10403 {
10404 /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10407 }
10408 }
10409 }
10410
10411 return SCIP_OKAY;
10412}
10413
10414/** converts special equalities */
10415static
10417 SCIP* scip, /**< SCIP data structure */
10418 SCIP_CONS* cons, /**< linear constraint */
10419 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10420 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10421 int* nfixedvars, /**< pointer to count number of fixed variables */
10422 int* naggrvars, /**< pointer to count number of aggregated variables */
10423 int* ndelconss, /**< pointer to count number of deleted constraints */
10424 int* nchgvartypes /**< pointer to count number of changed variable types */
10425 )
10426{
10427 SCIP_CONSDATA* consdata;
10428
10429 assert(scip != NULL);
10430 assert(cons != NULL);
10431 assert(conshdlrdata != NULL);
10432 assert(cutoff != NULL);
10433 assert(nfixedvars != NULL);
10434 assert(naggrvars != NULL);
10435 assert(ndelconss != NULL);
10436
10437 consdata = SCIPconsGetData(cons);
10438 assert(consdata != NULL);
10439 assert(consdata->removedfixings);
10440
10441 /* do nothing on inequalities */
10442 if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10443 return SCIP_OKAY;
10444
10445 /* depending on the number of variables, call a special conversion method */
10446 if( consdata->nvars == 1 )
10447 {
10448 /* fix variable */
10449 SCIP_CALL( convertUnaryEquality(scip, cons, cutoff, nfixedvars, ndelconss) );
10450 }
10451 else if( consdata->nvars == 2 )
10452 {
10453 /* aggregate one of the variables */
10454 SCIP_CALL( convertBinaryEquality(scip, cons, cutoff, naggrvars, ndelconss) );
10455 }
10456 else
10457 {
10458 /* check if the equality is part of the objective function */
10459 SCIP_CALL( checkPartialObjective(scip, cons, conshdlrdata) );
10460
10461 /* try to multi-aggregate one of the variables */
10462 SCIP_CALL( convertLongEquality(scip, conshdlrdata, cons, cutoff, naggrvars, ndelconss, nchgvartypes) );
10463 }
10464
10465 return SCIP_OKAY;
10466}
10467
10468/** returns whether the linear sum of all variables/coefficients except the given one divided by the given value is always
10469 * integral
10470 */
10471static
10473 SCIP* scip, /**< SCIP data structure */
10474 SCIP_CONSDATA* consdata, /**< linear constraint */
10475 int pos, /**< position of variable to be left out */
10476 SCIP_Real val /**< value to divide the coefficients by */
10477 )
10478{
10479 int v;
10480
10481 assert(scip != NULL);
10482 assert(consdata != NULL);
10483 assert(0 <= pos && pos < consdata->nvars);
10484
10485 for( v = 0; v < consdata->nvars; ++v )
10486 {
10487 if( v != pos && (!SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v]/val)) )
10488 return FALSE;
10489 }
10490
10491 return TRUE;
10492}
10493
10494/** 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$,
10495 * 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$
10496 */
10497static
10499 SCIP* scip, /**< SCIP data structure */
10500 SCIP_Real side, /**< lhs or rhs */
10501 SCIP_Real val, /**< coefficient */
10502 SCIP_Real minresactivity, /**< minimal residual activity */
10503 SCIP_Real maxresactivity, /**< maximal residual activity */
10504 SCIP_Real* minval, /**< pointer to store calculated minval */
10505 SCIP_Real* maxval /**< pointer to store calculated maxval */
10506 )
10507{
10508 assert(scip != NULL);
10509 assert(minval != NULL);
10510 assert(maxval != NULL);
10511
10512 if( val > 0.0 )
10513 {
10514 if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10515 *minval = -maxresactivity;
10516 else
10517 *minval = (side - maxresactivity)/val;
10518
10519 if( SCIPisInfinity(scip, ABS(minresactivity)) )
10520 *maxval = -minresactivity;
10521 else
10522 *maxval = (side - minresactivity)/val;
10523 }
10524 else
10525 {
10526 if( SCIPisInfinity(scip, ABS(minresactivity)) )
10527 *minval = minresactivity;
10528 else
10529 *minval = (side - minresactivity)/val;
10530
10531 if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10532 *maxval = maxresactivity;
10533 else
10534 *maxval = (side - maxresactivity)/val;
10535 }
10536}
10537
10538
10539/** applies dual presolving for variables that are locked only once in a direction, and this locking is due to a
10540 * linear inequality
10541 */
10542static
10544 SCIP* scip, /**< SCIP data structure */
10545 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10546 SCIP_CONS* cons, /**< linear constraint */
10547 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10548 int* nfixedvars, /**< pointer to count number of fixed variables */
10549 int* naggrvars, /**< pointer to count number of aggregated variables */
10550 int* ndelconss, /**< pointer to count number of deleted constraints */
10551 int* nchgvartypes /**< pointer to count number of changed variable types */
10552 )
10553{
10554 SCIP_CONSDATA* consdata;
10555 SCIP_Bool lhsexists;
10556 SCIP_Bool rhsexists;
10557 SCIP_Bool bestisint;
10558 SCIP_Bool bestislhs;
10559 SCIP_Real minabsval;
10560 SCIP_Real maxabsval;
10561 int bestpos;
10562 int i;
10563 int maxotherlocks;
10564
10565 assert(scip != NULL);
10566 assert(cons != NULL);
10567 assert(cutoff != NULL);
10568 assert(nfixedvars != NULL);
10569 assert(naggrvars != NULL);
10570 assert(ndelconss != NULL);
10571
10572 /* only process checked constraints (for which the locks are increased);
10573 * otherwise we would have to check for variables with nlocks == 0, and these are already processed by the
10574 * dualfix presolver
10575 */
10576 if( !SCIPconsIsChecked(cons) )
10577 return SCIP_OKAY;
10578
10579 consdata = SCIPconsGetData(cons);
10580 assert(consdata != NULL);
10581
10582 lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
10583 rhsexists = !SCIPisInfinity(scip, consdata->rhs);
10584
10585 /* search for a single-locked variable which can be multi-aggregated; if a valid continuous variable was found, we
10586 * can use it safely for aggregation and break the search loop
10587 */
10588 bestpos = -1;
10589 bestisint = TRUE;
10590 bestislhs = FALSE;
10591
10592 /* We only want to multi-aggregate variables, if they appear in maximal one additional constraint,
10593 * everything else would produce fill-in. Exceptions:
10594 * - If there are only two variables in the constraint from which the multi-aggregation arises, no fill-in will be
10595 * produced.
10596 * - If there are three variables in the constraint, multi-aggregation in three additional constraints will remove
10597 * six nonzeros (three from the constraint and the three entries of the multi-aggregated variable) and add
10598 * six nonzeros (two variables per substitution).
10599 * - If there at most four variables in the constraint, multi-aggregation in two additional constraints will remove
10600 * six nonzeros (four from the constraint and the two entries of the multi-aggregated variable) and add
10601 * six nonzeros (three variables per substitution). God exists!
10602 */
10603 if( consdata->nvars <= 2 )
10604 maxotherlocks = INT_MAX;
10605 else if( consdata->nvars == 3 )
10606 maxotherlocks = 3;
10607 else if( consdata->nvars == 4 )
10608 maxotherlocks = 2;
10609 else
10610 maxotherlocks = 1;
10611
10612 /* if this constraint has both sides, it also provides a lock for the other side and thus we can allow one more lock */
10613 if( lhsexists && rhsexists && maxotherlocks < INT_MAX )
10614 maxotherlocks++;
10615
10616 minabsval = SCIPinfinity(scip);
10617 maxabsval = -1.0;
10618 for( i = 0; i < consdata->nvars && bestisint; ++i )
10619 {
10620 SCIP_VAR* var;
10621 SCIP_Bool isint;
10622 SCIP_Real val;
10623 SCIP_Real absval;
10624 SCIP_Real obj;
10625 SCIP_Real lb;
10626 SCIP_Real ub;
10627 SCIP_Bool agglhs;
10628 SCIP_Bool aggrhs;
10629
10630 val = consdata->vals[i];
10631 absval = REALABS(val);
10632
10633 /* calculate minimal and maximal absolute value */
10634 if( absval < minabsval )
10635 minabsval = absval;
10636 if( absval > maxabsval )
10637 maxabsval = absval;
10638
10639 /* do not try to multi aggregate, when numerical bad */
10640 if( maxabsval / minabsval > conshdlrdata->maxdualmultaggrquot )
10641 return SCIP_OKAY;
10642
10643 var = consdata->vars[i];
10645
10646 /* if we already found a candidate, skip integers */
10647 if( bestpos >= 0 && isint )
10648 continue;
10649
10650 /* better do not multi-aggregate binary variables, since most plugins rely on their binary variables to be either
10651 * active, fixed, or single-aggregated with another binary variable
10652 */
10653 if( SCIPvarIsBinary(var) && consdata->nvars > 2 )
10654 continue;
10655
10657 continue;
10658
10659 val = consdata->vals[i];
10661 lb = SCIPvarGetLbGlobal(var);
10662 ub = SCIPvarGetUbGlobal(var);
10663
10664 /* lhs <= a_0 * x_0 + a_1 * x_1 + ... + a_{n-1} * x_{n-1} <= rhs
10665 *
10666 * a_i >= 0, c_i >= 0, lhs exists, nlocksdown(x_i) == 1:
10667 * - constraint is the only one that forbids fixing the variable to its lower bound
10668 * - 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
10669 *
10670 * a_i <= 0, c_i <= 0, lhs exists, nlocksup(x_i) == 1:
10671 * - constraint is the only one that forbids fixing the variable to its upper bound
10672 * - 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
10673 *
10674 * a_i >= 0, c_i <= 0, rhs exists, nlocksup(x_i) == 1:
10675 * - constraint is the only one that forbids fixing the variable to its upper bound
10676 * - 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
10677 *
10678 * a_i <= 0, c_i >= 0, rhs exists, nlocksdown(x_i) == 1:
10679 * - constraint is the only one that forbids fixing the variable to its lower bound
10680 * - 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
10681 *
10682 * but: all this is only applicable, if the aggregated value is inside x_i's bounds for all possible values
10683 * of all x_j
10684 * furthermore: we only want to apply this, if no fill-in will be produced
10685 */
10686 agglhs = lhsexists
10688 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10690 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10691 aggrhs = rhsexists
10693 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10695 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10696 if( agglhs || aggrhs )
10697 {
10698 SCIP_Real minresactivity;
10699 SCIP_Real maxresactivity;
10700 SCIP_Real minval;
10701 SCIP_Real maxval;
10702 SCIP_Bool ismintight;
10703 SCIP_Bool ismaxtight;
10704 SCIP_Bool isminsettoinfinity;
10705 SCIP_Bool ismaxsettoinfinity;
10706
10707 /* calculate bounds for \sum_{j \neq i} a_j * x_j */
10708 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
10709 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
10710 assert(SCIPisLE(scip, minresactivity, maxresactivity));
10711
10712 /* We called consdataGetActivityResiduals() saying that we do not need a good relaxation,
10713 * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
10714 * This is needed, because we do not want to rely on relaxed finite resactivities.
10715 */
10716 assert((ismintight || isminsettoinfinity) && (ismaxtight || ismaxsettoinfinity));
10717
10718 if( agglhs )
10719 {
10720 /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10721 calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10722
10723 assert(SCIPisLE(scip, minval, maxval));
10724 if( !SCIPisInfinity(scip, -minval) && SCIPisGE(scip, minval, lb)
10725 && !SCIPisInfinity(scip, maxval) && SCIPisLE(scip, maxval, ub) )
10726 {
10727 SCIP_Real oldmaxresactivity;
10728 SCIP_Real oldminresactivity;
10729 SCIP_Bool recalculated;
10730
10731 recalculated = FALSE;
10732 oldmaxresactivity = maxresactivity;
10733 oldminresactivity = minresactivity;
10734
10735 /* check minresactivity for reliability */
10736 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10737 {
10738 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10739 recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10740 isminsettoinfinity = TRUE; /* here it means only that it was even calculated */
10741 }
10742
10743 /* check maxresactivity for reliability */
10744 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10745 {
10746 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10747 recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10748 ismaxsettoinfinity = TRUE; /* here it means only that it was even calculated */
10749 }
10750
10751 /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10752 if( recalculated )
10753 {
10754 assert(SCIPisLE(scip, minresactivity, maxresactivity));
10755
10756 /* check again if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10757 calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10758
10759 assert(SCIPisLE(scip, minval, maxval));
10760 }
10761
10762 if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10763 {
10764 /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10765 * in the multi-aggregation
10766 */
10767 if( !isint || (SCIPisIntegral(scip, consdata->lhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10768 {
10769 bestpos = i;
10770 bestisint = isint;
10771 bestislhs = TRUE;
10772 continue; /* no need to also look at the right hand side */
10773 }
10774 }
10775 }
10776 }
10777
10778 if( aggrhs )
10779 {
10780 /* check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10781 calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10782
10783 assert(SCIPisLE(scip,minval,maxval));
10784 if( !SCIPisInfinity(scip, -minval) && SCIPisGE(scip, minval, lb)
10785 && !SCIPisInfinity(scip, maxval) && SCIPisLE(scip, maxval, ub) )
10786 {
10787 SCIP_Real oldmaxresactivity;
10788 SCIP_Real oldminresactivity;
10789 SCIP_Bool recalculated;
10790
10791 recalculated = FALSE;
10792 oldmaxresactivity = maxresactivity;
10793 oldminresactivity = minresactivity;
10794
10795 /* check minresactivity for reliability */
10796 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10797 {
10798 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10799 recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10800 }
10801
10802 /* check maxresactivity for reliability */
10803 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10804 {
10805 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10806 recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10807 }
10808
10809 /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10810 if( recalculated )
10811 {
10812 /* check again if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10813 calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10814 assert(SCIPisLE(scip,minval,maxval));
10815 }
10816
10817 if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10818 {
10819 /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10820 * in the multi-aggregation
10821 */
10822 if( !isint || (SCIPisIntegral(scip, consdata->rhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10823 {
10824 bestpos = i;
10825 bestisint = isint;
10826 bestislhs = FALSE;
10827 }
10828 }
10829 }
10830 }
10831 }
10832 }
10833
10834 if( bestpos >= 0 )
10835 {
10836 SCIP_VAR** aggrvars;
10837 SCIP_Real* aggrcoefs;
10838 SCIP_Real aggrconst;
10839 SCIP_VAR* bestvar;
10840 SCIP_Real bestval;
10841 int naggrs;
10842 int j;
10843 SCIP_Bool infeasible;
10844 SCIP_Bool aggregated;
10845
10846 assert(!bestislhs || lhsexists);
10847 assert(bestislhs || rhsexists);
10848
10849 bestvar = consdata->vars[bestpos];
10850 bestval = consdata->vals[bestpos];
10851 assert(bestisint == SCIPvarIsNonimpliedIntegral(bestvar));
10852
10853 /* allocate temporary memory */
10854 SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars-1) );
10855 SCIP_CALL( SCIPallocBufferArray(scip, &aggrcoefs, consdata->nvars-1) );
10856
10857 /* set up the multi-aggregation */
10859 SCIPdebugMsg(scip, "linear constraint <%s> (dual): multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(bestvar));
10860 naggrs = 0;
10861
10862 for( j = 0; j < consdata->nvars; ++j )
10863 {
10864 if( j != bestpos )
10865 {
10866 aggrvars[naggrs] = consdata->vars[j];
10867 aggrcoefs[naggrs] = -consdata->vals[j]/consdata->vals[bestpos];
10868
10869 SCIPdebugMsgPrint(scip, " %+.15g<%s>", aggrcoefs[naggrs], SCIPvarGetName(aggrvars[naggrs]));
10870
10871 /* do not try to multi aggregate, when numerical bad */
10872 if( SCIPisZero(scip, aggrcoefs[naggrs]) )
10873 {
10874 SCIPdebugMsg(scip, "do not perform multi-aggregation: too large aggregation coefficients\n");
10875
10876 /* free temporary memory */
10877 SCIPfreeBufferArray(scip, &aggrcoefs);
10878 SCIPfreeBufferArray(scip, &aggrvars);
10879
10880 return SCIP_OKAY;
10881 }
10882
10883 if( bestisint )
10884 {
10885 /* coefficient must be integral: round it to exact integral value */
10886 assert(SCIPisIntegral(scip, aggrcoefs[naggrs]));
10887 aggrcoefs[naggrs] = SCIPfloor(scip, aggrcoefs[naggrs]+0.5);
10888 }
10889
10890 naggrs++;
10891 }
10892 }
10893
10894 aggrconst = (bestislhs ? consdata->lhs/bestval : consdata->rhs/bestval);
10895 SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g]\n", aggrconst, SCIPvarGetName(bestvar),
10896 SCIPvarGetLbGlobal(bestvar), SCIPvarGetUbGlobal(bestvar));
10897 assert(naggrs == consdata->nvars-1);
10898
10899 /* right hand side must be integral: round it to exact integral value */
10900 if( bestisint )
10901 {
10902 assert(SCIPisIntegral(scip, aggrconst));
10903 aggrconst = SCIPfloor(scip, aggrconst+0.5);
10904 }
10905
10906 aggregated = FALSE;
10907 infeasible = FALSE;
10908
10909 /* perform the multi-aggregation */
10910 SCIP_CALL( SCIPmultiaggregateVar(scip, bestvar, naggrs, aggrvars, aggrcoefs, aggrconst, &infeasible, &aggregated) );
10911
10912 /** @todo handle this case properly with weak and strong implied integrality */
10913 /* if the multi-aggregated bestvar is enforced but not strongly implied integral, we need to convert implied
10914 * integral to integer variables because integrality of the multi-aggregated variable must hold
10915 */
10916 if( !infeasible && aggregated && SCIPvarGetType(bestvar) != SCIP_VARTYPE_CONTINUOUS && SCIPvarGetImplType(bestvar) != SCIP_IMPLINTTYPE_STRONG )
10917 {
10918 SCIP_Bool infeasiblevartypechg = FALSE;
10919
10920 for( j = 0; j < naggrs; ++j )
10921 {
10922 /* if the multi-aggregation was not infeasible, then setting implied integral to integer should not
10923 * lead to infeasibility
10924 */
10926 {
10927 if( SCIPvarGetType(aggrvars[j]) == SCIP_VARTYPE_CONTINUOUS )
10928 {
10929 SCIP_CALL( SCIPchgVarType(scip, aggrvars[j], SCIP_VARTYPE_INTEGER, &infeasiblevartypechg) );
10930 assert(!infeasiblevartypechg);
10931 }
10932 SCIP_CALL( SCIPchgVarImplType(scip, aggrvars[j], SCIP_IMPLINTTYPE_NONE, &infeasiblevartypechg) );
10933 assert(!infeasiblevartypechg);
10934 (*nchgvartypes)++;
10935 }
10936 }
10937 }
10938
10939 /* free temporary memory */
10940 SCIPfreeBufferArray(scip, &aggrcoefs);
10941 SCIPfreeBufferArray(scip, &aggrvars);
10942
10943 /* check for infeasible aggregation */
10944 if( infeasible )
10945 {
10946 SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
10947 *cutoff = TRUE;
10948 return SCIP_OKAY;
10949 }
10950
10951 /* delete the constraint, if the aggregation was successful */
10952 if( aggregated )
10953 {
10954 SCIP_CALL( SCIPdelCons(scip, cons) );
10955
10956 if( !consdata->upgraded )
10957 (*ndelconss)++;
10958 (*naggrvars)++;
10959 }
10960 else
10961 {
10962 SCIPdebugMsg(scip, "aggregation non successful!\n");
10963 }
10964 }
10965
10966 return SCIP_OKAY;
10967}
10968
10969#define BINWEIGHT 1
10970#define INTWEIGHT 4
10971#define CONTWEIGHT 8
10972
10973/** gets weight for variable in a "weighted number of variables" sum */
10974static
10976 SCIP_VAR* var /**< variable to get weight for */
10977 )
10978{
10980 return INTWEIGHT;
10981
10982 switch( SCIPvarGetType(var) )
10983 {
10985 return BINWEIGHT;
10987 return INTWEIGHT;
10989 return CONTWEIGHT;
10990 default:
10991 SCIPerrorMessage("unknown variable type\n");
10992 SCIPABORT();
10993 return 0; /*lint !e527*/
10994 } /*lint !e788*/
10995}
10996
10997/** tries to aggregate variables in equations a^Tx = lhs
10998 * in case there are at most two binary variables with an odd coefficient and all other
10999 * variables are not continuous and have an even coefficient then:
11000 * - exactly one odd binary variables
11001 * this binary variables y can be fixed to 0 if the lhs is even and to 1 if the lhs is odd
11002 * - lhs is odd -> y = 1
11003 * - lhs is even -> y = 0
11004 * - exactly two odd binary variables
11005 * aggregate the two binary variables with odd coefficient
11006 * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11007 * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11008 */
11009static
11011 SCIP* scip, /**< SCIP data structure */
11012 SCIP_CONS* cons, /**< linear constraint */
11013 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
11014 int* nfixedvars, /**< pointer to count number of fixed variables */
11015 int* naggrvars /**< pointer to count number of aggregated variables */
11016 )
11017{ /*lint --e{715}*/
11018 SCIP_CONSDATA* consdata;
11019 SCIP_Bool success;
11020
11021 assert( scip != NULL );
11022 assert( cons != NULL );
11023
11024 consdata = SCIPconsGetData(cons);
11025 assert( consdata != NULL );
11026
11027 /* check if the linear constraint is an equation with integral right hand side */
11028 if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) || !SCIPisIntegral(scip, consdata->lhs) )
11029 return SCIP_OKAY;
11030
11031 /* try to fix and aggregated variables until nothing is possible anymore */
11032 do
11033 {
11034 int v;
11035 int nvars;
11036 SCIP_VAR** vars;
11037 SCIP_Real* vals;
11038 SCIP_Real lhs;
11039 SCIP_Bool lhsodd;
11040
11041 SCIP_Bool infeasible;
11042 SCIP_Bool fixed;
11043 SCIP_Bool aggregated;
11044 SCIP_Bool redundant;
11045
11046 SCIP_VAR* var1;
11047 SCIP_VAR* var2;
11048 int noddvars;
11049
11050 success = FALSE;
11051
11052 lhs = consdata->lhs;
11053 vars = consdata->vars;
11054 vals = consdata->vals;
11055 nvars = consdata->nvars;
11056
11057 assert( !SCIPisInfinity(scip, ABS(lhs)) );
11058
11059 var1 = NULL;
11060 var2 = NULL;
11061 noddvars = 0;
11062
11063 /* search for binary variables with an odd coefficient */
11064 for( v = 0; v < nvars && noddvars < 3; ++v )
11065 {
11066 SCIP_Longint val;
11067
11068 /* all coefficients and variables have to be integral */
11069 if( !SCIPvarIsIntegral(vars[v]) || !SCIPisIntegral(scip, vals[v]) )
11070 return SCIP_OKAY;
11071
11072 val = (SCIP_Longint)SCIPfeasFloor(scip, vals[v]);
11073 if( val % 2 != 0 )
11074 {
11075 /* the odd values have to belong to binary variables */
11076 if( !SCIPvarIsBinary(vars[v]) )
11077 return SCIP_OKAY;
11078
11079 if( noddvars == 0 )
11080 var1 = vars[v];
11081 else
11082 var2 = vars[v];
11083
11084 noddvars++;
11085 }
11086 }
11087
11088 /* check lhs is odd or even */
11089 lhsodd = (((SCIP_Longint)SCIPfeasFloor(scip, lhs)) % 2 != 0);
11090
11091 if( noddvars == 1 )
11092 {
11093 assert( var1 != NULL );
11094
11095 SCIPdebugMsg(scip, "linear constraint <%s>: try fixing variable <%s> to <%g>\n",
11096 SCIPconsGetName(cons), SCIPvarGetName(var1), lhsodd ? 1.0 : 0.0);
11097
11098 SCIP_CALL( SCIPfixVar(scip, var1, lhsodd? 1.0 : 0.0, &infeasible, &fixed) );
11099
11100 /* check for infeasibility of fixing */
11101 if( infeasible )
11102 {
11103 SCIPdebugMsg(scip, " -> infeasible fixing\n");
11104 *cutoff = TRUE;
11105 return SCIP_OKAY;
11106 }
11107
11108 if( fixed )
11109 {
11110 SCIPdebugMsg(scip, " -> feasible fixing\n");
11111 (*nfixedvars)++;
11112 success = TRUE;
11113 }
11114 }
11115 else if( noddvars == 2 )
11116 {
11117 assert( var1 != NULL );
11118 assert( var2 != NULL );
11119
11120 /* aggregate the two variables with odd coefficient
11121 * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11122 * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11123 */
11124 SCIPdebugMsg(scip, "linear constraint <%s>: try aggregation of variables <%s> and <%s>\n",
11125 SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
11126
11127 SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, lhsodd ? 1.0 : -1.0,
11128 lhsodd ? 1.0 : 0.0, &infeasible, &redundant, &aggregated) );
11129
11130 /* check for infeasibility of aggregation */
11131 if( infeasible )
11132 {
11133 SCIPdebugMsg(scip, " -> infeasible aggregation\n");
11134 *cutoff = TRUE;
11135 return SCIP_OKAY;
11136 }
11137
11138 /* count the aggregation */
11139 if( aggregated )
11140 {
11141 SCIPdebugMsg(scip, " -> feasible aggregation\n");
11142 (*naggrvars)++;
11143 success = TRUE;
11144 }
11145 }
11146
11147 if( success )
11148 {
11149 /* apply fixings and aggregation to successfully rerun this presolving step */
11150 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
11151
11152 if( infeasible )
11153 {
11154 SCIPdebugMsg(scip, " -> infeasible fixing\n");
11155 *cutoff = TRUE;
11156 return SCIP_OKAY;
11157 }
11158
11159 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
11160
11161 if( infeasible )
11162 {
11163 SCIPdebugMsg(scip, " -> infeasible normalization\n");
11164 *cutoff = TRUE;
11165 return SCIP_OKAY;
11166 }
11167 }
11168 }
11169 while( success && consdata->nvars >= 1 );
11170
11171 return SCIP_OKAY;
11172}
11173
11174
11175
11176/** sorting method for constraint data, compares two variables on given indices, continuous variables will be sorted to
11177 * the end and for all other variables the sortation will be in non-increasing order of their absolute value of the
11178 * coefficients
11179 */
11180static
11182{ /*lint --e{715}*/
11183 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
11184 SCIP_Real value;
11185
11186 assert(consdata != NULL);
11187 assert(0 <= ind1 && ind1 < consdata->nvars);
11188 assert(0 <= ind2 && ind2 < consdata->nvars);
11189
11190 SCIP_Bool varcont1 = !SCIPvarIsIntegral(consdata->vars[ind1]);
11191 SCIP_Bool varcont2 = !SCIPvarIsIntegral(consdata->vars[ind2]);
11192
11193 if( varcont1 )
11194 {
11195 /* continuous variables will be sorted to the back */
11196 if( varcont1 != varcont2 )
11197 return +1;
11198 /* both variables are continuous */
11199 else
11200 return 0;
11201 }
11202 /* continuous variables will be sorted to the back */
11203 else if( varcont2 )
11204 return -1;
11205
11206 value = REALABS(consdata->vals[ind2]) - REALABS(consdata->vals[ind1]);
11207
11208 /* for all non-continuous variables, the variables are sorted after decreasing absolute coefficients */
11209 return (value > 0 ? +1 : (value < 0 ? -1 : 0));
11210}
11211
11212/** tries to simplify coefficients in ranged row of the form lhs <= a^Tx <= rhs
11213 *
11214 * 1. lhs <= a^Tx <= rhs, x binary, lhs > 0, forall a_i >= lhs, a_i <= rhs, and forall pairs a_i + a_j > rhs,
11215 * then we can change this constraint to 1^Tx = 1
11216 */
11217static
11219 SCIP* scip, /**< SCIP data structure */
11220 SCIP_CONS* cons, /**< linear constraint */
11221 int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11222 int* nchgsides /**< pointer to store the amount of changed sides */
11223 )
11224{
11225 SCIP_CONSDATA* consdata;
11226 SCIP_VAR** vars;
11227 SCIP_Real* vals;
11228 SCIP_Real minval;
11229 SCIP_Real secondminval;
11230 SCIP_Real maxval;
11231 SCIP_Real lhs;
11232 SCIP_Real rhs;
11233 int nvars;
11234 int v;
11235
11236 /* we must not change a modifiable constraint in any way */
11237 if( SCIPconsIsModifiable(cons) )
11238 return SCIP_OKAY;
11239
11240 if( SCIPconsIsDeleted(cons) )
11241 return SCIP_OKAY;
11242
11243 consdata = SCIPconsGetData(cons);
11244 assert(consdata != NULL);
11245
11246 nvars = consdata->nvars;
11247
11248 /* do not check empty or bound-constraints */
11249 if( nvars < 2 )
11250 return SCIP_OKAY;
11251
11252 lhs = consdata->lhs;
11253 rhs = consdata->rhs;
11254 assert(!SCIPisInfinity(scip, -lhs));
11255 assert(!SCIPisInfinity(scip, rhs));
11256 assert(!SCIPisNegative(scip, rhs));
11257
11258 /* sides must be positive and different to detect set partition */
11259 if( !SCIPisPositive(scip, lhs) || !SCIPisLT(scip, lhs, rhs) )
11260 return SCIP_OKAY;
11261
11262 vals = consdata->vals;
11263 vars = consdata->vars;
11264 assert(vars != NULL);
11265 assert(vals != NULL);
11266
11267 minval = SCIP_INVALID;
11268 secondminval = SCIP_INVALID;
11269 maxval = -SCIP_INVALID;
11270
11271 for( v = nvars - 1; v >= 0; --v )
11272 {
11273 if( SCIPvarIsBinary(vars[v]) )
11274 {
11275 if( minval > vals[v] || minval == SCIP_INVALID ) /*lint !e777*/
11276 {
11277 secondminval = minval;
11278 minval = vals[v];
11279 }
11280 else if( secondminval > vals[v] || secondminval == SCIP_INVALID ) /*lint !e777*/
11281 secondminval = vals[v];
11282
11283 if( maxval < vals[v] || maxval == -SCIP_INVALID ) /*lint !e777*/
11284 maxval = vals[v];
11285 }
11286 else
11287 break;
11288 }
11289
11290 /* check if all variables are binary, we can choose one, and need to choose at most one */
11291 if( v == -1 && SCIPisGE(scip, minval, lhs) && SCIPisLE(scip, maxval, rhs)
11292 && SCIPisGT(scip, minval + secondminval, rhs) )
11293 {
11294 /* change all coefficients to 1.0 */
11295 for( v = nvars - 1; v >= 0; --v )
11296 {
11297 SCIP_CALL( chgCoefPos(scip, cons, v, 1.0) );
11298 }
11299 (*nchgcoefs) += nvars;
11300
11301 /* replace old right and left hand side with 1.0 */
11302 SCIP_CALL( chgRhs(scip, cons, 1.0) );
11303 SCIP_CALL( chgLhs(scip, cons, 1.0) );
11304 (*nchgsides) += 2;
11305 }
11306
11307 return SCIP_OKAY;
11308}
11309
11310/** tries to simplify coefficients and delete variables in constraints of the form lhs <= a^Tx <= rhs
11311 *
11312 * for both-sided constraints only @see rangedRowSimplify() will be called
11313 *
11314 * for one-sided constraints there are several different coefficient reduction steps which will be applied
11315 *
11316 * 1. We try to determine parts of the constraint which will not change anything on (in-)feasibility of the constraint
11317 *
11318 * e.g. 5x1 + 5x2 + 3z1 <= 8 => 3z1 is redundant if all x are binary and -2 < 3z1 <= 3
11319 *
11320 * 2. We try to remove redundant fractional parts in a constraint
11321 *
11322 * e.g. 5.2x1 + 5.1x2 + 3x3 <= 8.3 => will be changed to 5x1 + 5x2 + 3x3 <= 8 if all x are binary
11323 *
11324 * 3. We are using the greatest common divisor for further reductions
11325 *
11326 * e.g. 10x1 + 5y2 + 5x3 + 3x4 <= 15 => will be changed to 2x1 + y2 + x3 + x4 <= 3 if all xi are binary and y2 is
11327 * integral
11328 */
11329static
11331 SCIP* scip, /**< SCIP data structure */
11332 SCIP_CONS* cons, /**< linear constraint */
11333 int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11334 int* nchgsides, /**< pointer to store the amount of changed sides */
11335 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
11336 )
11337{
11338 SCIP_CONSDATA* consdata;
11339 SCIP_VAR** vars;
11340 SCIP_Real* vals;
11341 int* perm;
11342 SCIP_Real minactsub;
11343 SCIP_Real maxactsub;
11344 SCIP_Real siderest;
11345 SCIP_Real feastol;
11346 SCIP_Real newcoef;
11347 SCIP_Real absval;
11348 SCIP_Real minact;
11349 SCIP_Real maxact;
11350 SCIP_Real side;
11351 SCIP_Real lhs;
11352 SCIP_Real rhs;
11353 SCIP_Real lb;
11354 SCIP_Real ub;
11355 SCIP_Longint restcoef;
11356 SCIP_Longint oldgcd;
11357 SCIP_Longint rest;
11358 SCIP_Longint gcd;
11359 SCIP_Bool isminsettoinfinity;
11360 SCIP_Bool ismaxsettoinfinity;
11361 SCIP_Bool ismintight;
11362 SCIP_Bool ismaxtight;
11363 SCIP_Bool allcoefintegral;
11364 SCIP_Bool onlybin;
11365 SCIP_Bool hasrhs;
11366 SCIP_Bool haslhs;
11367 int oldnchgcoefs; /* cppcheck-suppress unassignedVariable */
11368 int oldnchgsides; /* cppcheck-suppress unassignedVariable */
11369 int foundbin;
11370 int candpos;
11371 int candpos2;
11372 int offsetv;
11373 int nvars;
11374 int v;
11375 int w;
11376
11377 assert(scip != NULL);
11378 assert(cons != NULL);
11379 assert(nchgcoefs != NULL);
11380 assert(nchgsides != NULL);
11381
11382 *infeasible = FALSE;
11383
11384 /* we must not change a modifiable constraint in any way */
11385 if( SCIPconsIsModifiable(cons) )
11386 return SCIP_OKAY;
11387
11388 if( SCIPconsIsDeleted(cons) )
11389 return SCIP_OKAY;
11390
11391 consdata = SCIPconsGetData(cons);
11392 assert(consdata != NULL);
11393
11394 nvars = consdata->nvars;
11395
11396 /* do not check empty or bound-constraints */
11397 if( nvars <= 2 )
11398 return SCIP_OKAY;
11399
11400 /* update maximal activity delta if necessary */
11401 if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
11403
11404 assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
11405 assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
11406 checkMaxActivityDelta(scip, consdata);
11407
11408 /* @todo the following might be too hard, check which steps can be applied and what code must be corrected
11409 * accordingly
11410 */
11411 /* can only work with valid non-infinity activities per variable */
11412 if( SCIPisInfinity(scip, consdata->maxactdelta) )
11413 return SCIP_OKAY;
11414
11415 /* @todo: change the following: due to vartype changes, the status of the normalization can be wrong, need an event
11416 * but the eventsystem seems to be full
11417 */
11418 consdata->normalized = FALSE;
11419
11420 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11421 assert(nvars == consdata->nvars);
11422
11423 if( *infeasible )
11424 return SCIP_OKAY;
11425
11426 if( !consdata->normalized )
11427 return SCIP_OKAY;
11428
11429 lhs = consdata->lhs;
11430 rhs = consdata->rhs;
11431 assert(!SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs));
11432 assert(!SCIPisNegative(scip, rhs));
11433
11434 if( !SCIPisInfinity(scip, -lhs) )
11435 haslhs = TRUE;
11436 else
11437 haslhs = FALSE;
11438
11439 if( !SCIPisInfinity(scip, rhs) )
11440 hasrhs = TRUE;
11441 else
11442 hasrhs = FALSE;
11443
11444 /* @todo extend both-sided simplification */
11445 if( haslhs && hasrhs )
11446 {
11447 SCIP_CALL( rangedRowSimplify(scip, cons, nchgcoefs, nchgsides ) );
11448
11449 return SCIP_OKAY;
11450 }
11451 assert(haslhs != hasrhs);
11452
11453 /* if we have a normalized inequality (not ranged) the one side should be positive, @see normalizeCons() */
11454 assert(!hasrhs || !SCIPisNegative(scip, rhs));
11455 assert(!haslhs || !SCIPisNegative(scip, lhs));
11456
11457 /* get temporary memory to store the sorted permutation */
11459
11460 /* call sorting method, order continuous variables to the end and all other variables after non-increasing absolute
11461 * value of their coefficients
11462 */
11463 SCIPsort(perm, consdataCompSim, (void*)consdata, nvars);
11464
11465 /* perform sorting after permutation array */
11466 permSortConsdata(consdata, perm, nvars);
11467 consdata->indexsorted = FALSE;
11468 consdata->coefsorted = FALSE;
11469
11470 vars = consdata->vars;
11471 vals = consdata->vals;
11472 assert(vars != NULL);
11473 assert(vals != NULL);
11474 assert(!consdata->validmaxabsval || SCIPisFeasEQ(scip, consdata->maxabsval, REALABS(vals[0])) || !SCIPvarIsIntegral(vars[nvars - 1]));
11475
11476 /* free temporary memory */
11477 SCIPfreeBufferArray(scip, &perm);
11478
11479 /* only check constraints with at least two non continuous variables */
11480 if( !SCIPvarIsIntegral(vars[1]) )
11481 return SCIP_OKAY;
11482
11483 /* do not process constraints when all coefficients are 1.0 */
11484 if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) && ((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs))) )
11485 return SCIP_OKAY;
11486
11487 feastol = SCIPfeastol(scip);
11488
11489 SCIPdebugMsg(scip, "starting simplification of coefficients\n");
11491
11492 /* get global activities */
11493 consdataGetGlbActivityBounds(scip, consdata, FALSE, &minact, &maxact,
11494 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
11495
11496 /* cannot work with infinite activities */
11497 if( isminsettoinfinity || ismaxsettoinfinity )
11498 return SCIP_OKAY;
11499
11500 assert(ismintight);
11501 assert(ismaxtight);
11502 assert(maxact > minact);
11503 assert(!SCIPisInfinity(scip, -minact));
11504 assert(!SCIPisInfinity(scip, maxact));
11505
11506 v = 0;
11507 offsetv = -1;
11508 side = haslhs ? lhs : rhs;
11509 minactsub = minact;
11510 maxactsub = maxact;
11511
11512 /* we now determine coefficients as large as the side of the constraint to retrieve a better reduction where we
11513 * do not need to look at the large coefficients
11514 *
11515 * e.g. all x are binary, z are positive integer
11516 * c1: +5x1 + 5x2 + 3x3 + 3x4 + x5 >= 5 (x5 is redundant and does not change (in-)feasibility of this constraint)
11517 * c2: +4x1 + 4x2 + 3x3 + 3x4 + x5 >= 4 (gcd (without the coefficient of x5) after the large coefficients is 3
11518 * c3: +30x1 + 29x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 30 (gcd (without the coefficient of x2) after the large coefficients is 7
11519 *
11520 * can be changed to
11521 *
11522 * c1: +6x1 + 6x2 + 3x3 + 3x4 >= 6 (will be changed to c1: +2x1 + 2x2 + x3 + x4 >= 2)
11523 * c2: +6x1 + 6x2 + 3x3 + 3x4 + 3x5 >= 6 (will be changed to c2: +2x1 + 2x2 + x3 + x4 + x5 >= 2)
11524 * c3: +28x1 + 28x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 28 (will be changed to c3: +4x1 + 4x2 + 2x3 + 2z1 + x5 + x6 <= 4)
11525 */
11526
11527 /* if the minimal activity is negative and we found more than one variable with a coefficient bigger than the left
11528 * hand side, we cannot apply the extra reduction step and need to reset v
11529 *
11530 * 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
11531 * coefficients due to the gcd on the "small" coefficients we would get 8x1 + 8x2 - 4x3 - 4x4 >= 8 were xi = 1
11532 * for all i is a solution
11533 *
11534 * also redundancy of variables would not be correctly determined in such a case
11535 */
11536 if( nvars > 2 && SCIPisEQ(scip, vals[0], side) && !SCIPisNegative(scip, minactsub) )
11537 {
11538 v = 1;
11539
11540 while( v < nvars && SCIPisEQ(scip, side, vals[v]) )
11541 {
11542 /* if we have integer variable with "side"-coefficients but also with a lower bound greater than 0 we stop this
11543 * extra step, which might have worked
11544 */
11545 if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
11546 {
11547 v = 0;
11548 break;
11549 }
11550
11551 ++v;
11552 }
11553
11554 /* easy and quick fix: if all coefficients were equal to the side, we cannot apply further simplifications */
11555 /* todo find numerically stable normalization conditions to scale this cons to have coefficients almost equal to 1 */
11556 if( v == nvars )
11557 return SCIP_OKAY;
11558
11559 /* cannot work with continuous variables which have a big coefficient */
11560 if( v > 0 && !SCIPvarIsIntegral(vars[v - 1]) )
11561 return SCIP_OKAY;
11562
11563 /* big negative coefficient, do not try to use the extra coefficient reduction step */
11564 if( SCIPisEQ(scip, side, -vals[v]) )
11565 v = 0;
11566
11567 /* all but one variable are processed or the next variable is continuous we cannot perform the extra coefficient
11568 * reduction
11569 */
11570 if( v == nvars - 1 || !SCIPvarIsIntegral(vars[v]) )
11571 v = 0;
11572
11573 if( v > 0 )
11574 {
11575 assert(v < nvars);
11576
11577 offsetv = v - 1;
11578
11579 for( w = 0; w < v; ++w )
11580 {
11581 lb = SCIPvarGetLbGlobal(vars[w]);
11582 ub = SCIPvarGetUbGlobal(vars[w]);
11583
11584 assert(vals[w] > 0);
11585
11586 /* update residual activities */
11587 maxactsub -= ub * vals[w];
11588 minactsub -= lb * vals[w];
11589 assert(maxactsub > minactsub);
11590 }
11591 }
11592 }
11593
11594 /* find and remove redundant variables which do not interact with the (in-)feasibility of this constraint
11595 *
11596 * e.g. let all x are binary and y1 is continuous with bounds [-3,1] then we can reduce
11597 *
11598 * 15x1 + 15x2 + 7x3 + 3x4 + y1 <= 26
11599 * to
11600 * 15x1 + 15x2 <= 26 <=> x1 + x2 <= 1
11601 */
11602 if( nvars > 2 && SCIPisIntegral(scip, vals[v]) )
11603 {
11604 SCIP_Bool redundant = FALSE;
11605 SCIP_Bool numericsok;
11606 SCIP_Bool rredundant;
11607 SCIP_Bool lredundant;
11608
11609 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11610 assert(gcd >= 1);
11611
11612 if( v == 0 )
11613 {
11614 lb = SCIPvarGetLbGlobal(vars[0]);
11615 ub = SCIPvarGetUbGlobal(vars[0]);
11616
11617 /* update residual activities */
11618 if( vals[0] > 0 )
11619 {
11620 maxactsub -= ub * vals[0];
11621 minactsub -= lb * vals[0];
11622 }
11623 else
11624 {
11625 maxactsub -= lb * vals[0];
11626 minactsub -= ub * vals[0];
11627 }
11628 assert(maxactsub > minactsub);
11629 ++v;
11630 }
11631
11632 siderest = -SCIP_INVALID;
11633 allcoefintegral = TRUE;
11634
11635 /* check if some variables always fit into the given constraint */
11636 for( ; v < nvars - 1; ++v )
11637 {
11638 if( !SCIPvarIsIntegral(vars[v]) )
11639 break;
11640
11641 if( !SCIPisIntegral(scip, vals[v]) )
11642 {
11643 allcoefintegral = FALSE;
11644 break;
11645 }
11646
11647 /* calculate greatest common divisor for all general and binary variables */
11648 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11649
11650 if( gcd == 1 )
11651 break;
11652
11653 lb = SCIPvarGetLbGlobal(vars[v]);
11654 ub = SCIPvarGetUbGlobal(vars[v]);
11655
11656 assert(!SCIPisInfinity(scip, -lb));
11657 assert(!SCIPisInfinity(scip, ub));
11658
11659 /* update residual activities */
11660 if( vals[v] > 0 )
11661 {
11662 maxactsub -= ub * vals[v];
11663 minactsub -= lb * vals[v];
11664 }
11665 else
11666 {
11667 maxactsub -= lb * vals[v];
11668 minactsub -= ub * vals[v];
11669 }
11670 assert(SCIPisGE(scip, maxactsub, minactsub));
11671
11672 if( hasrhs )
11673 {
11674 /* determine the remainder of the right hand side and the gcd */
11675 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11676 }
11677 else
11678 {
11679 /* determine the remainder of the left hand side and the gcd */
11680 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11681 if( SCIPisZero(scip, siderest) )
11682 siderest = gcd;
11683 }
11684
11685 rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
11686 lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11687
11688 /* early termination if the activities deceed the gcd */
11689 if( offsetv == -1 && (rredundant || lredundant) )
11690 {
11691 redundant = TRUE;
11692 break;
11693 }
11694 }
11695 assert(v < nvars || (offsetv >= 0 && gcd > 1));
11696
11697 if( !redundant )
11698 {
11699 if( hasrhs )
11700 {
11701 /* determine the remainder of the right hand side and the gcd */
11702 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11703 }
11704 else
11705 {
11706 /* determine the remainder of the left hand side and the gcd */
11707 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11708 if( SCIPisZero(scip, siderest) )
11709 siderest = gcd;
11710 }
11711 }
11712 else
11713 ++v;
11714
11715 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",
11716 v, nvars, minactsub, maxactsub, redundant, hasrhs, siderest, gcd, offsetv);
11717
11718 /* to avoid inconsistencies due to numerics, check that the full and partial activities have
11719 * reasonable absolute values */
11720 numericsok = REALABS(maxact) < MAXACTVAL && REALABS(maxactsub) < MAXACTVAL && REALABS(minact) < MAXACTVAL &&
11721 REALABS(minactsub) < MAXACTVAL;
11722
11723 rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
11724 lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11725
11726 /* check if we can remove redundant variables */
11727 if( v < nvars && numericsok && (redundant || (offsetv == -1 && (rredundant || lredundant))) )
11728 {
11729 SCIP_Real oldcoef;
11730
11731 /* double check the redundancy */
11732#ifndef NDEBUG
11733 SCIP_Real tmpminactsub = 0.0;
11734 SCIP_Real tmpmaxactsub = 0.0;
11735
11736 /* recompute residual activities */
11737 for( w = v; w < nvars; ++w )
11738 {
11739 lb = SCIPvarGetLbGlobal(vars[w]);
11740 ub = SCIPvarGetUbGlobal(vars[w]);
11741
11742 assert(!SCIPisInfinity(scip, -lb));
11743 assert(!SCIPisInfinity(scip, ub));
11744
11745 /* update residual activities */
11746 if( vals[w] > 0 )
11747 {
11748 tmpmaxactsub += ub * vals[w];
11749 tmpminactsub += lb * vals[w];
11750 }
11751 else
11752 {
11753 tmpmaxactsub += lb * vals[w];
11754 tmpminactsub += ub * vals[w];
11755 }
11756 assert(tmpmaxactsub >= tmpminactsub);
11757 }
11758
11759 if( hasrhs )
11760 {
11761 assert(offsetv == -1);
11762
11763 /* determine the remainder of the right hand side and the gcd */
11764 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11765 }
11766 else
11767 {
11768 /* determine the remainder of the left hand side and the gcd */
11769 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11770 if( SCIPisZero(scip, siderest) )
11771 siderest = gcd;
11772 }
11773
11774 /* is the redundancy really fulfilled */
11775 assert((hasrhs && SCIPisFeasLE(scip, tmpmaxactsub, siderest) && tmpminactsub > siderest - gcd) ||
11776 (haslhs && tmpmaxactsub < siderest && SCIPisFeasGE(scip, tmpminactsub, siderest - gcd)));
11777#endif
11778
11779 SCIPdebugMsg(scip, "removing %d last variables from constraint <%s>, because they never change anything on the feasibility of this constraint\n",
11780 nvars - v, SCIPconsGetName(cons));
11781
11782 /* remove redundant variables */
11783 for( w = nvars - 1; w >= v; --w )
11784 {
11785 SCIP_CALL( delCoefPos(scip, cons, w) );
11786 }
11787 (*nchgcoefs) += (nvars - v);
11788
11789 assert(w >= 0);
11790
11791 oldcoef = vals[w];
11792
11793 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11794 assert(vars == consdata->vars);
11795 assert(vals == consdata->vals);
11797
11798 if( *infeasible )
11799 return SCIP_OKAY;
11800
11801 /* compute new greatest common divisor due to normalization */
11802 gcd = (SCIP_Longint)(gcd / (oldcoef/vals[w]) + feastol);
11803 assert(gcd >= 1);
11804
11805 /* update side */
11806 if( hasrhs )
11807 {
11808 /* replace old with new right hand side */
11809 SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
11810 rhs = consdata->rhs;
11811 }
11812 else
11813 {
11814 if( SCIPisFeasGT(scip, oldcoef/vals[w], 1.0) )
11815 {
11816 SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
11817 lhs = consdata->lhs;
11818 }
11819 else
11820 assert(offsetv == -1 || SCIPisEQ(scip, vals[offsetv], consdata->lhs));
11821 }
11822 ++(*nchgsides);
11823
11824 assert(!hasrhs || !SCIPisNegative(scip, rhs));
11825 assert(!haslhs || !SCIPisNegative(scip, lhs));
11826
11827 /* get new constraint data */
11828 nvars = consdata->nvars;
11829 assert(nvars > 0);
11830
11831 allcoefintegral = TRUE;
11832
11833#ifndef NDEBUG
11834 /* check integrality */
11835 for( w = offsetv + 1; w < nvars; ++w )
11836 {
11837 assert(SCIPisIntegral(scip, vals[w]));
11838 }
11839#endif
11841 }
11842
11843 /* try to find a better gcd, when having large coefficients */
11844 if( offsetv >= 0 && gcd == 1 )
11845 {
11846 /* calculate greatest common divisor for all general variables */
11847 gcd = (SCIP_Longint)(REALABS(vals[nvars - 1]) + feastol);
11848
11849 if( gcd > 1 )
11850 {
11851 gcd = -1;
11852 candpos = -1;
11853
11854 for( v = nvars - 1; v > offsetv; --v )
11855 {
11856 assert(!SCIPisZero(scip, vals[v]));
11857 if( !SCIPvarIsIntegral(vars[v]) )
11858 break;
11859
11860 if( !SCIPisIntegral(scip, vals[v]) )
11861 {
11862 allcoefintegral = FALSE;
11863 break;
11864 }
11865
11866 oldgcd = gcd;
11867
11868 if( gcd == -1 )
11869 {
11870 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11871 assert(gcd >= 1);
11872 }
11873 else
11874 {
11875 /* calculate greatest common divisor for all general and binary variables */
11876 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11877 }
11878
11879 /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
11880 * can stop searching
11881 */
11882 if( gcd == 1 )
11883 {
11884 if( !SCIPvarIsBinary(vars[v]) )
11885 break;
11886
11887 /* found candidate */
11888 if( candpos == -1 )
11889 {
11890 gcd = oldgcd;
11891 candpos = v;
11892 }
11893 /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
11894 else
11895 break;
11896 }
11897 }
11898 assert(v > offsetv || candpos > offsetv);
11899 }
11900 else
11901 candpos = -1;
11902 }
11903 else
11904 candpos = nvars - 1;
11905
11906 /* check last coefficient for integrality */
11907 if( gcd > 1 && allcoefintegral && !redundant )
11908 {
11909 if( !SCIPisIntegral(scip, vals[nvars - 1]) )
11910 allcoefintegral = FALSE;
11911 }
11912
11913 /* check for further necessary coefficient adjustments */
11914 if( offsetv >= 0 && gcd > 1 && allcoefintegral )
11915 {
11916 assert(offsetv + 1 < nvars);
11917 assert(0 <= candpos && candpos < nvars);
11918
11919 if( SCIPvarIsIntegral(vars[candpos]) )
11920 {
11921 SCIP_Bool notchangable = FALSE;
11922
11923#ifndef NDEBUG
11924 /* check integrality */
11925 for( w = offsetv + 1; w < nvars; ++w )
11926 {
11927 assert(SCIPisIntegral(scip, vals[w]));
11928 }
11929#endif
11930
11931 if( vals[candpos] > 0 && SCIPvarIsBinary(vars[candpos]) &&
11932 SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) < gcd )
11933 {
11934 /* determine the remainder of the side and the gcd */
11935 if( hasrhs )
11936 rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
11937 else
11938 rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
11939 assert(rest >= 0);
11940 assert(rest < gcd);
11941
11942 /* determine the remainder of the coefficient candidate and the gcd */
11943 restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
11944 assert(restcoef >= 1);
11945 assert(restcoef < gcd);
11946
11947 if( hasrhs )
11948 {
11949 /* calculate new coefficient */
11950 if( restcoef > rest )
11951 newcoef = vals[candpos] - restcoef + gcd;
11952 else
11953 newcoef = vals[candpos] - restcoef;
11954 }
11955 else
11956 {
11957 /* calculate new coefficient */
11958 if( rest == 0 || restcoef < rest )
11959 newcoef = vals[candpos] - restcoef;
11960 else
11961 newcoef = vals[candpos] - restcoef + gcd;
11962 }
11963
11964 /* done */
11965
11966 /* new coeffcient must not be zero if we would loose the implication that a variable needs to be 0 if
11967 * another with the big coefficient was set to 1
11968 */
11969 if( hasrhs && SCIPisZero(scip, newcoef) )
11970 {
11971 notchangable = TRUE;
11972 }
11973 else if( SCIPisZero(scip, newcoef) )
11974 {
11975 /* delete old redundant coefficient */
11976 SCIP_CALL( delCoefPos(scip, cons, candpos) );
11977 ++(*nchgcoefs);
11978 }
11979 else
11980 {
11981 /* replace old with new coefficient */
11982 SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
11983 ++(*nchgcoefs);
11984 }
11985 }
11986 else if( vals[candpos] < 0 || !SCIPvarIsBinary(vars[candpos]) )
11987 {
11988 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol));
11989 }
11990
11991 /* correct side and big coefficients */
11992 if( (!notchangable && hasrhs && ((!SCIPisFeasIntegral(scip, rhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(rhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd))) ||
11993 ( haslhs && (!SCIPisFeasIntegral(scip, lhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(lhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd)) )
11994 {
11995 if( haslhs )
11996 {
11997 newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasCeil(scip, lhs/gcd) * gcd + feastol));
11998
11999 SCIP_CALL( chgLhs(scip, cons, newcoef) );
12000 ++(*nchgsides);
12001 }
12002 else
12003 {
12004 assert(hasrhs);
12005 newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasFloor(scip, rhs/gcd) * gcd + feastol));
12006
12007 SCIP_CALL( chgRhs(scip, cons, newcoef) );
12008 ++(*nchgsides);
12009 }
12010
12011 /* correct coefficients up front */
12012 for( w = offsetv; w >= 0; --w )
12013 {
12014 assert(vals[w] > 0);
12015
12016 SCIP_CALL( chgCoefPos(scip, cons, w, newcoef) );
12017 }
12018 (*nchgcoefs) += (offsetv + 1);
12019 }
12020
12021 if( !notchangable )
12022 {
12023 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12024 assert(vars == consdata->vars);
12025 assert(vals == consdata->vals);
12026
12027 if( *infeasible )
12028 return SCIP_OKAY;
12029
12030 /* get new constraint data */
12031 nvars = consdata->nvars;
12032 assert(nvars >= 2);
12033
12035
12036 lhs = consdata->lhs;
12037 rhs = consdata->rhs;
12038 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12039 assert(!haslhs || !SCIPisNegative(scip, lhs));
12040 }
12041 }
12042 }
12043 }
12044
12045 /* @todo we still can remove continuous variables if they are redundant due to the non-integrality argument */
12046 /* no continuous variables are left over */
12047 if( !SCIPvarIsIntegral(vars[nvars - 1]) )
12048 return SCIP_OKAY;
12049
12050 onlybin = TRUE;
12051 allcoefintegral = TRUE;
12052 /* check if all variables are of binary type */
12053 for( v = nvars - 1; v >= 0; --v )
12054 {
12055 if( !SCIPvarIsBinary(vars[v]) )
12056 onlybin = FALSE;
12057 if( !SCIPisIntegral(scip, vals[v]) )
12058 allcoefintegral = FALSE;
12059 }
12060
12061 /* check if the non-integrality part of all integral variables is smaller than the non-inegrality part of the right
12062 * hand side or bigger than the left hand side respectively, so we can make all of them integral
12063 *
12064 * @todo there are some steps missing ....
12065 */
12066 if( (hasrhs && !SCIPisFeasIntegral(scip, rhs)) || (haslhs && !SCIPisFeasIntegral(scip, lhs)) )
12067 {
12068 SCIP_Real val;
12069 SCIP_Real newval;
12070 SCIP_Real frac = 0.0;
12071 SCIP_Bool found = FALSE;
12072
12073 if( hasrhs )
12074 {
12075 if( allcoefintegral )
12076 {
12077 /* replace old with new right hand side */
12078 SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12079 ++(*nchgsides);
12080 }
12081 else
12082 {
12083 siderest = rhs - SCIPfloor(scip, rhs);
12084
12085 /* try to round down all non-integral coefficients */
12086 for( v = nvars - 1; v >= 0; --v )
12087 {
12088 val = vals[v];
12089
12090 /* add up all possible fractional parts */
12091 if( !SCIPisIntegral(scip, val) )
12092 {
12093 lb = SCIPvarGetLbGlobal(vars[v]);
12094 ub = SCIPvarGetUbGlobal(vars[v]);
12095
12096 /* at least one bound need to be at zero */
12097 if( !onlybin && !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12098 return SCIP_OKAY;
12099
12100 /* swap bounds for 'standard' form */
12101 if( !SCIPisFeasZero(scip, lb) )
12102 {
12103 ub = -lb;
12104 val *= -1;
12105 }
12106
12107 found = TRUE;
12108
12109 frac += (val - SCIPfloor(scip, val)) * ub;
12110
12111 /* if we exceed the fractional part of the right hand side, we cannot tighten the coefficients
12112 *
12113 * e.g. 1.1x1 + 1.1x2 + 1.4x3 + 1.02x4 <= 2.4, here we cannot floor all fractionals because
12114 * x3, x4 set to 1 would be infeasible but feasible after flooring
12115 */
12116 if( SCIPisGT(scip, frac, siderest) )
12117 return SCIP_OKAY;
12118 }
12119 }
12120 assert(v == -1);
12121
12122 SCIPdebugMsg(scip, "rounding all non-integral coefficients and the right hand side down\n");
12123
12124 /* round rhs and coefficients to integral values */
12125 if( found )
12126 {
12127 for( v = nvars - 1; v >= 0; --v )
12128 {
12129 val = vals[v];
12130
12131 /* add the whole fractional part */
12132 if( !SCIPisIntegral(scip, val) )
12133 {
12134 lb = SCIPvarGetLbGlobal(vars[v]);
12135
12136 if( SCIPisFeasZero(scip, lb) )
12137 newval = SCIPfloor(scip, val);
12138 else
12139 newval = SCIPceil(scip, val);
12140
12141 if( SCIPisZero(scip, newval) )
12142 {
12143 /* delete old redundant coefficient */
12144 SCIP_CALL( delCoefPos(scip, cons, v) );
12145 ++(*nchgcoefs);
12146 }
12147 else
12148 {
12149 /* replace old with new coefficient */
12150 SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12151 ++(*nchgcoefs);
12152 }
12153 }
12154 }
12155 }
12156
12157 /* replace old with new right hand side */
12158 SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12159 ++(*nchgsides);
12160 }
12161 }
12162 else
12163 {
12164 if( allcoefintegral )
12165 {
12166 /* replace old with new left hand side */
12167 SCIP_CALL( chgLhs(scip, cons, SCIPceil(scip, lhs)) );
12168 ++(*nchgsides);
12169 }
12170 else
12171 {
12172 /* cannot floor left hand side to zero */
12173 if( SCIPisLT(scip, lhs, 1.0) )
12174 return SCIP_OKAY;
12175
12176 siderest = lhs - SCIPfloor(scip, lhs);
12177
12178 /* try to round down all non-integral coefficients */
12179 for( v = nvars - 1; v >= 0; --v )
12180 {
12181 val = vals[v];
12182
12183 /* add up all possible fractional parts */
12184 if( !SCIPisIntegral(scip, val) )
12185 {
12186 lb = SCIPvarGetLbGlobal(vars[v]);
12187 ub = SCIPvarGetUbGlobal(vars[v]);
12188
12189 /* at least one bound need to be at zero */
12190 if( !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12191 return SCIP_OKAY;
12192
12193 /* swap bounds for 'standard' form */
12194 if( !SCIPisFeasZero(scip, lb) )
12195 {
12196 ub = -lb;
12197 val *= -1;
12198 }
12199
12200 /* cannot floor to zero */
12201 if( SCIPisLT(scip, val, 1.0) )
12202 return SCIP_OKAY;
12203
12204 /* the fractional part on each variable need to exceed the fractional part on the left hand side */
12205 if( SCIPisLT(scip, val - SCIPfloor(scip, val), siderest) )
12206 return SCIP_OKAY;
12207
12208 found = TRUE;
12209
12210 frac += (val - SCIPfloor(scip, val)) * ub;
12211
12212 /* if we exceed the fractional part of the left hand side plus one by summing up all maximal
12213 * fractional parts of the variables, we cannot tighten the coefficients
12214 *
12215 * e.g. 4.3x1 + 1.3x2 + 1.3x3 + 1.6x4 >= 4.2, here we cannot floor all fractionals because
12216 * x2-x4 set to 1 would be feasible but not after flooring
12217 */
12218 if( SCIPisGE(scip, frac, 1 + siderest) )
12219 return SCIP_OKAY;
12220 }
12221 /* all coefficients need to be integral, otherwise we might do an invalid reduction */
12222 else
12223 return SCIP_OKAY;
12224 }
12225 assert(v == -1);
12226
12227 SCIPdebugMsg(scip, "rounding all non-integral coefficients and the left hand side down\n");
12228
12229 /* round lhs and coefficients to integral values */
12230 if( found )
12231 {
12232 for( v = nvars - 1; v >= 0; --v )
12233 {
12234 val = vals[v];
12235
12236 /* add the whole fractional part */
12237 if( !SCIPisIntegral(scip, val) )
12238 {
12239 lb = SCIPvarGetLbGlobal(vars[v]);
12240
12241 if( SCIPisFeasZero(scip, lb) )
12242 newval = SCIPfloor(scip, val);
12243 else
12244 newval = SCIPceil(scip, val);
12245
12246 if( SCIPisZero(scip, newval) )
12247 {
12248 /* delete old redundant coefficient */
12249 SCIP_CALL( delCoefPos(scip, cons, v) );
12250 ++(*nchgcoefs);
12251 }
12252 else
12253 {
12254 /* replace old with new coefficient */
12255 SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12256 ++(*nchgcoefs);
12257 }
12258 }
12259 }
12260 }
12261
12262 /* replace old with new left hand side */
12263 SCIP_CALL( chgLhs(scip, cons, SCIPfloor(scip, lhs)) );
12264 ++(*nchgsides);
12265 }
12266 }
12267
12268 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12269 assert(vars == consdata->vars);
12270 assert(vals == consdata->vals);
12271
12272 if( *infeasible )
12273 return SCIP_OKAY;
12274
12275 rhs = consdata->rhs;
12276 lhs = consdata->lhs;
12277
12278 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12279 assert(!haslhs || !SCIPisNegative(scip, lhs));
12280
12282
12283 nvars = consdata->nvars;
12284 if( nvars < 2 )
12285 return SCIP_OKAY;
12286
12287 allcoefintegral = TRUE;
12288#ifndef NDEBUG
12289 /* debug check if all coefficients are really integral */
12290 for( v = nvars - 1; v >= 0; --v )
12291 assert(SCIPisIntegral(scip, vals[v]));
12292#endif
12293 }
12294
12295 /* @todo following can also work on non integral coefficients, need more investigation */
12296 /* only check constraints with integral coefficients on all integral variables */
12297 if( !allcoefintegral )
12298 return SCIP_OKAY;
12299
12300 /* we want to avoid numerical troubles, therefore we do not change non-integral sides */
12301 if( (hasrhs && !SCIPisIntegral(scip, rhs)) || (haslhs && !SCIPisIntegral(scip, lhs)) )
12302 return SCIP_OKAY;
12303
12304 /* maximal absolute value of coefficients in constraint is one, so we cannot tighten it further */
12305 if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) )
12306 return SCIP_OKAY;
12307
12308 /* stop if the last coeffcients is one in absolute value and the variable is not binary */
12309 if( !SCIPvarIsBinary(vars[nvars - 1]) && SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) )
12310 return SCIP_OKAY;
12311
12312 assert(nvars >= 2);
12313
12314 /* start gcd procedure for all variables */
12315 do
12316 {
12317 SCIPdebug( oldnchgcoefs = *nchgcoefs; )
12318 SCIPdebug( oldnchgsides = *nchgsides; )
12319
12320 /* stop if we have two coeffcients which are one in absolute value */
12321 if( SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) && SCIPisEQ(scip, REALABS(vals[nvars - 2]), 1.0) )
12322 return SCIP_OKAY;
12323
12324 gcd = -1;
12325
12326 /* calculate greatest common divisor over all integer variables; note that the onlybin flag needs to be recomputed
12327 * because coefficients of non-binary variables might have changed to zero */
12328 if( !onlybin )
12329 {
12330 foundbin = -1;
12331 onlybin = TRUE;
12332
12333 for( v = nvars - 1; v >= 0; --v )
12334 {
12335 assert(!SCIPisZero(scip, vals[v]));
12337
12338 if( SCIPvarIsBinary(vars[v]) )
12339 {
12340 if( foundbin == -1 )
12341 foundbin = v;
12342 continue;
12343 }
12344 else
12345 onlybin = FALSE;
12346
12347 absval = REALABS(vals[v]);
12348 /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12349 * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12350 */
12351 assert(SCIPisFeasIntegral(scip, absval));
12352
12353 if( gcd == -1 )
12354 {
12355 gcd = (SCIP_Longint)(absval + feastol);
12356 assert(gcd >= 1);
12357 }
12358 else
12359 {
12360 /* calculate greatest common divisor for all general variables */
12361 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(absval + feastol));
12362 }
12363 if( gcd == 1 )
12364 break;
12365 }
12366 }
12367 else
12368 foundbin = nvars - 1;
12369
12370 /* we need at least one binary variable and a gcd greater than 1 to try to perform further coefficient changes */
12371 if( gcd == 1 || foundbin == -1)
12372 return SCIP_OKAY;
12373
12374 assert((onlybin && gcd == -1) || (!onlybin && gcd > 1));
12375
12376 candpos = -1;
12377 candpos2 = -1;
12378
12379 /* calculate greatest common divisor over all integer and binary variables and determine the candidate where we might
12380 * change the coefficient
12381 */
12382 for( v = foundbin; v >= 0; --v )
12383 {
12384 if( onlybin || SCIPvarIsBinary(vars[v]) )
12385 {
12386 absval = REALABS(vals[v]);
12387 /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12388 * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12389 */
12390 assert(SCIPisFeasIntegral(scip, absval));
12391
12392 oldgcd = gcd;
12393
12394 if( gcd == -1 )
12395 {
12396 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12397 assert(gcd >= 1);
12398 }
12399 else
12400 {
12401 /* calculate greatest common divisor for all general and binary variables */
12402 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12403 }
12404
12405 /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12406 * can terminate
12407 */
12408 if( gcd == 1 )
12409 {
12410 /* found candidate */
12411 if( candpos == -1 )
12412 {
12413 gcd = oldgcd;
12414 candpos = v;
12415
12416 /* if we have only binary variables and both first coefficients have a gcd of 1, both are candidates for
12417 * the coefficient change
12418 */
12419 if( onlybin && v == foundbin - 1 )
12420 candpos2 = foundbin;
12421 }
12422 /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12423 else
12424 {
12425 if( onlybin && candpos == v + 1 && candpos2 == v + 2 )
12426 {
12427 assert(candpos2 == nvars - 1);
12428
12429 /* take new candidates */
12430 candpos = candpos2;
12431
12432 /* recalculate gcd from scratch */
12433 gcd = (SCIP_Longint)(REALABS(vals[v+1]) + feastol);
12434 assert(gcd >= 1);
12435
12436 /* calculate greatest common divisor for all general and binary variables */
12437 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12438 if( gcd == 1 )
12439 return SCIP_OKAY;
12440 }
12441 else
12442 /* cannot determine a possible coefficient for reduction */
12443 return SCIP_OKAY;
12444 }
12445 }
12446 }
12447 }
12448 assert(gcd >= 2);
12449
12450 /* we should have found one coefficient, that led to a gcd of 1, otherwise we could normalize the constraint
12451 * further
12452 */
12453 assert(candpos >= 0 && candpos < nvars);
12454
12455 /* all variables and all coefficients are integral, so the side should be too */
12456 assert((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs)));
12457
12458 /* check again, if we have a normalized inequality (not ranged) the one side should be positive,
12459 * @see normalizeCons()
12460 */
12461 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12462 assert(!haslhs || !SCIPisNegative(scip, lhs));
12463
12464 /* determine the remainder of the side and the gcd */
12465 if( hasrhs )
12466 rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12467 else
12468 rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12469 assert(rest >= 0);
12470 assert(rest < gcd);
12471
12472 /* determine the remainder of the coefficient candidate and the gcd */
12473 if( vals[candpos] < 0 )
12474 {
12475 restcoef = ((SCIP_Longint)(vals[candpos] - feastol)) % gcd;
12476 assert(restcoef <= -1);
12477 restcoef += gcd;
12478 }
12479 else
12480 restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12481 assert(restcoef >= 1);
12482 assert(restcoef < gcd);
12483
12484 if( hasrhs )
12485 {
12486 if( rest > 0 )
12487 {
12488 /* replace old with new right hand side */
12489 SCIP_CALL( chgRhs(scip, cons, rhs - rest) );
12490 ++(*nchgsides);
12491 }
12492
12493 /* calculate new coefficient */
12494 if( restcoef > rest )
12495 newcoef = vals[candpos] - restcoef + gcd;
12496 else
12497 newcoef = vals[candpos] - restcoef;
12498 }
12499 else
12500 {
12501 if( rest > 0 )
12502 {
12503 /* replace old with new left hand side */
12504 SCIP_CALL( chgLhs(scip, cons, lhs - rest + gcd) );
12505 ++(*nchgsides);
12506 }
12507
12508 /* calculate new coefficient */
12509 if( rest == 0 || restcoef < rest )
12510 newcoef = vals[candpos] - restcoef;
12511 else
12512 newcoef = vals[candpos] - restcoef + gcd;
12513 }
12514 assert(SCIPisZero(scip, newcoef) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(newcoef) + feastol)) == gcd);
12515
12516 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));
12517
12518 if( SCIPisZero(scip, newcoef) )
12519 {
12520 /* delete redundant coefficient */
12521 SCIP_CALL( delCoefPos(scip, cons, candpos) );
12522 }
12523 else
12524 {
12525 /* replace old with new coefficient */
12526 SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12527 }
12528 ++(*nchgcoefs);
12529
12530 /* now constraint can be normalized, might be directly done by dividing it by the gcd */
12531 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12532 assert(vars == consdata->vars);
12533 assert(vals == consdata->vals);
12534
12535 if( *infeasible )
12536 return SCIP_OKAY;
12537
12539
12540 rhs = consdata->rhs;
12541 lhs = consdata->lhs;
12542 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12543 assert(!haslhs || !SCIPisNegative(scip, lhs));
12544
12545 nvars = consdata->nvars;
12546
12547 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));
12548 }
12549 while( nvars >= 2 );
12550
12551 return SCIP_OKAY;
12552}
12553
12554
12555/** tries to aggregate an (in)equality and an equality in order to decrease the number of variables in the (in)equality:
12556 * cons0 := a * cons0 + b * cons1,
12557 * where a = val1[v] and b = -val0[v] for common variable v which removes most variable weight;
12558 * for numerical stability, we will only accept integral a and b;
12559 * the variable weight is a weighted sum over all included variables, where each binary variable weighs BINWEIGHT,
12560 * each integer or implied integral variable weighs INTWEIGHT and each continuous variable weighs CONTWEIGHT
12561 */
12562static
12564 SCIP* scip, /**< SCIP data structure */
12565 SCIP_CONS* cons0, /**< (in)equality to modify */
12566 SCIP_CONS* cons1, /**< equality to use for aggregation of cons0 */
12567 int* commonidx0, /**< array with indices of variables in cons0, that appear also in cons1 */
12568 int* commonidx1, /**< array with indices of variables in cons1, that appear also in cons0 */
12569 int* diffidx0minus1, /**< array with indices of variables in cons0, that don't appear in cons1 */
12570 int* diffidx1minus0, /**< array with indices of variables in cons1, that don't appear in cons0 */
12571 int nvarscommon, /**< number of variables, that appear in both constraints */
12572 int commonidxweight, /**< variable weight sum of common variables */
12573 int diffidx0minus1weight, /**< variable weight sum of variables in cons0, that don't appear in cons1 */
12574 int diffidx1minus0weight, /**< variable weight sum of variables in cons1, that don't appear in cons0 */
12575 SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
12576 int* nchgcoefs, /**< pointer to count the number of changed coefficients */
12577 SCIP_Bool* aggregated, /**< pointer to store whether an aggregation was made */
12578 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
12579 )
12580{
12581 SCIP_CONSDATA* consdata0;
12582 SCIP_CONSDATA* consdata1;
12583 SCIP_Real a;
12584 SCIP_Real b;
12585 SCIP_Real aggrcoef;
12586 SCIP_Real scalarsum;
12587 SCIP_Real bestscalarsum;
12588 SCIP_Bool betterscalarsum;
12589 SCIP_Bool commonvarlindependent; /* indicates whether coefficient vector of common variables in linearly dependent */
12590 int varweight;
12591 int nvars;
12592 int bestvarweight;
12593 int bestnvars;
12594 int bestv;
12595 int v;
12596 int i;
12597
12598 assert(scip != NULL);
12599 assert(cons0 != NULL);
12600 assert(cons1 != NULL);
12601 assert(commonidx0 != NULL);
12602 assert(commonidx1 != NULL);
12603 assert(diffidx0minus1 != NULL);
12604 assert(diffidx1minus0 != NULL);
12605 assert(nvarscommon >= 1);
12606 assert(commonidxweight >= nvarscommon);
12607 assert(nchgcoefs != NULL);
12608 assert(aggregated != NULL);
12609
12610 assert(SCIPconsIsActive(cons0));
12611 assert(SCIPconsIsActive(cons1));
12612
12613 *infeasible = FALSE;
12614
12615 SCIPdebugMsg(scip, "try aggregation of <%s> and <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
12616
12617 /* cons0 is an (in)equality */
12618 consdata0 = SCIPconsGetData(cons0);
12619 assert(consdata0 != NULL);
12620 assert(consdata0->nvars >= 1);
12621 assert(SCIPisLE(scip, consdata0->lhs, consdata0->rhs));
12622 assert(diffidx0minus1weight >= consdata0->nvars - nvarscommon);
12623
12624 /* cons1 is an equality */
12625 consdata1 = SCIPconsGetData(cons1);
12626 assert(consdata1 != NULL);
12627 assert(consdata1->nvars >= 1);
12628 assert(SCIPisEQ(scip, consdata1->lhs, consdata1->rhs));
12629 assert(diffidx1minus0weight >= consdata1->nvars - nvarscommon);
12630
12631 *aggregated = FALSE;
12632
12633 /* search for the best common variable such that
12634 * val1[var] * consdata0 - val0[var] * consdata1
12635 * has least weighted number of variables
12636 */
12637 bestvarweight = commonidxweight + diffidx0minus1weight;
12638 bestnvars = consdata0->nvars;
12639 bestv = -1;
12640 bestscalarsum = 0.0;
12641 commonvarlindependent = TRUE;
12642 for( v = 0; v < nvarscommon; ++v )
12643 {
12644 assert(consdata0->vars[commonidx0[v]] == consdata1->vars[commonidx1[v]]);
12645 a = consdata1->vals[commonidx1[v]];
12646 b = -consdata0->vals[commonidx0[v]];
12647
12648 /* only try aggregation, if coefficients are integral (numerical stability) */
12650 {
12651 /* count the number of variables in the potential new constraint a * consdata0 + b * consdata1 */
12652 varweight = diffidx0minus1weight + diffidx1minus0weight;
12653 nvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12654 scalarsum = REALABS(a) + REALABS(b);
12655 betterscalarsum = (scalarsum < bestscalarsum);
12656 for( i = 0; i < nvarscommon
12657 && (varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum)); ++i )
12658 {
12659 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12660 if( !SCIPisZero(scip, aggrcoef) )
12661 {
12662 varweight += getVarWeight(consdata0->vars[commonidx0[i]]);
12663 nvars++;
12664 }
12665 }
12666 if( varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum) )
12667 {
12668 bestv = v;
12669 bestvarweight = varweight;
12670 bestnvars = nvars;
12671 bestscalarsum = scalarsum;
12672 }
12673 }
12674
12675 /* update commonvarlindependent flag, if still TRUE:
12676 * 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
12677 */
12678 if( commonvarlindependent && v > 0 )
12679 commonvarlindependent = SCIPisEQ(scip,
12680 consdata1->vals[commonidx1[v]] * consdata0->vals[commonidx0[0]],
12681 consdata1->vals[commonidx1[0]] * consdata0->vals[commonidx0[v]]);
12682 }
12683
12684 /* if better aggregation was found, create new constraint and delete old one */
12685 if( (bestv != -1 || commonvarlindependent) && SCIPconsGetNUpgradeLocks(cons0) == 0 )
12686 {
12687 SCIP_CONS* newcons;
12688 SCIP_CONSDATA* newconsdata;
12689 SCIP_VAR** newvars;
12690 SCIP_Real* newvals;
12691 SCIP_Real newlhs;
12692 SCIP_Real newrhs;
12693 int newnvars;
12694
12695 if( bestv != -1 )
12696 {
12697 /* choose multipliers such that the multiplier for the (in)equality cons0 is positive */
12698 if( consdata1->vals[commonidx1[bestv]] > 0.0 )
12699 {
12700 a = consdata1->vals[commonidx1[bestv]];
12701 b = -consdata0->vals[commonidx0[bestv]];
12702 }
12703 else
12704 {
12705 a = -consdata1->vals[commonidx1[bestv]];
12706 b = consdata0->vals[commonidx0[bestv]];
12707 }
12711 assert(!SCIPisZero(scip, b));
12712 }
12713 else
12714 {
12715 assert(commonvarlindependent);
12716 if( consdata1->vals[commonidx1[0]] > 0.0 )
12717 {
12718 a = consdata1->vals[commonidx1[0]];
12719 b = -consdata0->vals[commonidx0[0]];
12720 }
12721 else
12722 {
12723 a = -consdata1->vals[commonidx1[0]];
12724 b = consdata0->vals[commonidx0[0]];
12725 }
12727 assert(!SCIPisZero(scip, b));
12728
12729 /* if a/b is integral, then we can easily choose integer multipliers */
12730 if( SCIPisIntegral(scip, a/b) )
12731 {
12732 if( a/b > 0 )
12733 {
12734 a /= b;
12735 b = 1.0;
12736 }
12737 else
12738 {
12739 a /= -b;
12740 b = -1.0;
12741 }
12742 }
12743
12744 /* setup best* variables that were not setup above because we are in the commonvarlindependent case */
12745 SCIPdebug( bestvarweight = diffidx0minus1weight + diffidx1minus0weight; )
12746 bestnvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12747 }
12748
12749 SCIPdebugMsg(scip, "aggregate linear constraints <%s> := %.15g*<%s> + %.15g*<%s> -> nvars: %d -> %d, weight: %d -> %d\n",
12750 SCIPconsGetName(cons0), a, SCIPconsGetName(cons0), b, SCIPconsGetName(cons1),
12751 consdata0->nvars, bestnvars, commonidxweight + diffidx0minus1weight, bestvarweight);
12752 SCIPdebugPrintCons(scip, cons0, NULL);
12753 SCIPdebugPrintCons(scip, cons1, NULL);
12754
12755 /* get temporary memory for creating the new linear constraint */
12756 SCIP_CALL( SCIPallocBufferArray(scip, &newvars, bestnvars) );
12757 SCIP_CALL( SCIPallocBufferArray(scip, &newvals, bestnvars) );
12758
12759 /* calculate the common coefficients, if we have not recognized linear dependency */
12760 newnvars = 0;
12761 if( !commonvarlindependent )
12762 {
12763 for( i = 0; i < nvarscommon; ++i )
12764 {
12765 assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12766 assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12767
12768 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12769 if( !SCIPisZero(scip, aggrcoef) )
12770 {
12771 assert(newnvars < bestnvars);
12772 newvars[newnvars] = consdata0->vars[commonidx0[i]];
12773 newvals[newnvars] = aggrcoef;
12774 newnvars++;
12775 }
12776 }
12777 }
12778 else
12779 {
12780 /* if we recognized linear dependency of the common coefficients, then the aggregation coefficient should be 0.0 for every common variable */
12781#ifndef NDEBUG
12782 for( i = 0; i < nvarscommon; ++i )
12783 {
12784 assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12785 assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12786
12787 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12788 assert(SCIPisZero(scip, aggrcoef));
12789 }
12790#endif
12791 }
12792
12793 /* calculate the coefficients appearing in cons0 but not in cons1 */
12794 for( i = 0; i < consdata0->nvars - nvarscommon; ++i )
12795 {
12796 assert(0 <= diffidx0minus1[i] && diffidx0minus1[i] < consdata0->nvars);
12797
12798 aggrcoef = a * consdata0->vals[diffidx0minus1[i]];
12799 assert(!SCIPisZero(scip, aggrcoef));
12800 assert(newnvars < bestnvars);
12801 newvars[newnvars] = consdata0->vars[diffidx0minus1[i]];
12802 newvals[newnvars] = aggrcoef;
12803 newnvars++;
12804 }
12805
12806 /* calculate the coefficients appearing in cons1 but not in cons0 */
12807 for( i = 0; i < consdata1->nvars - nvarscommon; ++i )
12808 {
12809 assert(0 <= diffidx1minus0[i] && diffidx1minus0[i] < consdata1->nvars);
12810
12811 aggrcoef = b * consdata1->vals[diffidx1minus0[i]];
12812 assert(!SCIPisZero(scip, aggrcoef));
12813 assert(newnvars < bestnvars);
12814 newvars[newnvars] = consdata1->vars[diffidx1minus0[i]];
12815 newvals[newnvars] = aggrcoef;
12816 newnvars++;
12817 }
12818 assert(newnvars == bestnvars);
12819
12820 /* calculate the new left and right hand side of the (in)equality */
12821 assert(!SCIPisInfinity(scip, -consdata1->lhs));
12822 assert(!SCIPisInfinity(scip, consdata1->rhs));
12823 if( SCIPisInfinity(scip, -consdata0->lhs) )
12824 newlhs = -SCIPinfinity(scip);
12825 else
12826 newlhs = a * consdata0->lhs + b * consdata1->lhs;
12827 if( SCIPisInfinity(scip, consdata0->rhs) )
12828 newrhs = SCIPinfinity(scip);
12829 else
12830 newrhs = a * consdata0->rhs + b * consdata1->rhs;
12831
12832 /* create the new linear constraint */
12833 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, SCIPconsGetName(cons0), newnvars, newvars, newvals, newlhs, newrhs,
12838
12839 newconsdata = SCIPconsGetData(newcons);
12840 assert(newconsdata != NULL);
12841
12842 /* copy the upgraded flag from the old cons0 to the new constraint */
12843 newconsdata->upgraded = consdata0->upgraded;
12844
12845 SCIP_CALL( normalizeCons(scip, newcons, infeasible) );
12846
12847 /* check, if we really want to use the new constraint instead of the old one:
12848 * use the new one, if the maximum norm doesn't grow too much
12849 */
12850 if( !(*infeasible) && consdataGetMaxAbsval(SCIPconsGetData(newcons)) <= maxaggrnormscale * consdataGetMaxAbsval(consdata0) )
12851 {
12852 SCIPdebugMsg(scip, " -> aggregated to <%s>\n", SCIPconsGetName(newcons));
12853 SCIPdebugPrintCons(scip, newcons, NULL);
12854
12855 /* update the statistics: we changed all coefficients */
12856 if( !consdata0->upgraded )
12857 (*nchgcoefs) += consdata0->nvars + consdata1->nvars - nvarscommon;
12858 *aggregated = TRUE;
12859
12860 /* add the new linear constraint to the problem and delete the old constraint */
12861 SCIP_CALL( SCIPaddConsUpgrade(scip, cons0, &newcons) );
12862 SCIP_CALL( SCIPdelCons(scip, cons0) );
12863 }
12864 else
12865 {
12866 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
12867 }
12868
12869 /* free temporary memory */
12870 SCIPfreeBufferArray(scip, &newvals);
12871 SCIPfreeBufferArray(scip, &newvars);
12872 }
12873
12874 return SCIP_OKAY;
12875}
12876
12877/** gets the key of the given element */
12878static
12879SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
12880{ /*lint --e{715}*/
12881 /* the key is the element itself */
12882 return elem;
12883}
12884
12885/** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables and the
12886 * coefficients are either equal or negated
12887 */
12888static
12889SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
12890{
12891 SCIP* scip;
12892 SCIP_CONSDATA* consdata1;
12893 SCIP_CONSDATA* consdata2;
12894 SCIP_Real minscale;
12895 SCIP_Real maxscale;
12896 int i;
12897
12898 assert(key1 != NULL);
12899 assert(key2 != NULL);
12900 consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
12901 consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
12902 assert(consdata1->indexsorted);
12903 assert(consdata2->indexsorted);
12904
12905 scip = (SCIP*)userptr;
12906 assert(scip != NULL);
12907
12908 /* if it is the same constraint we dont need to check anything */
12909 if( key1 == key2 )
12910 return TRUE;
12911
12912 /* checks trivial case */
12913 if( consdata1->nvars != consdata2->nvars )
12914 return FALSE;
12915
12916 /* tests if variables are equal */
12917 for( i = 0; i < consdata1->nvars; ++i )
12918 {
12919 if( consdata1->vars[i] != consdata2->vars[i] )
12920 {
12921 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
12922 SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
12923 return FALSE;
12924 }
12925 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
12926 }
12927
12928 /* order by maxabsval */
12929 if( consdataGetMaxAbsval(consdata1) > consdataGetMaxAbsval(consdata2) )
12930 SCIPswapPointers((void**)&consdata1, (void**)&consdata2);
12931
12932 /* initialize extremal scales */
12933 minscale = SCIPinfinity(scip);
12934 maxscale = -SCIPinfinity(scip);
12935
12936 /* test if coefficient scales are equal */
12937 for( i = 0; i < consdata1->nvars; ++i )
12938 {
12939 SCIP_Real scale = consdata2->vals[i] / consdata1->vals[i];
12940
12941 if( minscale > scale )
12942 {
12943 minscale = scale;
12944
12945 if( SCIPisLT(scip, minscale, maxscale) )
12946 return FALSE;
12947 }
12948
12949 if( maxscale < scale )
12950 {
12951 maxscale = scale;
12952
12953 if( SCIPisLT(scip, minscale, maxscale) )
12954 return FALSE;
12955 }
12956 }
12957
12958 return TRUE;
12959}
12960
12961/** returns the hash value of the key */
12962static
12963SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
12964{
12965 SCIP_CONSDATA* consdata;
12966 int minidx;
12967 int mididx;
12968 int maxidx;
12969#ifndef NDEBUG
12970 SCIP* scip;
12971
12972 scip = (SCIP*)userptr;
12973 assert(scip != NULL);
12974#endif
12975
12976 assert(key != NULL);
12977 consdata = SCIPconsGetData((SCIP_CONS*)key);
12978 assert(consdata != NULL);
12979 assert(consdata->nvars > 0);
12980
12981 assert(consdata->indexsorted);
12982
12983 minidx = SCIPvarGetIndex(consdata->vars[0]);
12984 mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
12985 maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
12986
12987 /* using only the variable indices as hash, since the values are compared by epsilon */
12988 return SCIPhashFour(consdata->nvars, minidx, mididx, maxidx);
12989}
12990
12991/** returns the key for deciding which of two parallel constraints should be kept (smaller key should be kept);
12992 * prefers non-upgraded constraints and as second criterion the constraint with the smallest position
12993 */
12994static
12996 SCIP_CONS* cons /**< linear constraint */
12997 )
12998{
12999 SCIP_CONSDATA* consdata;
13000
13001 assert(cons != NULL);
13002
13003 consdata = SCIPconsGetData(cons);
13004 assert(consdata != NULL);
13005
13006 return (((unsigned int)consdata->upgraded)<<31) + (unsigned int)SCIPconsGetPos(cons); /*lint !e571*/
13007}
13008
13009/** updates the hashtable such that out of all constraints in the hashtable that are detected
13010 * to be parallel to *querycons, only one is kept in the hashtable and stored into *querycons,
13011 * and all others are removed from the hashtable and stored in the given array
13012 */
13013static
13015 SCIP_HASHTABLE* hashtable, /**< hashtable containing linear constraints */
13016 SCIP_CONS** querycons, /**< pointer to linear constraint used to look for duplicates in the hash table;
13017 * upon return will contain the constraint that should be kept */
13018 SCIP_CONS** parallelconss, /**< array to return constraints that are parallel to the given;
13019 * these constraints where removed from the hashtable */
13020 int* nparallelconss /**< pointer to return number of parallel constraints */
13021 )
13022{
13023 SCIP_CONS* parallelcons;
13024 unsigned int querykey;
13025
13026 *nparallelconss = 0;
13027 querykey = getParallelConsKey(*querycons);
13028
13029 while( (parallelcons = (SCIP_CONS*)SCIPhashtableRetrieve(hashtable, (void*)(*querycons))) != NULL )
13030 {
13031 unsigned int conskey = getParallelConsKey(parallelcons);
13032
13033 if( conskey < querykey )
13034 {
13035 parallelconss[(*nparallelconss)++] = *querycons;
13036 *querycons = parallelcons;
13037 querykey = conskey;
13038 }
13039 else
13040 {
13041 parallelconss[(*nparallelconss)++] = parallelcons;
13042 }
13043
13044 /* if the constraint that just came out of the hash table is the one that is kept,
13045 * we do not need to look into the hashtable again, since the invariant is that
13046 * in the hashtable only pair-wise non-parallel constraints are contained.
13047 * For the original querycons, however, multiple constraints that compare equal (=parallel)
13048 * could be contained due to non-transitivity of the equality comparison.
13049 * Also we can return immediately, since parallelcons is already contained in the
13050 * hashtable and we do not need to remove and reinsert it.
13051 */
13052 if( *querycons == parallelcons )
13053 return SCIP_OKAY;
13054
13055 /* remove parallelcons from the hashtable, since it will be replaced by querycons */
13056 SCIP_CALL( SCIPhashtableRemove(hashtable, (void*) parallelcons) );
13057 }
13058
13059 /* in debug mode we make sure, that the hashtable cannot contain a constraint that
13060 * comnpares equal to querycons at this point
13061 */
13062#ifndef NDEBUG
13063 SCIP_CALL_ABORT( SCIPhashtableSafeInsert(hashtable, *querycons) );
13064#else
13065 SCIP_CALL( SCIPhashtableInsert(hashtable, *querycons) );
13066#endif
13067
13068 return SCIP_OKAY;
13069}
13070
13071/** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
13072 * accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
13073 */
13074static
13076 SCIP* scip, /**< SCIP data structure */
13077 BMS_BLKMEM* blkmem, /**< block memory */
13078 SCIP_CONS** conss, /**< constraint set */
13079 int nconss, /**< number of constraints in constraint set */
13080 int* firstchange, /**< pointer to store first changed constraint */
13081 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13082 int* ndelconss, /**< pointer to count number of deleted constraints */
13083 int* nchgsides /**< pointer to count number of changed left/right hand sides */
13084 )
13085{
13086 SCIP_HASHTABLE* hashtable;
13087 SCIP_CONS** parallelconss;
13088 int nparallelconss;
13089 int hashtablesize;
13090 int c;
13091
13092 assert(scip != NULL);
13093 assert(blkmem != NULL);
13094 assert(conss != NULL);
13095 assert(firstchange != NULL);
13096 assert(cutoff != NULL);
13097 assert(ndelconss != NULL);
13098 assert(nchgsides != NULL);
13099
13100 /* create a hash table for the constraint set */
13101 hashtablesize = nconss;
13102 SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
13103 hashGetKeyLinearcons, hashKeyEqLinearcons, hashKeyValLinearcons, (void*) scip) );
13104
13105 SCIP_CALL( SCIPallocBufferArray(scip, &parallelconss, nconss) );
13106
13107 /* check all constraints in the given set for redundancy */
13108 for( c = 0; c < nconss; ++c )
13109 {
13110 SCIP_CONS* cons0;
13111 SCIP_CONSDATA* consdata0;
13112
13113 cons0 = conss[c];
13114
13115 if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
13116 continue;
13117
13118 /* do not check for parallel constraints if they should not be upgraded */
13119 if ( SCIPconsGetNUpgradeLocks(cons0) > 0 )
13120 continue;
13121
13122 /* check for interuption */
13123 if( c % 1000 == 0 && SCIPisStopped(scip) )
13124 break;
13125
13126 /* sorts the constraint */
13127 consdata0 = SCIPconsGetData(cons0);
13128 assert(consdata0 != NULL);
13129 SCIP_CALL( consdataSort(scip, consdata0) );
13130 assert(consdata0->indexsorted);
13131
13132 /* get constraints from current hash table with same variables as cons0 and with coefficients equal
13133 * to the ones of cons0 when both are scaled such that maxabsval is 1.0 and the coefficient of the
13134 * first variable is positive
13135 * Also inserts cons0 into the hashtable.
13136 */
13137 SCIP_CALL( retrieveParallelConstraints(hashtable, &cons0, parallelconss, &nparallelconss) );
13138
13139 if( nparallelconss != 0 )
13140 {
13141 SCIP_Real lhs;
13142 SCIP_Real rhs;
13143
13144 int i;
13145
13146 /* cons0 may have been changed in retrieveParallelConstraints() */
13147 consdata0 = SCIPconsGetData(cons0);
13148
13149 lhs = consdata0->lhs;
13150 rhs = consdata0->rhs;
13151
13152 for( i = 0; i < nparallelconss; ++i )
13153 {
13154 SCIP_CONS* consdel;
13155 SCIP_CONSDATA* consdatadel;
13156 SCIP_Real scale;
13157
13158 consdel = parallelconss[i];
13159 consdatadel = SCIPconsGetData(consdel);
13160
13161 /* do not delete constraint if it should not be upgraded */
13162 if ( SCIPconsGetNUpgradeLocks(consdel) > 0 )
13163 continue;
13164
13165 assert(SCIPconsIsActive(consdel));
13166 assert(!SCIPconsIsModifiable(consdel));
13167
13168 /* constraint found: create a new constraint with same coefficients and best left and right hand side;
13169 * delete old constraints afterwards
13170 */
13171 assert(consdatadel != NULL);
13172 assert(consdata0->nvars >= 1 && consdata0->nvars == consdatadel->nvars);
13173
13174 assert(consdatadel->indexsorted);
13175 assert(consdata0->vars[0] == consdatadel->vars[0]);
13176
13177 scale = consdata0->vals[0] / consdatadel->vals[0];
13178 assert(scale != 0.0);
13179
13180 /* in debug mode, check that all coefficients are equal with respect to epsilon
13181 * if the constraints are in equilibrium scale
13182 */
13183#ifndef NDEBUG
13184 {
13185 assert(consdata0->validmaxabsval);
13186 assert(consdatadel->validmaxabsval);
13187 int k;
13188 SCIP_Real scale0 = 1.0 / consdata0->maxabsval;
13189 SCIP_Real scaledel = COPYSIGN(1.0 / consdatadel->maxabsval, scale);
13190
13191 for( k = 0; k < consdata0->nvars; ++k )
13192 {
13193 assert(SCIPisEQ(scip, scale0 * consdata0->vals[k], scaledel * consdatadel->vals[k]));
13194 }
13195 }
13196#endif
13197
13198 if( scale > 0.0 )
13199 {
13200 /* the coefficients of both constraints are parallel with a positive scale */
13201 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with equal coefficients into single ranged row\n",
13202 SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13203 SCIPdebugPrintCons(scip, cons0, NULL);
13204 SCIPdebugPrintCons(scip, consdel, NULL);
13205
13206 if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13207 lhs = MAX(scale * consdatadel->lhs, lhs);
13208
13209 if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13210 rhs = MIN(scale * consdatadel->rhs, rhs);
13211 }
13212 else
13213 {
13214 /* the coefficients of both rows are negations */
13215 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with negated coefficients into single ranged row\n",
13216 SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13217 SCIPdebugPrintCons(scip, cons0, NULL);
13218 SCIPdebugPrintCons(scip, consdel, NULL);
13219
13220 if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13221 lhs = MAX(scale * consdatadel->rhs, lhs);
13222
13223 if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13224 rhs = MIN(scale * consdatadel->lhs, rhs);
13225 }
13226
13227 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13228 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, consdel) );
13229
13230 /* delete consdel */
13231 assert( ! consdata0->upgraded || consdatadel->upgraded );
13232 SCIP_CALL( SCIPdelCons(scip, consdel) );
13233 if( !consdatadel->upgraded )
13234 (*ndelconss)++;
13235 }
13236
13237 if( SCIPisFeasLT(scip, rhs, lhs) )
13238 {
13239 SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13240 *cutoff = TRUE;
13241 break;
13242 }
13243
13244 /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
13245 if( lhs > rhs )
13246 {
13247 rhs = (lhs + rhs)/2;
13248 lhs = rhs;
13249 }
13250
13251 /* update lhs and rhs of cons0 */
13252 SCIP_CALL( chgLhs(scip, cons0, lhs) );
13253 SCIP_CALL( chgRhs(scip, cons0, rhs) );
13254
13255 /* update the first changed constraint to begin the next aggregation round with */
13256 if( consdata0->changed && SCIPconsGetPos(cons0) < *firstchange )
13257 *firstchange = SCIPconsGetPos(cons0);
13258
13259 assert(SCIPconsIsActive(cons0));
13260 }
13261 }
13262#ifdef SCIP_MORE_DEBUG
13263 SCIPinfoMessage(scip, NULL, "linear pairwise comparison hashtable statistics:\n");
13265#endif
13266
13267 SCIPfreeBufferArray(scip, &parallelconss);
13268
13269 /* free hash table */
13270 SCIPhashtableFree(&hashtable);
13271
13272 return SCIP_OKAY;
13273}
13274
13275/** compares constraint with all prior constraints for possible redundancy or aggregation,
13276 * and removes or changes constraint accordingly
13277 */
13278static
13280 SCIP* scip, /**< SCIP data structure */
13281 SCIP_CONS** conss, /**< constraint set */
13282 int firstchange, /**< first constraint that changed since last pair preprocessing round */
13283 int chkind, /**< index of constraint to check against all prior indices upto startind */
13284 SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
13285 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13286 int* ndelconss, /**< pointer to count number of deleted constraints */
13287 int* nchgsides, /**< pointer to count number of changed left/right hand sides */
13288 int* nchgcoefs /**< pointer to count number of changed coefficients */
13289 )
13290{
13291 SCIP_CONS* cons0;
13292 SCIP_CONSDATA* consdata0;
13293 int* commonidx0;
13294 int* commonidx1;
13295 int* diffidx0minus1;
13296 int* diffidx1minus0;
13297 uint64_t possignature0;
13298 uint64_t negsignature0;
13299 SCIP_Bool cons0changed;
13300 SCIP_Bool cons0isequality;
13301 int diffidx1minus0size;
13302 int c;
13303 SCIP_Real cons0lhs;
13304 SCIP_Real cons0rhs;
13305 SCIP_Bool cons0upgraded;
13306
13307 assert(scip != NULL);
13308 assert(conss != NULL);
13309 assert(firstchange <= chkind);
13310 assert(cutoff != NULL);
13311 assert(ndelconss != NULL);
13312 assert(nchgsides != NULL);
13313 assert(nchgcoefs != NULL);
13314
13315 /* get the constraint to be checked against all prior constraints */
13316 cons0 = conss[chkind];
13317 assert(cons0 != NULL);
13318 assert(SCIPconsIsActive(cons0));
13320
13321 consdata0 = SCIPconsGetData(cons0);
13322 assert(consdata0 != NULL);
13323 assert(consdata0->nvars >= 1);
13324 cons0isequality = SCIPisEQ(scip, consdata0->lhs, consdata0->rhs);
13325
13326 /* sort the constraint */
13327 SCIP_CALL( consdataSort(scip, consdata0) );
13328
13329 /* calculate bit signatures of cons0 for potentially positive and negative coefficients */
13330 consdataCalcSignatures(consdata0);
13331 possignature0 = consdata0->possignature;
13332 negsignature0 = consdata0->negsignature;
13333
13334 /* get temporary memory for indices of common variables */
13335 SCIP_CALL( SCIPallocBufferArray(scip, &commonidx0, consdata0->nvars) );
13336 SCIP_CALL( SCIPallocBufferArray(scip, &commonidx1, consdata0->nvars) );
13337 SCIP_CALL( SCIPallocBufferArray(scip, &diffidx0minus1, consdata0->nvars) );
13338 SCIP_CALL( SCIPallocBufferArray(scip, &diffidx1minus0, consdata0->nvars) );
13339 diffidx1minus0size = consdata0->nvars;
13340
13341 cons0lhs = consdata0->lhs;
13342 cons0rhs = consdata0->rhs;
13343 cons0upgraded = consdata0->upgraded;
13344
13345 /* check constraint against all prior constraints */
13346 cons0changed = consdata0->changed;
13347 consdata0->changed = FALSE;
13348 for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && conss[chkind] != NULL; ++c )
13349 {
13350 SCIP_CONS* cons1;
13351 SCIP_CONSDATA* consdata1;
13352 uint64_t possignature1;
13353 uint64_t negsignature1;
13354 SCIP_Bool cons0dominateslhs;
13355 SCIP_Bool cons1dominateslhs;
13356 SCIP_Bool cons0dominatesrhs;
13357 SCIP_Bool cons1dominatesrhs;
13358 SCIP_Bool cons1isequality;
13359 SCIP_Bool coefsequal;
13360 SCIP_Bool coefsnegated;
13361 SCIP_Bool tryaggregation;
13362 int nvarscommon;
13363 int nvars0minus1;
13364 int nvars1minus0;
13365 int commonidxweight;
13366 int diffidx0minus1weight;
13367 int diffidx1minus0weight;
13368 int v0;
13369 int v1;
13370
13371 assert(cons0lhs == consdata0->lhs); /*lint !e777*/
13372 assert(cons0rhs == consdata0->rhs); /*lint !e777*/
13373 assert(cons0upgraded == consdata0->upgraded);
13374
13375 cons1 = conss[c];
13376
13377 /* cons1 has become inactive during presolving of constraint pairs */
13378 if( cons1 == NULL )
13379 continue;
13380
13381 assert(SCIPconsIsActive(cons0) && !SCIPconsIsModifiable(cons0));
13382 assert(SCIPconsIsActive(cons1) && !SCIPconsIsModifiable(cons1));
13383
13384 consdata1 = SCIPconsGetData(cons1);
13385 assert(consdata1 != NULL);
13386
13387 /* SCIPdebugMsg(scip, "preprocess linear constraint pair <%s>[chgd:%d, upgd:%d] and <%s>[chgd:%d, upgd:%d]\n",
13388 SCIPconsGetName(cons0), cons0changed, cons0upgraded,
13389 SCIPconsGetName(cons1), consdata1->changed, consdata1->upgraded); */
13390
13391 /* if both constraints didn't change since last pair processing, we can ignore the pair */
13392 if( !cons0changed && !consdata1->changed )
13393 continue;
13394
13395 /* if both constraints are already upgraded, skip the pair;
13396 * because changes on these constraints cannot be applied to the instance anymore */
13397 if( cons0upgraded && consdata1->upgraded )
13398 continue;
13399
13400 assert(consdata1->nvars >= 1);
13401
13402 /* sort the constraint */
13403 SCIP_CALL( consdataSort(scip, consdata1) );
13404
13405 /* calculate bit signatures of cons1 for potentially positive and negative coefficients */
13406 consdataCalcSignatures(consdata1);
13407 possignature1 = consdata1->possignature;
13408 negsignature1 = consdata1->negsignature;
13409
13410 /* the signatures give a quick test to check for domination and equality of coefficients */
13411 coefsequal = (possignature0 == possignature1) && (negsignature0 == negsignature1);
13412 coefsnegated = (possignature0 == negsignature1) && (negsignature0 == possignature1);
13413 cons0dominateslhs = SCIPisGE(scip, cons0lhs, consdata1->lhs)
13414 && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13415 && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13416 cons1dominateslhs = SCIPisGE(scip, consdata1->lhs, cons0lhs)
13417 && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13418 && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13419 cons0dominatesrhs = SCIPisLE(scip, cons0rhs, consdata1->rhs)
13420 && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13421 && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13422 cons1dominatesrhs = SCIPisLE(scip, consdata1->rhs, cons0rhs)
13423 && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13424 && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13425 cons1isequality = SCIPisEQ(scip, consdata1->lhs, consdata1->rhs);
13426 tryaggregation = (cons0isequality || cons1isequality) && (maxaggrnormscale > 0.0);
13427 if( !cons0dominateslhs && !cons1dominateslhs && !cons0dominatesrhs && !cons1dominatesrhs
13428 && !coefsequal && !coefsnegated && !tryaggregation )
13429 continue;
13430
13431 /* make sure, we have enough memory for the index set of V_1 \ V_0 */
13432 if( tryaggregation && consdata1->nvars > diffidx1minus0size )
13433 {
13434 SCIP_CALL( SCIPreallocBufferArray(scip, &diffidx1minus0, consdata1->nvars) );
13435 diffidx1minus0size = consdata1->nvars;
13436 }
13437
13438 /* check consdata0 against consdata1:
13439 * - if lhs0 >= lhs1 and for each variable v and each solution value x_v val0[v]*x_v <= val1[v]*x_v,
13440 * consdata0 dominates consdata1 w.r.t. left hand side
13441 * - if rhs0 <= rhs1 and for each variable v and each solution value x_v val0[v]*x_v >= val1[v]*x_v,
13442 * consdata0 dominates consdata1 w.r.t. right hand side
13443 * - if val0[v] == -val1[v] for all variables v, the two inequalities can be replaced by a single
13444 * ranged row (or equality)
13445 * - if at least one constraint is an equality, count the weighted number of common variables W_c
13446 * and the weighted number of variable in the difference sets W_0 = w(V_0 \ V_1), W_1 = w(V_1 \ V_0),
13447 * where the weight of each variable depends on its type, such that aggregations in order to remove the
13448 * number of continuous and integer variables are preferred:
13449 * - if W_c > W_1, try to aggregate consdata0 := a * consdata0 + b * consdata1 in order to decrease the
13450 * variable weight in consdata0, where a = +/- val1[v] and b = -/+ val0[v] for common v which leads to
13451 * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13452 * to be positive to not switch the sense of the (in)equality cons0
13453 * - if W_c > W_0, try to aggregate consdata1 := a * consdata1 + b * consdata0 in order to decrease the
13454 * variable weight in consdata1, where a = +/- val0[v] and b = -/+ val1[v] for common v which leads to
13455 * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13456 * to be positive to not switch the sense of the (in)equality cons1
13457 */
13458
13459 /* check consdata0 against consdata1 for redundancy, or ranged row accumulation */
13460 nvarscommon = 0;
13461 commonidxweight = 0;
13462 nvars0minus1 = 0;
13463 diffidx0minus1weight = 0;
13464 nvars1minus0 = 0;
13465 diffidx1minus0weight = 0;
13466 v0 = 0;
13467 v1 = 0;
13468 while( (v0 < consdata0->nvars || v1 < consdata1->nvars)
13469 && (cons0dominateslhs || cons1dominateslhs || cons0dominatesrhs || cons1dominatesrhs
13470 || coefsequal || coefsnegated || tryaggregation) )
13471 {
13472 SCIP_VAR* var;
13473 SCIP_Real val0;
13474 SCIP_Real val1;
13475 int varcmp;
13476
13477 /* test, if variable appears in only one or in both constraints */
13478 if( v0 < consdata0->nvars && v1 < consdata1->nvars )
13479 varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
13480 else if( v0 < consdata0->nvars )
13481 varcmp = -1;
13482 else
13483 varcmp = +1;
13484
13485 switch( varcmp )
13486 {
13487 case -1:
13488 /* variable doesn't appear in consdata1 */
13489 var = consdata0->vars[v0];
13490 val0 = consdata0->vals[v0];
13491 val1 = 0.0;
13492 if( tryaggregation )
13493 {
13494 diffidx0minus1[nvars0minus1] = v0;
13495 nvars0minus1++;
13496 diffidx0minus1weight += getVarWeight(var);
13497 }
13498 v0++;
13499 coefsequal = FALSE;
13500 coefsnegated = FALSE;
13501 break;
13502
13503 case +1:
13504 /* variable doesn't appear in consdata0 */
13505 var = consdata1->vars[v1];
13506 val0 = 0.0;
13507 val1 = consdata1->vals[v1];
13508 if( tryaggregation )
13509 {
13510 diffidx1minus0[nvars1minus0] = v1;
13511 nvars1minus0++;
13512 diffidx1minus0weight += getVarWeight(var);
13513 }
13514 v1++;
13515 coefsequal = FALSE;
13516 coefsnegated = FALSE;
13517 break;
13518
13519 case 0:
13520 /* variable appears in both constraints */
13521 assert(consdata0->vars[v0] == consdata1->vars[v1]);
13522 var = consdata0->vars[v0];
13523 val0 = consdata0->vals[v0];
13524 val1 = consdata1->vals[v1];
13525 if( tryaggregation )
13526 {
13527 commonidx0[nvarscommon] = v0;
13528 commonidx1[nvarscommon] = v1;
13529 nvarscommon++;
13530 commonidxweight += getVarWeight(var);
13531 }
13532 v0++;
13533 v1++;
13534 coefsequal = coefsequal && (SCIPisEQ(scip, val0, val1));
13535 coefsnegated = coefsnegated && (SCIPisEQ(scip, val0, -val1));
13536 break;
13537
13538 default:
13539 SCIPerrorMessage("invalid comparison result\n");
13540 SCIPABORT();
13541 var = NULL;
13542 val0 = 0.0;
13543 val1 = 0.0;
13544 }
13545 assert(var != NULL);
13546
13547 /* update domination criteria w.r.t. the coefficient and the variable's bounds */
13548 if( SCIPisGT(scip, val0, val1) )
13549 {
13551 {
13552 cons0dominatesrhs = FALSE;
13553 cons1dominateslhs = FALSE;
13554 }
13556 {
13557 cons0dominateslhs = FALSE;
13558 cons1dominatesrhs = FALSE;
13559 }
13560 }
13561 else if( SCIPisLT(scip, val0, val1) )
13562 {
13564 {
13565 cons0dominateslhs = FALSE;
13566 cons1dominatesrhs = FALSE;
13567 }
13569 {
13570 cons0dominatesrhs = FALSE;
13571 cons1dominateslhs = FALSE;
13572 }
13573 }
13574 }
13575
13576 /* check for disaggregated ranged rows */
13577 if( coefsequal || coefsnegated )
13578 {
13579 SCIP_CONS* consstay;
13580 SCIP_CONS* consdel;
13581#ifndef NDEBUG
13582 SCIP_CONSDATA* consdatastay;
13583#endif
13584 SCIP_CONSDATA* consdatadel;
13585 SCIP_Real lhs;
13586 SCIP_Real rhs;
13587 int consinddel;
13588
13589 /* the coefficients in both rows are either equal or negated: create a new constraint with same coefficients and
13590 * best left and right hand sides; delete the old constraints afterwards
13591 */
13592 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with %s coefficients into single ranged row\n",
13593 SCIPconsGetName(cons0), SCIPconsGetName(cons1), coefsequal ? "equal" : "negated");
13594 SCIPdebugPrintCons(scip, cons0, NULL);
13595 SCIPdebugPrintCons(scip, cons1, NULL);
13596
13597 if( coefsequal )
13598 {
13599 /* the coefficients of both rows are equal */
13600 lhs = MAX(consdata0->lhs, consdata1->lhs);
13601 rhs = MIN(consdata0->rhs, consdata1->rhs);
13602 }
13603 else
13604 {
13605 /* the coefficients of both rows are negations */
13606 lhs = MAX(consdata0->lhs, -consdata1->rhs);
13607 rhs = MIN(consdata0->rhs, -consdata1->lhs);
13608 }
13609 if( SCIPisFeasLT(scip, rhs, lhs) )
13610 {
13611 SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13612 *cutoff = TRUE;
13613 break;
13614 }
13615
13616 /* check which constraint has to stay;
13617 * changes applied to an upgraded constraint will not be considered in the instance */
13618 if( consdata0->upgraded )
13619 {
13620 assert(!consdata1->upgraded);
13621 consstay = cons1;
13622#ifndef NDEBUG
13623 consdatastay = consdata1;
13624#endif
13625
13626 consdel = cons0;
13627 consdatadel = consdata0;
13628 consinddel = chkind;
13629 }
13630 else
13631 {
13632 consstay = cons0;
13633#ifndef NDEBUG
13634 consdatastay = consdata0;
13635#endif
13636
13637 consdel = cons1;
13638 consdatadel = consdata1;
13639 consinddel = c;
13640 }
13641
13642 /* update the sides of consstay */
13643 SCIP_CALL( chgLhs(scip, consstay, lhs) );
13644 SCIP_CALL( chgRhs(scip, consstay, rhs) );
13645 if( !consdata0->upgraded )
13646 {
13647 assert(consstay == cons0);
13648 cons0lhs = consdata0->lhs;
13649 cons0rhs = consdata0->rhs;
13650 }
13651
13652 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13653 SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) );
13654
13655 assert( !consdatastay->upgraded );
13656 /* delete consdel */
13657 SCIP_CALL( SCIPdelCons(scip, consdel) );
13658 conss[consinddel] = NULL;
13659 if( !consdatadel->upgraded )
13660 (*ndelconss)++;
13661 continue;
13662 }
13663
13664 /* check for domination: remove dominated sides, but don't touch equalities as long as they are not totally
13665 * redundant
13666 */
13667 if( cons1dominateslhs && (!cons0isequality || cons1dominatesrhs || SCIPisInfinity(scip, consdata0->rhs) ) )
13668 {
13669 /* left hand side is dominated by consdata1: delete left hand side of consdata0 */
13670 SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13671 SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13672 SCIPdebugPrintCons(scip, cons0, NULL);
13673 SCIPdebugPrintCons(scip, cons1, NULL);
13674
13675 /* check for infeasibility */
13676 if( SCIPisFeasGT(scip, consdata1->lhs, consdata0->rhs) )
13677 {
13678 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13679 *cutoff = TRUE;
13680 break;
13681 }
13682
13683 /* remove redundant left hand side */
13684 if( !SCIPisInfinity(scip, -consdata0->lhs) )
13685 {
13686 SCIP_CALL( chgLhs(scip, cons0, -SCIPinfinity(scip)) );
13687 cons0lhs = consdata0->lhs;
13688 cons0isequality = FALSE;
13689 if( !consdata0->upgraded )
13690 {
13691 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13692 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13693
13694 (*nchgsides)++;
13695 }
13696 }
13697 }
13698 else if( cons0dominateslhs && (!cons1isequality || cons0dominatesrhs || SCIPisInfinity(scip, consdata1->rhs)) )
13699 {
13700 /* left hand side is dominated by consdata0: delete left hand side of consdata1 */
13701 SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13702 SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13703 SCIPdebugPrintCons(scip, cons1, NULL);
13704 SCIPdebugPrintCons(scip, cons0, NULL);
13705
13706 /* check for infeasibility */
13707 if( SCIPisFeasGT(scip, consdata0->lhs, consdata1->rhs) )
13708 {
13709 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13710 *cutoff = TRUE;
13711 break;
13712 }
13713
13714 /* remove redundant left hand side */
13715 if( !SCIPisInfinity(scip, -consdata1->lhs) )
13716 {
13717 SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
13718 cons1isequality = FALSE;
13719 if( !consdata1->upgraded )
13720 {
13721 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13722 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13723
13724 (*nchgsides)++;
13725 }
13726 }
13727 }
13728 if( cons1dominatesrhs && (!cons0isequality || cons1dominateslhs || SCIPisInfinity(scip, -consdata0->lhs)) )
13729 {
13730 /* right hand side is dominated by consdata1: delete right hand side of consdata0 */
13731 SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13732 SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13733 SCIPdebugPrintCons(scip, cons0, NULL);
13734 SCIPdebugPrintCons(scip, cons1, NULL);
13735
13736 /* check for infeasibility */
13737 if( SCIPisFeasLT(scip, consdata1->rhs, consdata0->lhs) )
13738 {
13739 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13740 *cutoff = TRUE;
13741 break;
13742 }
13743
13744 /* remove redundant right hand side */
13745 if( !SCIPisInfinity(scip, consdata0->rhs) )
13746 {
13747 SCIP_CALL( chgRhs(scip, cons0, SCIPinfinity(scip)) );
13748 cons0rhs = consdata0->rhs;
13749 cons0isequality = FALSE;
13750 if( !consdata0->upgraded )
13751 {
13752 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13753 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13754
13755 (*nchgsides)++;
13756 }
13757 }
13758 }
13759 else if( cons0dominatesrhs && (!cons1isequality || cons0dominateslhs || SCIPisInfinity(scip, -consdata1->lhs)) )
13760 {
13761 /* right hand side is dominated by consdata0: delete right hand side of consdata1 */
13762 SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13763 SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13764 SCIPdebugPrintCons(scip, cons1, NULL);
13765 SCIPdebugPrintCons(scip, cons0, NULL);
13766
13767 /* check for infeasibility */
13768 if( SCIPisFeasLT(scip, consdata0->rhs, consdata1->lhs) )
13769 {
13770 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13771 *cutoff = TRUE;
13772 break;
13773 }
13774
13775 /* remove redundant right hand side */
13776 if( !SCIPisInfinity(scip, consdata1->rhs) )
13777 {
13778 SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
13779 cons1isequality = FALSE;
13780 if( !consdata1->upgraded )
13781 {
13782 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13783 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13784
13785 (*nchgsides)++;
13786 }
13787 }
13788 }
13789
13790 /* check for now redundant constraints */
13791 if( SCIPisInfinity(scip, -consdata0->lhs) && SCIPisInfinity(scip, consdata0->rhs) )
13792 {
13793 /* consdata0 became redundant */
13794 SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons0));
13795 SCIP_CALL( SCIPdelCons(scip, cons0) );
13796 conss[chkind] = NULL;
13797 if( !consdata0->upgraded )
13798 {
13799 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13800 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13801
13802 (*ndelconss)++;
13803 }
13804 continue;
13805 }
13806 if( SCIPisInfinity(scip, -consdata1->lhs) && SCIPisInfinity(scip, consdata1->rhs) )
13807 {
13808 /* consdata1 became redundant */
13809 SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons1));
13810 SCIP_CALL( SCIPdelCons(scip, cons1) );
13811 conss[c] = NULL;
13812 if( !consdata1->upgraded )
13813 {
13814 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13815 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13816
13817 (*ndelconss)++;
13818 }
13819 continue;
13820 }
13821
13822 /* check, if we want to aggregate an (in)equality with an equality:
13823 * consdata0 := a * consdata0 + b * consdata1 or consdata1 := a * consdata1 + b * consdata0
13824 */
13825 if( tryaggregation )
13826 {
13827 SCIP_Bool aggregated;
13828
13829 assert(consdata0->nvars == nvarscommon + nvars0minus1);
13830 assert(consdata1->nvars == nvarscommon + nvars1minus0);
13831
13832 aggregated = FALSE;
13833 if( cons1isequality && !consdata0->upgraded && commonidxweight > diffidx1minus0weight )
13834 {
13835 /* W_c > W_1: try to aggregate consdata0 := a * consdata0 + b * consdata1 */
13836 SCIP_CALL( aggregateConstraints(scip, cons0, cons1, commonidx0, commonidx1, diffidx0minus1, diffidx1minus0,
13837 nvarscommon, commonidxweight, diffidx0minus1weight, diffidx1minus0weight, maxaggrnormscale,
13838 nchgcoefs, &aggregated, cutoff) );
13839
13840 if( *cutoff )
13841 break;
13842
13843 /* update array of active constraints */
13844 if( aggregated )
13845 {
13846 assert(!SCIPconsIsActive(cons0));
13847 assert(SCIPconsIsActive(cons1));
13848 conss[chkind] = NULL;
13849 }
13850 }
13851 if( !aggregated && cons0isequality && !consdata1->upgraded && commonidxweight > diffidx0minus1weight )
13852 {
13853 /* W_c > W_0: try to aggregate consdata1 := a * consdata1 + b * consdata0 */
13854 SCIP_CALL( aggregateConstraints(scip, cons1, cons0, commonidx1, commonidx0, diffidx1minus0, diffidx0minus1,
13855 nvarscommon, commonidxweight, diffidx1minus0weight, diffidx0minus1weight, maxaggrnormscale,
13856 nchgcoefs, &aggregated, cutoff) );
13857
13858 if( *cutoff )
13859 break;
13860
13861 /* update array of active constraints */
13862 if( aggregated )
13863 {
13864 assert(!SCIPconsIsActive(cons1));
13865 assert(SCIPconsIsActive(cons0));
13866 conss[c] = NULL;
13867 }
13868 }
13869 }
13870 }
13871
13872 /* free temporary memory */
13873 SCIPfreeBufferArray(scip, &diffidx1minus0);
13874 SCIPfreeBufferArray(scip, &diffidx0minus1);
13875 SCIPfreeBufferArray(scip, &commonidx1);
13876 SCIPfreeBufferArray(scip, &commonidx0);
13877
13878 return SCIP_OKAY;
13879}
13880
13881/** do stuffing presolving on a single constraint */
13882static
13884 SCIP* scip, /**< SCIP data structure */
13885 SCIP_CONS* cons, /**< linear constraint */
13886 SCIP_Bool singletonstuffing, /**< should stuffing of singleton continuous variables be performed? */
13887 SCIP_Bool singlevarstuffing, /**< should single variable stuffing be performed, which tries to fulfill
13888 * constraints using the cheapest variable? */
13889 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13890 int* nfixedvars, /**< pointer to count the total number of fixed variables */
13891 int* nchgbds /**< pointer to count the total number of tightened bounds */
13892 )
13893{
13894 SCIP_CONSDATA* consdata;
13895 SCIP_Real* ratios;
13896 int* varpos;
13897 SCIP_Bool* swapped;
13898 SCIP_VAR** vars;
13899 SCIP_Real* vals;
13900 SCIP_VAR* var;
13901 SCIP_Real lb;
13902 SCIP_Real ub;
13903 SCIP_Real minactivity;
13904 SCIP_Real maxactivity;
13905 SCIP_Real maxcondactivity;
13906 SCIP_Real mincondactivity;
13907 SCIP_Real rhs;
13908 SCIP_Real val;
13909 SCIP_Real obj;
13910 SCIP_Real factor;
13911 SCIP_Bool isminacttight;
13912 SCIP_Bool ismaxacttight;
13913 SCIP_Bool isminsettoinfinity;
13914 SCIP_Bool ismaxsettoinfinity;
13915 SCIP_Bool tryfixing;
13916 int nsingletons;
13917 int idx;
13918 int v;
13919 int nvars;
13920
13921 assert(scip != NULL);
13922 assert(cons != NULL);
13923 assert(nfixedvars != NULL);
13924
13925 consdata = SCIPconsGetData(cons);
13926
13927 /* we only want to run for inequalities */
13928 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->lhs) )
13929 return SCIP_OKAY;
13930
13931 if( singlevarstuffing )
13932 {
13933 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
13934 &isminsettoinfinity, &ismaxsettoinfinity);
13935 }
13936 else
13937 {
13938 minactivity = SCIP_INVALID;
13939 maxactivity = SCIP_INVALID;
13940 isminsettoinfinity = FALSE;
13941 ismaxsettoinfinity = FALSE;
13942 }
13943
13944 /* we want to have a <= constraint, if the rhs is infinite, we implicitly multiply the constraint by -1,
13945 * the new maxactivity is minus the old minactivity then
13946 */
13947 if( SCIPisInfinity(scip, consdata->rhs) )
13948 {
13949 rhs = -consdata->lhs;
13950 factor = -1.0;
13951 maxactivity = -minactivity;
13952 ismaxsettoinfinity = isminsettoinfinity;
13953 }
13954 else
13955 {
13956 assert(SCIPisInfinity(scip, -consdata->lhs));
13957 rhs = consdata->rhs;
13958 factor = 1.0;
13959 }
13960
13961 nvars = consdata->nvars;
13962 vars = consdata->vars;
13963 vals = consdata->vals;
13964
13965 /* check for continuous singletons */
13966 if( singletonstuffing )
13967 {
13968 for( v = 0; v < nvars; ++v )
13969 {
13970 var = vars[v];
13971
13974 break;
13975 }
13976 }
13977 else
13978 /* we don't want to go into the next block */
13979 v = nvars;
13980
13981 /* a singleton was found -> perform singleton variable stuffing */
13982 if( v < nvars )
13983 {
13984 assert(singletonstuffing);
13985
13989
13990 tryfixing = TRUE;
13991 nsingletons = 0;
13992 mincondactivity = 0.0;
13993 maxcondactivity = 0.0;
13994
13995 for( v = 0; v < nvars; ++v )
13996 {
13997 var = vars[v];
13998 lb = SCIPvarGetLbGlobal(var);
13999 ub = SCIPvarGetUbGlobal(var);
14001 val = factor * vals[v];
14002
14003 assert(!SCIPisZero(scip, val));
14004
14005 /* the variable is a singleton and continuous */
14008 {
14009 if( SCIPisNegative(scip, obj) && val > 0 )
14010 {
14011 /* case 1: obj < 0 and coef > 0 */
14012 if( SCIPisInfinity(scip, -lb) )
14013 {
14014 tryfixing = FALSE;
14015 break;
14016 }
14017
14018 maxcondactivity += val * lb;
14019 mincondactivity += val * lb;
14020 swapped[v] = FALSE;
14021 ratios[nsingletons] = obj / val;
14022 varpos[nsingletons] = v;
14023 nsingletons++;
14024 }
14025 else if( SCIPisPositive(scip, obj) && val < 0 )
14026 {
14027 /* case 2: obj > 0 and coef < 0 */
14028 if( SCIPisInfinity(scip, ub) )
14029 {
14030 tryfixing = FALSE;
14031 break;
14032 }
14033 /* multiply column by (-1) to become case 1.
14034 * now bounds are swapped: ub := -lb, lb := -ub
14035 */
14036
14037 maxcondactivity += val * ub;
14038 mincondactivity += val * ub;
14039 swapped[v] = TRUE;
14040 ratios[nsingletons] = obj / val;
14041 varpos[nsingletons] = v;
14042 nsingletons++;
14043 }
14044 else if( val > 0 )
14045 {
14046 /* case 3: obj >= 0 and coef >= 0 is handled by duality fixing.
14047 * we only consider the lower bound for the constants
14048 */
14050
14051 if( SCIPisInfinity(scip, -lb) )
14052 {
14053 /* maybe unbounded */
14054 tryfixing = FALSE;
14055 break;
14056 }
14057
14058 maxcondactivity += val * lb;
14059 mincondactivity += val * lb;
14060 }
14061 else
14062 {
14063 /* case 4: obj <= 0 and coef <= 0 is also handled by duality fixing.
14064 * we only consider the upper bound for the constants
14065 */
14067 assert(val < 0);
14068
14069 if( SCIPisInfinity(scip, ub) )
14070 {
14071 /* maybe unbounded */
14072 tryfixing = FALSE;
14073 break;
14074 }
14075
14076 maxcondactivity += val * ub;
14077 mincondactivity += val * ub;
14078 }
14079 }
14080 else
14081 {
14082 /* consider contribution of discrete variables, non-singleton
14083 * continuous variables and variables with more than one lock
14084 */
14085 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14086 {
14087 tryfixing = FALSE;
14088 break;
14089 }
14090
14091 if( val > 0 )
14092 {
14093 maxcondactivity += val * ub;
14094 mincondactivity += val * lb;
14095 }
14096 else
14097 {
14098 maxcondactivity += val * lb;
14099 mincondactivity += val * ub;
14100 }
14101 }
14102 }
14103 if( tryfixing && nsingletons > 0 && (SCIPisGT(scip, rhs, maxcondactivity) || SCIPisLE(scip, rhs, mincondactivity)) )
14104 {
14105 SCIP_Real delta;
14106 SCIP_Bool tightened;
14107#ifdef SCIP_DEBUG
14108 int oldnfixedvars = *nfixedvars;
14109#endif
14110
14111 SCIPsortRealInt(ratios, varpos, nsingletons);
14112
14113 /* verify which singleton continuous variables can be fixed */
14114 for( v = 0; v < nsingletons; ++v )
14115 {
14116 idx = varpos[v];
14117 var = vars[idx];
14118 val = factor * vals[idx];
14119 lb = SCIPvarGetLbGlobal(var);
14120 ub = SCIPvarGetUbGlobal(var);
14121
14123 assert((val < 0) == swapped[idx]);
14124 val = REALABS(val);
14125
14126 /* stop fixing if variable bounds are not finite */
14127 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14128 break;
14129
14133
14134 /* calculate the change in the row activities if this variable changes
14135 * its value from its worst to its best bound
14136 */
14137 if( swapped[idx] )
14138 delta = -(lb - ub) * val;
14139 else
14140 delta = (ub - lb) * val;
14141
14142 assert(!SCIPisNegative(scip, delta));
14143
14144 if( SCIPisLE(scip, delta, rhs - maxcondactivity) )
14145 {
14146 if( swapped[idx] )
14147 {
14148 SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14149 SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14150 }
14151 else
14152 {
14153 SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14154 SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14155 }
14156
14157 if( *cutoff )
14158 break;
14159 if( tightened )
14160 {
14161 (*nfixedvars)++;
14162 }
14163 }
14164 /* @note: we could in theory tighten the bound of the first singleton variable which does not fall into the above case,
14165 * since it cannot be fully fixed. However, this is not needed and should be done by activity-based bound tightening
14166 * anyway after all other continuous singleton columns were fixed; doing it here may introduce numerical
14167 * troubles in case of large bounds.
14168 */
14169 else if( SCIPisLE(scip, rhs, mincondactivity) )
14170 {
14171 if( swapped[idx] )
14172 {
14173 SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14174 SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14175 }
14176 else
14177 {
14178 SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14179 SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14180 }
14181
14182 if( *cutoff )
14183 break;
14184 if( tightened )
14185 {
14186 (*nfixedvars)++;
14187 }
14188 }
14189
14190 maxcondactivity += delta;
14191 mincondactivity += delta;
14192 }
14193
14194#ifdef SCIP_DEBUG
14195 if( *nfixedvars - oldnfixedvars > 0 )
14196 {
14197 SCIPdebugMsg(scip, "### stuffing fixed %d variables\n", *nfixedvars - oldnfixedvars);
14198 }
14199#endif
14200 }
14201
14202 SCIPfreeBufferArray(scip, &swapped);
14203 SCIPfreeBufferArray(scip, &ratios);
14204 SCIPfreeBufferArray(scip, &varpos);
14205 }
14206
14207 /* perform single-variable stuffing:
14208 * for a linear inequality
14209 * a_1 x_1 + a_2 x_2 + ... + a_n x_n <= b
14210 * with a_i > 0 and objective coefficients c_i < 0,
14211 * setting all variables to their upper bound (giving us the maximal activity of the constraint) is worst w.r.t.
14212 * feasibility of the constraint. On the other hand, this gives the best objective function contribution of the
14213 * variables contained in the constraint. The maximal activity should be larger than the rhs, otherwise the constraint
14214 * is redundant.
14215 * Now we are searching for a variable x_k with maximal ratio c_k / a_k (note that all these ratios are negative), so
14216 * that by reducing the value of this variable we reduce the activity of the constraint while having the smallest
14217 * objective deterioration per activity unit. If x_k has no downlocks, is continuous, and can be reduced enough to
14218 * render the constraint feasible, and ALL other variables have only the one uplock installed by the current constraint,
14219 * we can reduce the upper bound of x_k such that the maxactivity equals the rhs and fix all other variables to their
14220 * upper bound.
14221 * Note that the others variables may have downlocks from other constraints, which we do not need to care
14222 * about since we are setting them to the highest possible value. Also, they may be integer or binary, because the
14223 * computed ratio is still a lower bound on the change in the objective caused by reducing those variable to reach
14224 * constraint feasibility. On the other hand, uplocks on x_k from other constraint do no interfer with the method.
14225 * With a slight adjustment, the procedure even works for integral x_k. If (maxactivity - rhs)/val is integral,
14226 * the variable gets an integral value in order to fulfill the constraint tightly, and we can just apply the procedure.
14227 * If (maxactivity - rhs)/val is fractional, we need to check, if overfulfilling the constraint by setting x_k to
14228 * ceil((maxactivity - rhs)/val) is still better than setting x_k to ceil((maxactivity - rhs)/val) - 1 and
14229 * filling the remaining gap in the constraint with the next-best variable. For this, we check that
14230 * c_k * ceil((maxactivity - rhs)/val) is still better than
14231 * c_k * floor((maxactivity - rhs)/val) + c_j * ((maxactivity - rhs) - (floor((maxactivity - rhs)/val) * val))/a_j.
14232 * In this case, the upper bound of x_k is decreased to ub_k - ceil(maxactivity - rhs).
14233 * If there are variables with a_i < 0 and c_i > 0, they are negated to obtain the above form, variables with same
14234 * sign of coefficients in constraint and objective prevent the use of this method.
14235 */
14236 if( singlevarstuffing && !ismaxsettoinfinity )
14237 {
14238 SCIP_Real bestratio = -SCIPinfinity(scip);
14239 SCIP_Real secondbestratio = -SCIPinfinity(scip);
14240 SCIP_Real ratio;
14241 int bestindex = -1;
14242 int bestuplocks = 0;
14243 int bestdownlocks = 1;
14244 int downlocks;
14245 int uplocks;
14246 SCIPdebug( int oldnfixedvars = *nfixedvars; )
14247 SCIPdebug( int oldnchgbds = *nchgbds; )
14248
14249 /* loop over all variables to identify the best and second-best ratio */
14250 for( v = 0; v < nvars; ++v )
14251 {
14252 var = vars[v];
14254 val = factor * vals[v];
14255
14256 assert(!SCIPisZero(scip, val));
14257
14258 ratio = obj / val;
14259
14260 /* if both objective and constraint push the variable to the same direction, we can do nothing here */
14261 if( !SCIPisNegative(scip, ratio) )
14262 {
14263 bestindex = -1;
14264 break;
14265 }
14266
14267 if( val > 0 )
14268 {
14271 }
14272 else
14273 {
14276 }
14277
14278 /* better ratio, update best candidate
14279 * @todo use some tolerance
14280 * @todo check size of domain and updated ratio for integer variables already?
14281 */
14282 if( ratio > bestratio || ( downlocks == 0 && ratio == bestratio && ( bestdownlocks > 0 /*lint !e777*/
14283 || ( !SCIPvarIsIntegral(var) && SCIPvarIsIntegral(vars[bestindex]) ) ) ) )
14284 {
14285 /* best index becomes second-best*/
14286 if( bestindex != -1 )
14287 {
14288 /* second-best index must not have more than 1 uplock */
14289 if( bestuplocks > 1 )
14290 {
14291 bestindex = -1;
14292 break;
14293 }
14294 else
14295 {
14296 secondbestratio = bestratio;
14297 }
14298 }
14299 bestdownlocks = downlocks;
14300 bestuplocks = uplocks;
14301 bestratio = ratio;
14302 bestindex = v;
14303
14304 /* if this variable is the best in the end, we cannot do reductions since it has a downlocks,
14305 * if it is not the best, it has too many uplocks -> not applicable
14306 */
14307 if( bestdownlocks > 0 && bestuplocks > 1 )
14308 {
14309 bestindex = -1;
14310 break;
14311 }
14312 }
14313 else
14314 {
14315 /* non-best index must not have more than 1 uplock */
14316 if( uplocks > 1 )
14317 {
14318 bestindex = -1;
14319 break;
14320 }
14321 /* update second-best ratio */
14322 if( ratio > secondbestratio )
14323 {
14324 secondbestratio = ratio;
14325 }
14326 }
14327 }
14328
14329 /* check if we can apply single variable stuffing */
14330 if( bestindex != -1 && bestdownlocks == 0 )
14331 {
14332 SCIP_Bool tightened = FALSE;
14333 SCIP_Real bounddelta;
14334
14335 var = vars[bestindex];
14337 val = factor * vals[bestindex];
14338 lb = SCIPvarGetLbGlobal(var);
14339 ub = SCIPvarGetUbGlobal(var);
14340 tryfixing = TRUE;
14341
14342 if( val < 0 )
14343 {
14345
14346 /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14347 if( SCIPvarIsIntegral(var) && !SCIPisIntegral(scip, (maxactivity - rhs) / val) )
14348 {
14349 SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/-val);
14350 SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * -val);
14351 assert(SCIPisPositive(scip, activitydelta));
14352
14353 tryfixing = SCIPisLE(scip, obj, -activitydelta * secondbestratio);
14354
14355 bounddelta = SCIPceil(scip, (maxactivity - rhs)/-val);
14356 assert(SCIPisPositive(scip, bounddelta));
14357 }
14358 else
14359 bounddelta = (maxactivity - rhs)/-val;
14360
14361 tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14362
14363 if( tryfixing )
14364 {
14366
14367 if( SCIPisEQ(scip, lb + bounddelta, ub) )
14368 {
14369 SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), lb + bounddelta);
14370 SCIP_CALL( SCIPfixVar(scip, var, lb + bounddelta, cutoff, &tightened) );
14371 }
14372 else
14373 {
14374 SCIPdebugMsg(scip, "tighten the lower bound of <%s> from %g to %g (ub=%g)\n", SCIPvarGetName(var), lb, lb + bounddelta, ub);
14375 SCIP_CALL( SCIPtightenVarLb(scip, var, lb + bounddelta, FALSE, cutoff, &tightened) );
14376 }
14377 }
14378 }
14379 else
14380 {
14382
14383 /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14384 if( SCIPvarIsIntegral(var) && !SCIPisIntegral(scip, (maxactivity - rhs) / val) )
14385 {
14386 SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/val);
14387 SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * val);
14388 assert(SCIPisPositive(scip, activitydelta));
14389
14390 tryfixing = SCIPisLE(scip, -obj, activitydelta * secondbestratio);
14391
14392 bounddelta = SCIPceil(scip, (maxactivity - rhs)/val);
14393 assert(SCIPisPositive(scip, bounddelta));
14394 }
14395 else
14396 bounddelta = (maxactivity - rhs)/val;
14397
14398 tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14399
14400 if( tryfixing )
14401 {
14403
14404 if( SCIPisEQ(scip, ub - bounddelta, lb) )
14405 {
14406 SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), ub - bounddelta);
14407 SCIP_CALL( SCIPfixVar(scip, var, ub - bounddelta, cutoff, &tightened) );
14408 }
14409 else
14410 {
14411 SCIPdebugMsg(scip, "tighten the upper bound of <%s> from %g to %g (lb=%g)\n", SCIPvarGetName(var), ub, ub - bounddelta, lb);
14412 SCIP_CALL( SCIPtightenVarUb(scip, var, ub - bounddelta, FALSE, cutoff, &tightened) );
14413 }
14414 }
14415 }
14416
14417 if( *cutoff )
14418 return SCIP_OKAY;
14419 if( tightened )
14420 {
14422 ++(*nfixedvars);
14423 else
14424 ++(*nchgbds);
14425
14426 SCIPdebugMsg(scip, "cons <%s>: %g <=\n", SCIPconsGetName(cons), factor > 0 ? consdata->lhs : -consdata->rhs);
14427 for( v = 0; v < nvars; ++v )
14428 {
14429 SCIPdebugMsg(scip, "%+g <%s>([%g,%g],%g,[%d,%d],%s)\n", factor * vals[v], SCIPvarGetName(vars[v]),
14433 SCIPvarIsIntegral(vars[v]) ? "I" : "C");
14434 }
14435 SCIPdebugMsg(scip, "<= %g\n", factor > 0 ? consdata->rhs : -consdata->lhs);
14436
14437 for( v = 0; v < nvars; ++v )
14438 {
14439 if( v == bestindex )
14440 continue;
14441
14442 if( factor * vals[v] < 0 )
14443 {
14445 SCIPdebugMsg(scip, "fix <%s> to its lower bound (%g)\n",
14447 SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetLbGlobal(vars[v]), cutoff, &tightened) );
14448 }
14449 else
14450 {
14452 SCIPdebugMsg(scip, "fix <%s> to its upper bound (%g)\n",
14454 SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetUbGlobal(vars[v]), cutoff, &tightened) );
14455 }
14456
14457 if( *cutoff )
14458 return SCIP_OKAY;
14459 if( tightened )
14460 ++(*nfixedvars);
14461 }
14462 SCIPdebug( SCIPdebugMsg(scip, "### new stuffing fixed %d vars, tightened %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds); )
14463 }
14464 }
14465 }
14466
14467 return SCIP_OKAY;
14468}
14469
14470/** applies full dual presolving on variables that only appear in linear constraints */
14471static
14473 SCIP* scip, /**< SCIP data structure */
14474 SCIP_CONS** conss, /**< constraint set */
14475 int nconss, /**< number of constraints */
14476 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14477 int* nchgbds, /**< pointer to count the number of bound changes */
14478 int* nchgvartypes /**< pointer to count the number of variable type changes */
14479 )
14480{
14481 SCIP_Real* redlb;
14482 SCIP_Real* redub;
14483 int* nlocksdown;
14484 int* nlocksup;
14485 SCIP_Bool* isimplint;
14486 SCIP_VAR** origvars;
14487 SCIP_VAR** vars;
14488 SCIP_VAR** conscontvars;
14489 int nvars;
14490 int nbinvars;
14491 int nintvars;
14492 int ncontvars;
14493 int v;
14494 int c;
14495
14496 /* we calculate redundancy bounds with the following meaning:
14497 * redlb[v] == k : if x_v >= k, we can always round x_v down to x_v == k without violating any constraint
14498 * redub[v] == k : if x_v <= k, we can always round x_v up to x_v == k without violating any constraint
14499 * then:
14500 * c_v >= 0 : x_v <= redlb[v] is feasible due to optimality
14501 * c_v <= 0 : x_v >= redub[v] is feasible due to optimality
14502 */
14503
14504 /* Additionally, we detect continuous variables that are implied integral.
14505 * A continuous variable j is implied integral if it only has only +/-1 coefficients,
14506 * and all constraints (including the bounds as trivial constraints) in which:
14507 * c_j > 0: the variable is down-locked,
14508 * c_j < 0: the variable is up-locked,
14509 * c_j = 0: the variable appears
14510 * have, apart from j, only integer variables with integral coefficients and integral sides.
14511 * This is because then, the value of the variable is either determined by one of its bounds or
14512 * by one of these constraints, and in all cases, the value of the variable is integral.
14513 */
14514
14515 assert(scip != NULL);
14516 assert(nconss == 0 || conss != NULL);
14517 assert(nchgbds != NULL);
14519
14520 /* get active variables */
14522 origvars = SCIPgetVars(scip);
14523
14524 /* if the problem is a pure binary program, nothing can be achieved by full dual presolve */
14525 nbinvars = SCIPgetNBinVars(scip);
14526 if( nbinvars == nvars )
14527 return SCIP_OKAY;
14528
14529 /* get number of continuous variables */
14530 ncontvars = SCIPgetNContVars(scip);
14531 nintvars = nvars - ncontvars;
14532
14533 /* copy the variable array since this array might change during the curse of this algorithm */
14534 nvars = nvars - nbinvars;
14535 SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &(origvars[nbinvars]), nvars) );
14536
14537 /* allocate temporary memory */
14540 SCIP_CALL( SCIPallocBufferArray(scip, &nlocksdown, nvars) );
14541 SCIP_CALL( SCIPallocBufferArray(scip, &nlocksup, nvars) );
14542 SCIP_CALL( SCIPallocBufferArray(scip, &isimplint, ncontvars) );
14543 SCIP_CALL( SCIPallocBufferArray(scip, &conscontvars, ncontvars) );
14544
14545 /* initialize redundancy bounds */
14546 for( v = 0; v < nvars; ++v )
14547 {
14549 redlb[v] = SCIPvarGetLbGlobal(vars[v]);
14550 redub[v] = SCIPvarGetUbGlobal(vars[v]);
14551 }
14552 BMSclearMemoryArray(nlocksdown, nvars);
14553 BMSclearMemoryArray(nlocksup, nvars);
14554
14555 /* Initialize isimplint array: variable may be implied integral if rounded to their best bound they are integral
14556 * we better not use SCIPisFeasIntegral() in these checks.
14557 */
14558 for( v = 0; v < ncontvars; v++ )
14559 {
14560 SCIP_VAR* var;
14561 SCIP_Real obj;
14562 SCIP_Real lb;
14563 SCIP_Real ub;
14564
14565 var = vars[v + nintvars - nbinvars];
14567
14568 lb = SCIPvarGetLbGlobal(var);
14569 ub = SCIPvarGetUbGlobal(var);
14570
14572 if( SCIPisZero(scip, obj) )
14573 isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb)) && (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14574 else
14575 {
14576 if( SCIPisPositive(scip, obj) )
14577 isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb));
14578 else
14579 {
14581 isimplint[v] = (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14582 }
14583 }
14584 }
14585
14586 /* scan all constraints */
14587 for( c = 0; c < nconss; ++c )
14588 {
14589 /* we only need to consider constraints that have been locked (i.e., checked constraints or constraints that are
14590 * part of checked disjunctions)
14591 */
14592 if( SCIPconsIsLocked(conss[c]) )
14593 {
14594 SCIP_CONSDATA* consdata;
14595 SCIP_Bool lhsexists;
14596 SCIP_Bool rhsexists;
14597 SCIP_Bool hasimpliedpotential;
14598 SCIP_Bool integralcoefs;
14599 int nlockspos;
14600 int contvarpos;
14601 int nconscontvars;
14602 int i;
14603
14604 consdata = SCIPconsGetData(conss[c]);
14605 assert(consdata != NULL);
14606
14607 /* get number of times the constraint was locked */
14608 nlockspos = SCIPconsGetNLocksPos(conss[c]);
14609
14610 /* we do not want to include constraints with locked negation (this would be too weird) */
14611 if( SCIPconsGetNLocksNeg(conss[c]) > 0 )
14612 {
14613 /* mark all non-implied continuous variables */
14614 for( i = 0; i < consdata->nvars; ++i )
14615 {
14616 SCIP_VAR* var;
14617
14618 var = consdata->vars[i];
14619 if( !SCIPvarIsIntegral(var) )
14620 {
14621 int contv;
14622 contv = SCIPvarGetProbindex(var) - nintvars;
14623 assert(0 <= contv && contv < ncontvars); /* variable should be active due to applyFixings() */
14624 isimplint[contv] = FALSE;
14625 }
14626 }
14627 continue;
14628 }
14629
14630 /* check for existing sides */
14631 lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
14632 rhsexists = !SCIPisInfinity(scip, consdata->rhs);
14633
14634 /* count locks and update redundancy bounds */
14635 contvarpos = -1;
14636 nconscontvars = 0;
14637 hasimpliedpotential = FALSE;
14638 integralcoefs = !SCIPconsIsModifiable(conss[c]);
14639
14640 for( i = 0; i < consdata->nvars; ++i )
14641 {
14642 SCIP_VAR* var;
14643 SCIP_Real val;
14644 SCIP_Real minresactivity;
14645 SCIP_Real maxresactivity;
14646 SCIP_Real newredlb;
14647 SCIP_Real newredub;
14648 SCIP_Bool ismintight;
14649 SCIP_Bool ismaxtight;
14650 SCIP_Bool isminsettoinfinity;
14651 SCIP_Bool ismaxsettoinfinity;
14652 int arrayindex;
14653
14654 var = consdata->vars[i];
14655 assert(var != NULL);
14656 val = consdata->vals[i];
14657 assert(!SCIPisZero(scip, val));
14658
14659 /* check if still all integer variables have integral coefficients */
14660 if( SCIPvarIsIntegral(var) )
14661 integralcoefs = integralcoefs && SCIPisIntegral(scip, val);
14662
14663 /* we do not need to process binary variables */
14664 if( SCIPvarIsBinary(var) )
14665 continue;
14666
14667 if( SCIPconsIsModifiable(conss[c]) )
14668 {
14669 minresactivity = -SCIPinfinity(scip);
14670 maxresactivity = SCIPinfinity(scip);
14671 isminsettoinfinity = TRUE;
14672 ismaxsettoinfinity = TRUE;
14673 }
14674 else
14675 {
14676 /* calculate residual activity bounds if variable would be fixed to zero */
14677 consdataGetGlbActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
14678 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
14679
14680 /* We called consdataGetGlbActivityResiduals() saying that we do not need a good relaxation,
14681 * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
14682 * This is needed, because we do not want to rely on relaxed finite resactivities.
14683 */
14684 assert((ismintight || isminsettoinfinity) && (ismaxtight || ismaxsettoinfinity));
14685
14686 /* check minresactivity for reliability */
14687 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
14688 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, TRUE);
14689
14690 /* check maxresactivity for reliability */
14691 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
14692 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, TRUE);
14693 }
14694
14695 arrayindex = SCIPvarGetProbindex(var) - nbinvars;
14696
14697 assert(0 <= arrayindex && arrayindex < nvars); /* variable should be active due to applyFixings() */
14698
14699 newredlb = redlb[arrayindex];
14700 newredub = redub[arrayindex];
14701 if( val > 0.0 )
14702 {
14703 if( lhsexists )
14704 {
14705 /* lhs <= d*x + a*y, d > 0 -> redundant in y if x >= (lhs - min{a*y})/d */
14706 nlocksdown[arrayindex] += nlockspos;
14707 newredlb = (isminsettoinfinity ? SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14708 }
14709 if( rhsexists )
14710 {
14711 /* d*x + a*y <= rhs, d > 0 -> redundant in y if x <= (rhs - max{a*y})/d */
14712 nlocksup[arrayindex] += nlockspos;
14713 newredub = (ismaxsettoinfinity ? -SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14714 }
14715 }
14716 else
14717 {
14718 if( lhsexists )
14719 {
14720 /* lhs <= d*x + a*y, d < 0 -> redundant in y if x <= (lhs - min{a*y})/d */
14721 nlocksup[arrayindex] += nlockspos;
14722 newredub = (isminsettoinfinity ? -SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14723 }
14724 if( rhsexists )
14725 {
14726 /* d*x + a*y <= rhs, d < 0 -> redundant in y if x >= (rhs - max{a*y})/d */
14727 nlocksdown[arrayindex] += nlockspos;
14728 newredlb = (ismaxsettoinfinity ? SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14729 }
14730 }
14731
14732 /* if the variable is integer, we have to round the value to the next integral value */
14733 if( SCIPvarIsIntegral(var) )
14734 {
14735 if( !SCIPisInfinity(scip, newredlb) )
14736 newredlb = SCIPceil(scip, newredlb);
14737 if( !SCIPisInfinity(scip, -newredub) )
14738 newredub = SCIPfloor(scip, newredub);
14739 }
14740
14741 /* update redundancy bounds */
14742 redlb[arrayindex] = MAX(redlb[arrayindex], newredlb);
14743 redub[arrayindex] = MIN(redub[arrayindex], newredub);
14744
14745 /* collect the continuous variables of the constraint */
14746 if( !SCIPvarIsIntegral(var) )
14747 {
14748 int contv;
14749
14750 assert(nconscontvars < ncontvars);
14751 contvarpos = i;
14752 conscontvars[nconscontvars] = var;
14753 nconscontvars++;
14754
14755 contv = SCIPvarGetProbindex(var) - nintvars;
14756 assert(0 <= contv && contv < ncontvars);
14757 hasimpliedpotential = hasimpliedpotential || isimplint[contv];
14758 }
14759 }
14760
14761 /* update implied integrality status of continuous variables */
14762 if( hasimpliedpotential )
14763 {
14764 if( nconscontvars > 1 || !integralcoefs )
14765 {
14766 /* there is more than one continuous variable or the integer variables have fractional coefficients:
14767 * none of the continuous variables is implied integral
14768 */
14769 for( i = 0; i < nconscontvars; i++ )
14770 {
14771 int contv;
14772 contv = SCIPvarGetProbindex(conscontvars[i]) - nintvars;
14773 assert(0 <= contv && contv < ncontvars);
14774 isimplint[contv] = FALSE;
14775 }
14776 }
14777 else
14778 {
14779 SCIP_VAR* var;
14780 SCIP_Real val;
14781 SCIP_Real absval;
14782 int contv;
14783
14784 /* there is exactly one continuous variable and the integer variables have integral coefficients:
14785 * this is the interesting case, and we have to check whether the coefficient is +/-1 and the corresponding
14786 * side(s) of the constraint is integral
14787 */
14788 assert(nconscontvars == 1);
14789 assert(0 <= contvarpos && contvarpos < consdata->nvars);
14790 var = consdata->vars[contvarpos];
14791 val = consdata->vals[contvarpos];
14792 contv = SCIPvarGetProbindex(var) - nintvars;
14793 assert(0 <= contv && contv < ncontvars);
14794 assert(isimplint[contv]);
14795
14796 absval = REALABS(val);
14797 if( !SCIPisEQ(scip, absval, 1.0) )
14798 isimplint[contv] = FALSE;
14799 else
14800 {
14801 SCIP_Real obj;
14802
14804 if( obj * val >= 0.0 && lhsexists )
14805 {
14806 /* the variable may be blocked by the constraint's left hand side */
14807 isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->lhs);
14808 }
14809 if( obj * val <= 0.0 && rhsexists )
14810 {
14811 /* the variable may be blocked by the constraint's left hand side */
14812 isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->rhs);
14813 }
14814 }
14815 }
14816 }
14817 }
14818 }
14819
14820 /* check if any bounds can be tightened due to optimality */
14821 for( v = 0; v < nvars; ++v )
14822 {
14823 SCIP_VAR* var;
14824 SCIP_Real obj;
14825 SCIP_Bool infeasible;
14826 SCIP_Bool tightened;
14827
14831
14832 var = vars[v];
14834 if( !SCIPisPositive(scip, -obj) )
14835 {
14836 /* making the variable as small as possible does not increase the objective:
14837 * check if all down locks of the variables are due to linear constraints;
14838 * if variable is cost neutral and only upper bounded non-positively or negative largest bound to make
14839 * constraints redundant is huge, we better do nothing for numerical reasons
14840 */
14843 && !SCIPisHugeValue(scip, -redlb[v])
14844 && redlb[v] < SCIPvarGetUbGlobal(var) )
14845 {
14846 SCIP_Real ub;
14847
14848 /* if x_v >= redlb[v], we can always round x_v down to x_v == redlb[v] without violating any constraint
14849 * -> tighten upper bound to x_v <= redlb[v]
14850 */
14851 SCIPdebugMsg(scip, "variable <%s> only locked down in linear constraints: dual presolve <%s>[%.15g,%.15g] <= %.15g\n",
14853 redlb[v]);
14854 SCIP_CALL( SCIPtightenVarUb(scip, var, redlb[v], FALSE, &infeasible, &tightened) );
14855 assert(!infeasible);
14856
14857 ub = SCIPvarGetUbGlobal(var);
14858 redub[v] = MIN(redub[v], ub);
14859 if( tightened )
14860 (*nchgbds)++;
14861 }
14862 }
14863 if( !SCIPisPositive(scip, obj) )
14864 {
14865 /* making the variable as large as possible does not increase the objective:
14866 * check if all up locks of the variables are due to linear constraints;
14867 * if variable is cost neutral and only lower bounded non-negatively or positive smallest bound to make
14868 * constraints redundant is huge, we better do nothing for numerical reasons
14869 */
14872 && !SCIPisHugeValue(scip, redub[v])
14873 && redub[v] > SCIPvarGetLbGlobal(var) )
14874 {
14875 SCIP_Real lb;
14876
14877 /* if x_v <= redub[v], we can always round x_v up to x_v == redub[v] without violating any constraint
14878 * -> tighten lower bound to x_v >= redub[v]
14879 */
14880 SCIPdebugMsg(scip, "variable <%s> only locked up in linear constraints: dual presolve <%s>[%.15g,%.15g] >= %.15g\n",
14882 redub[v]);
14883 SCIP_CALL( SCIPtightenVarLb(scip, var, redub[v], FALSE, &infeasible, &tightened) );
14884 assert(!infeasible);
14885
14886 lb = SCIPvarGetLbGlobal(var);
14887 redlb[v] = MAX(redlb[v], lb);
14888 if( tightened )
14889 (*nchgbds)++;
14890 }
14891 }
14892 }
14893
14894 /* @TODO: improve range names */
14895 /* declare continuous variables implied integral */
14896 for( v = nintvars - nbinvars; v < nvars; ++v )
14897 {
14898 SCIP_VAR* var;
14899 SCIP_Bool infeasible;
14900
14901 var = vars[v];
14902 assert(var != NULL);
14903
14907 assert(0 <= v - nintvars + nbinvars && v - nintvars + nbinvars < ncontvars);
14908
14909 /* @TODO: relax lock conditions */
14910 /* we can only conclude implied integrality if the variable appears in no other constraint */
14911 if( isimplint[v - nintvars + nbinvars]
14913 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v] )
14914 {
14915 /* since we locally copied the variable array we can change the variable type immediately */
14918 (*nchgvartypes)++;
14919 if( infeasible )
14920 {
14921 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
14922 *cutoff = TRUE;
14923
14924 break;
14925 }
14926
14927 SCIPdebugMsg(scip, "dual presolve: declare continuous variable <%s>[%g,%g] implied integral\n",
14929 }
14930 }
14931
14932 /* free temporary memory */
14933 SCIPfreeBufferArray(scip, &conscontvars);
14934 SCIPfreeBufferArray(scip, &isimplint);
14935 SCIPfreeBufferArray(scip, &nlocksup);
14936 SCIPfreeBufferArray(scip, &nlocksdown);
14937 SCIPfreeBufferArray(scip, &redub);
14938 SCIPfreeBufferArray(scip, &redlb);
14939
14941
14942 return SCIP_OKAY;
14943}
14944
14945/** helper function to enforce constraints */
14946static
14948 SCIP* scip, /**< SCIP data structure */
14949 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
14950 SCIP_CONS** conss, /**< constraints to process */
14951 int nconss, /**< number of constraints */
14952 int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
14953 SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
14954 SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
14955 )
14956{
14957 SCIP_CONSHDLRDATA* conshdlrdata;
14958 SCIP_Bool checkrelmaxabs;
14959 SCIP_Bool violated;
14961 int c;
14962
14963 assert(scip != NULL);
14964 assert(conshdlr != NULL);
14965 assert(result != NULL);
14966
14968
14969 conshdlrdata = SCIPconshdlrGetData(conshdlr);
14970 assert(conshdlrdata != NULL);
14971
14972 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
14973
14974 SCIPdebugMsg(scip, "Enforcement method of linear constraints for %s solution\n", sol == NULL ? "LP" : "relaxation");
14975
14976 /* check for violated constraints
14977 * LP is processed at current node -> we can add violated linear constraints to the SCIP_LP
14978 */
14980
14981 /* check all useful linear constraints for feasibility */
14982 for( c = 0; c < nusefulconss; ++c )
14983 {
14984 SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
14985
14986 if( violated )
14987 {
14988 /* insert LP row as cut */
14989 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
14990 if ( cutoff )
14992 else
14994 }
14995 }
14996
14997 /* check all obsolete linear constraints for feasibility */
14998 for( c = nusefulconss; c < nconss && *result == SCIP_FEASIBLE; ++c )
14999 {
15000 SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15001
15002 if( violated )
15003 {
15004 /* insert LP row as cut */
15005 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15006 if ( cutoff )
15008 else
15010 }
15011 }
15012
15013 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
15014
15015 return SCIP_OKAY;
15016}
15017
15018/** adds symmetry information of constraint to a symmetry detection graph */
15019static
15021 SCIP* scip, /**< SCIP pointer */
15022 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
15023 SCIP_CONS* cons, /**< constraint */
15024 SYM_GRAPH* graph, /**< symmetry detection graph */
15025 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
15026 )
15027{
15028 SCIP_CONSDATA* consdata;
15029 SCIP_VAR** vars;
15030 SCIP_Real* vals;
15031 SCIP_Real constant = 0.0;
15032 SCIP_Real lhs;
15033 SCIP_Real rhs;
15034 int nlocvars;
15035 int nvars;
15036 int i;
15037
15038 assert(scip != NULL);
15039 assert(cons != NULL);
15040 assert(graph != NULL);
15041 assert(success != NULL);
15042
15043 consdata = SCIPconsGetData(cons);
15044 assert(consdata != NULL);
15045
15046 /* get active variables of the constraint */
15048 nlocvars = consdata->nvars;
15049
15052
15053 for( i = 0; i < nlocvars; ++i )
15054 {
15055 vars[i] = consdata->vars[i];
15056 vals[i] = consdata->vals[i];
15057 }
15058
15059 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
15060 lhs = consdata->lhs - constant;
15061 rhs = consdata->rhs - constant;
15062
15063 /* if rhs is infinite, normalize rhs to be finite to make sure that different encodings
15064 * of the same constraint are rated as equal
15065 */
15066 if ( SCIPisInfinity(scip, rhs) )
15067 {
15068 SCIP_Real tmp;
15069 assert(!SCIPisInfinity(scip, -lhs));
15070
15071 for( i = 0; i < nlocvars; ++i )
15072 vals[i] *= -1;
15073 tmp = rhs;
15074 rhs = -lhs;
15075 lhs = -tmp;
15076 }
15077
15079 cons, lhs, rhs, success) );
15080
15081 SCIPfreeBufferArray(scip, &vals);
15083
15084 return SCIP_OKAY;
15085}
15086
15087/*
15088 * Callback methods of constraint handler
15089 */
15090
15091/** copy method for constraint handler plugins (called when SCIP copies plugins) */
15092static
15093SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
15094{ /*lint --e{715}*/
15095 assert(scip != NULL);
15096 assert(conshdlr != NULL);
15097
15099
15100 /* call inclusion method of constraint handler */
15102
15103 *valid = TRUE;
15104
15105 return SCIP_OKAY;
15106}
15107
15108/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
15109static
15110SCIP_DECL_CONSFREE(consFreeLinear)
15111{ /*lint --e{715}*/
15112 SCIP_CONSHDLRDATA* conshdlrdata;
15113
15114 assert(scip != NULL);
15115 assert(conshdlr != NULL);
15116
15118
15119 /* free constraint handler data */
15120 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15121 assert(conshdlrdata != NULL);
15122
15123 conshdlrdataFree(scip, &conshdlrdata);
15124
15125 SCIPconshdlrSetData(conshdlr, NULL);
15126
15127 return SCIP_OKAY;
15128}
15129
15130
15131/** initialization method of constraint handler (called after problem was transformed) */
15132static
15133SCIP_DECL_CONSINIT(consInitLinear)
15134{
15135 SCIP_CONSHDLRDATA* conshdlrdata;
15136 int c;
15137
15138 assert(scip != NULL);
15139
15140 /* check for event handler */
15141 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15142 assert(conshdlrdata != NULL);
15143 assert(conshdlrdata->eventhdlr != NULL);
15144 assert(nconss == 0 || conss != NULL);
15145
15146 conshdlrdata->naddconss = 0;
15147
15148 /* catch events for the constraints */
15149 for( c = 0; c < nconss; ++c )
15150 {
15151 /* catch all events */
15152 SCIP_CALL( consCatchAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15153 }
15154
15155 return SCIP_OKAY;
15156}
15157
15158
15159/** deinitialization method of constraint handler (called before transformed problem is freed) */
15160static
15161SCIP_DECL_CONSEXIT(consExitLinear)
15162{
15163 SCIP_CONSHDLRDATA* conshdlrdata;
15164 int c;
15165
15166 assert(scip != NULL);
15167
15168 /* check for event handler */
15169 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15170 assert(conshdlrdata != NULL);
15171 assert(conshdlrdata->eventhdlr != NULL);
15172
15173 /* drop events for the constraints */
15174 for( c = nconss - 1; c >= 0; --c )
15175 {
15176 SCIP_CONSDATA* consdata;
15177
15178 consdata = SCIPconsGetData(conss[c]);
15179 assert(consdata != NULL);
15180
15181 if( consdata->eventdata != NULL )
15182 {
15183 /* drop all events */
15184 SCIP_CALL( consDropAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15185 assert(consdata->eventdata == NULL);
15186 }
15187 }
15188
15189 return SCIP_OKAY;
15190}
15191
15192/** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15193static
15195 SCIP* scip, /**< SCIP data structure */
15196 SCIP_Real lhs, /**< left hand side */
15197 SCIP_Real rhs /**< right hand side */
15198 )
15199{
15200 assert(scip != NULL);
15201
15202 return !(SCIPisEQ(scip, lhs, rhs) || SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs) );
15203}
15204
15205/** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15206static
15208 SCIP* scip, /**< SCIP data structure */
15209 SCIP_Real x /**< value */
15210 )
15211{
15212 assert(scip != NULL);
15213
15214 return (!SCIPisInfinity(scip, x) && !SCIPisNegative(scip, x) && SCIPisIntegral(scip, x));
15215}
15216
15217/** performs linear constraint type classification as used for MIPLIB
15218 *
15219 * iterates through all linear constraints and stores relevant statistics in the linear constraint statistics \p linconsstats.
15220 *
15221 * @note only constraints are iterated that belong to the linear constraint handler. If the problem has been presolved already,
15222 * constraints that were upgraded to more special types such as, e.g., varbound constraints, will not be shown correctly anymore.
15223 * Similarly, if specialized constraints were created through the API, these are currently not present.
15224 */
15226 SCIP* scip, /**< SCIP data structure */
15227 SCIP_LINCONSSTATS* linconsstats /**< linear constraint type classification */
15228 )
15229{
15230 int c;
15231 SCIP_CONSHDLR* conshdlr;
15232 SCIP_CONS** conss;
15233 int nconss;
15234
15235 assert(scip != NULL);
15236 assert(linconsstats != NULL);
15237 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
15238 assert(conshdlr != NULL);
15239
15241 {
15242 conss = SCIPgetConss(scip);
15243 nconss = SCIPgetNConss(scip);
15244 }
15245 else
15246 {
15247 conss = SCIPconshdlrGetConss(conshdlr);
15248 nconss = SCIPconshdlrGetNConss(conshdlr);
15249 }
15250
15251 /* reset linear constraint type classification */
15252 SCIPlinConsStatsReset(linconsstats);
15253
15254 /* loop through all constraints */
15255 for( c = 0; c < nconss; c++ )
15256 {
15257 SCIP_CONS* cons;
15258 SCIP_CONSDATA* consdata;
15259 SCIP_Real lhs;
15260 SCIP_Real rhs;
15261 int i;
15262
15263 /* get constraint */
15264 cons = conss[c];
15265 assert(cons != NULL);
15266
15267 /* skip constraints that are not handled by the constraint handler */
15268 if( SCIPconsGetHdlr(cons) != conshdlr )
15269 continue;
15270
15271 /* get constraint data */
15272 consdata = SCIPconsGetData(cons);
15273 assert(consdata != NULL);
15274 rhs = consdata->rhs;
15275 lhs = consdata->lhs;
15276
15277 /* merge multiples and delete variables with zero coefficient */
15278 SCIP_CALL( mergeMultiples(scip, cons) );
15279 for( i = 0; i < consdata->nvars; i++ )
15280 {
15281 assert(!SCIPisZero(scip, consdata->vals[i]));
15282 }
15283
15284 /* is constraint of type SCIP_CONSTYPE_EMPTY? */
15285 if( consdata->nvars == 0 )
15286 {
15287 SCIPdebugMsg(scip, "classified as EMPTY: ");
15290
15291 continue;
15292 }
15293
15294 /* is constraint of type SCIP_CONSTYPE_FREE? */
15295 if( SCIPisInfinity(scip, rhs) && SCIPisInfinity(scip, -lhs) )
15296 {
15297 SCIPdebugMsg(scip, "classified as FREE: ");
15300
15301 continue;
15302 }
15303
15304 /* is constraint of type SCIP_CONSTYPE_SINGLETON? */
15305 if( consdata->nvars == 1 )
15306 {
15307 SCIPdebugMsg(scip, "classified as SINGLETON: ");
15310
15311 continue;
15312 }
15313
15314 /* is constraint of type SCIP_CONSTYPE_AGGREGATION? */
15315 if( consdata->nvars == 2 && SCIPisEQ(scip, lhs, rhs) )
15316 {
15317 SCIPdebugMsg(scip, "classified as AGGREGATION: ");
15320
15321 continue;
15322 }
15323
15324 /* is constraint of type SCIP_CONSTYPE_{VARBOUND,PRECEDENCE}? */
15325 if( consdata->nvars == 2 )
15326 {
15327 /* precedence constraints have same variable type and same absolute coefficient with opposite sign */
15328 if( SCIPvarGetType(consdata->vars[0]) == SCIPvarGetType(consdata->vars[1])
15329 && SCIPisEQ(scip, consdata->vals[0], -consdata->vals[1]) )
15330 {
15331 SCIPdebugMsg(scip, "classified as PRECEDENCE: ");
15334
15335 continue;
15336 }
15337 /* varbound constraints have otherwise a binary variable */
15338 else if( SCIPvarGetType(consdata->vars[0]) == SCIP_VARTYPE_BINARY
15339 || SCIPvarGetType(consdata->vars[1]) == SCIP_VARTYPE_BINARY )
15340 {
15341 SCIPdebugMsg(scip, "classified as VARBOUND: ");
15344
15345 continue;
15346 }
15347 }
15348
15349 /* is constraint of type SCIP_CONSTYPE_{SETPARTITION, SETPACKING, SETCOVERING, CARDINALITY, INVKNAPSACK}? */
15350 {
15351 SCIP_Real scale;
15352 SCIP_Real b;
15353 SCIP_Bool unmatched;
15354 int nnegbinvars;
15355
15356 unmatched = FALSE;
15357 nnegbinvars = 0;
15358
15359 scale = REALABS(consdata->vals[0]);
15360
15361 /* scan through variables and detect if all variables are binary and have a coefficient +/-1 */
15362 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15363 {
15364 unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15365 unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15366 unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15367 unmatched = unmatched || !SCIPisEQ(scip, REALABS(consdata->vals[i]), scale);
15368
15369 if( consdata->vals[i] < 0.0 )
15370 nnegbinvars++;
15371 }
15372
15373 if( !unmatched )
15374 {
15375 if( SCIPisEQ(scip, lhs, rhs) )
15376 {
15377 b = rhs/scale + nnegbinvars;
15378 if( SCIPisEQ(scip, 1.0, b) )
15379 {
15380 SCIPdebugMsg(scip, "classified as SETPARTITION: ");
15383
15384 continue;
15385 }
15386 else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15387 {
15388 SCIPdebugMsg(scip, "classified as CARDINALITY: ");
15391
15392 continue;
15393 }
15394 }
15395
15396 /* compute right hand side divided by scale */
15397 if( !SCIPisInfinity(scip, rhs) )
15398 b = rhs/scale + nnegbinvars;
15399 else
15400 b = SCIPinfinity(scip);
15401
15402 if( SCIPisEQ(scip, 1.0, b) )
15403 {
15404 SCIPdebugMsg(scip, "classified as SETPACKING: ");
15407
15408 /* relax right hand side to prevent further classifications */
15409 rhs = SCIPinfinity(scip);
15410 }
15411 else if( !SCIPisInfinity(scip, b) && SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15412 {
15413 SCIPdebugMsg(scip, "classified as INVKNAPSACK: ");
15415
15417
15418 /* relax right hand side to prevent further classifications */
15419 rhs = SCIPinfinity(scip);
15420 }
15421
15422 if( !SCIPisInfinity(scip, lhs) )
15423 b = lhs/scale + nnegbinvars;
15424 else
15425 b = SCIPinfinity(scip);
15426
15427 if( SCIPisEQ(scip, 1.0, b) )
15428 {
15429 SCIPdebugMsg(scip, "classified as SETCOVERING: ");
15432
15433 /* relax left hand side to prevent further classifications */
15434 lhs = -SCIPinfinity(scip);
15435 }
15436
15437 /* if both sides are infinite at this point, no further classification is necessary for this constraint */
15438 if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
15439 continue;
15440 }
15441 }
15442
15443 /* is constraint of type SCIP_CONSTYPE_{EQKNAPSACK, BINPACKING, KNAPSACK}? */
15444 /* @todo If coefficients or rhs are not integral, we currently do not check
15445 * if the constraint could be scaled (finitely), such that they are.
15446 */
15447 {
15448 SCIP_Real b;
15449 SCIP_Bool unmatched;
15450
15451 b = rhs;
15452 unmatched = FALSE;
15453 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15454 {
15455 unmatched = unmatched || !SCIPvarIsIntegral(consdata->vars[i]);
15456 unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15457 unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15458 unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15459
15460 if( SCIPisNegative(scip, consdata->vals[i]) )
15461 b -= consdata->vals[i];
15462 }
15463 unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15464
15465 if( !unmatched )
15466 {
15467 if( SCIPisEQ(scip, lhs, rhs) )
15468 {
15469 SCIPdebugMsg(scip, "classified as EQKNAPSACK: ");
15471
15473
15474 continue;
15475 }
15476 else
15477 {
15478 SCIP_Bool matched;
15479
15480 matched = FALSE;
15481 for( i = 0; i < consdata->nvars && !matched; i++ )
15482 {
15483 matched = matched || SCIPisEQ(scip, b, REALABS(consdata->vals[i]));
15484 }
15485
15486 SCIPdebugMsg(scip, "classified as %s: ", matched ? "BINPACKING" : "KNAPSACK");
15489 }
15490
15491 /* check if finite left hand side allows for a second classification, relax already used right hand side */
15492 if( SCIPisInfinity(scip, -lhs) )
15493 continue;
15494 else
15495 rhs = SCIPinfinity(scip);
15496 }
15497 }
15498
15499 /* is constraint of type SCIP_CONSTYPE_{INTKNAPSACK}? */
15500 {
15501 SCIP_Real b;
15502 SCIP_Bool unmatched;
15503
15504 unmatched = FALSE;
15505
15506 b = rhs;
15507 unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15508
15509 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15510 {
15511 unmatched = unmatched || !SCIPvarIsIntegral(consdata->vars[i]);
15512 unmatched = unmatched || SCIPisNegative(scip, SCIPvarGetLbGlobal(consdata->vars[i]));
15513 unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15514 unmatched = unmatched || SCIPisNegative(scip, consdata->vals[i]);
15515 }
15516
15517 if( !unmatched )
15518 {
15519 SCIPdebugMsg(scip, "classified as INTKNAPSACK: ");
15522
15523 /* check if finite left hand side allows for a second classification, relax already used right hand side */
15524 if( SCIPisInfinity(scip, -lhs) )
15525 continue;
15526 else
15527 rhs = SCIPinfinity(scip);
15528 }
15529 }
15530
15531 /* is constraint of type SCIP_CONSTYPE_{MIXEDBINARY}? */
15532 {
15533 SCIP_Bool unmatched;
15534
15535 unmatched = FALSE;
15536 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15537 {
15538 if( SCIPvarIsIntegral(consdata->vars[i])
15539 && ( SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0)
15540 || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0) ) )
15541 unmatched = TRUE;
15542 }
15543
15544 if( !unmatched )
15545 {
15546 SCIPdebugMsg(scip, "classified as MIXEDBINARY (%d): ", isRangedRow(scip, lhs, rhs) ? 2 : 1);
15549
15550 continue;
15551 }
15552 }
15553
15554 /* no special structure detected */
15555 SCIPdebugMsg(scip, "classified as GENERAL: ");
15557 SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_GENERAL, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15558 }
15559
15560 return SCIP_OKAY;
15561}
15562
15563
15564/** presolving deinitialization method of constraint handler (called after presolving has been finished) */
15565static
15566SCIP_DECL_CONSEXITPRE(consExitpreLinear)
15567{ /*lint --e{715}*/
15568 int c;
15569#ifdef SCIP_STATISTIC
15570 SCIP_CONSHDLRDATA* conshdlrdata;
15571 int ngoodconss;
15572 int nallconss;
15573#endif
15574
15575 /* delete all linear constraints that were upgraded to a more specific constraint type;
15576 * make sure, only active variables remain in the remaining constraints
15577 */
15578 assert(scip != NULL);
15579
15580#ifdef SCIP_STATISTIC
15581 /* count number of well behaved linear constraints */
15582 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15583 assert(conshdlrdata != NULL);
15584
15585 ngoodconss = 0;
15586 nallconss = 0;
15587
15588 for( c = 0; c < nconss; ++c )
15589 {
15590 SCIP_CONSDATA* consdata;
15591
15592 if( SCIPconsIsDeleted(conss[c]) )
15593 continue;
15594
15595 consdata = SCIPconsGetData(conss[c]);
15596 assert(consdata != NULL);
15597
15598 if( consdata->upgraded )
15599 continue;
15600
15601 nallconss++;
15602
15604
15605 if( SCIPisLT(scip, consdata->maxactdelta, conshdlrdata->maxeasyactivitydelta) )
15606 ngoodconss++;
15607 }
15608 if( nallconss )
15609 {
15610 SCIPstatisticMessage("below threshold: %d / %d ratio= %g\n", ngoodconss, nallconss, (100.0 * ngoodconss / nallconss));
15611 }
15612#endif
15613
15614 for( c = 0; c < nconss; ++c )
15615 {
15616 SCIP_CONSDATA* consdata;
15617
15618 if( SCIPconsIsDeleted(conss[c]) )
15619 continue;
15620
15621 consdata = SCIPconsGetData(conss[c]);
15622 assert(consdata != NULL);
15623
15624 if( consdata->upgraded )
15625 {
15626 /* this is no problem reduction, because the upgraded constraint was added to the problem before, and the
15627 * (redundant) linear constraint was only kept in order to support presolving the the linear constraint handler
15628 */
15629 SCIP_CALL( SCIPdelCons(scip, conss[c]) );
15630 }
15631 else
15632 {
15633 /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */
15634 SCIP_CALL( applyFixings(scip, conss[c], NULL) );
15635 }
15636 }
15637
15638 return SCIP_OKAY;
15639}
15640
15641/** solving process initialization method of constraint handler */
15642static
15643SCIP_DECL_CONSINITSOL(consInitsolLinear)
15644{ /*lint --e{715}*/
15645 /* add nlrow representation to NLP, if NLP had been constructed */
15647 {
15648 int c;
15649 for( c = 0; c < nconss; ++c )
15650 {
15651 SCIP_CALL( addNlrow(scip, conss[c]) );
15652 }
15653 }
15654
15655 return SCIP_OKAY;
15656}
15657
15658/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
15659static
15660SCIP_DECL_CONSEXITSOL(consExitsolLinear)
15661{ /*lint --e{715}*/
15662 int c;
15663
15664 assert(scip != NULL);
15665
15666 /* release the rows and nlrows of all constraints */
15667 for( c = 0; c < nconss; ++c )
15668 {
15669 SCIP_CONSDATA* consdata;
15670
15671 consdata = SCIPconsGetData(conss[c]);
15672 assert(consdata != NULL);
15673
15674 if( consdata->row != NULL )
15675 {
15676 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
15677 }
15678
15679 if( consdata->nlrow != NULL )
15680 {
15681 SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
15682 }
15683 }
15684
15685 /* if this is a restart, convert cutpool rows into linear constraints */
15686 if( restart )
15687 {
15688 int ncutsadded;
15689
15690 ncutsadded = 0;
15691
15692 /* create out of all active cuts in cutpool linear constraints */
15693 SCIP_CALL( SCIPconvertCutsToConss(scip, NULL, NULL, TRUE, &ncutsadded) );
15694
15695 if( ncutsadded > 0 )
15696 {
15698 "(restart) converted %d cuts from the global cut pool into linear constraints\n", ncutsadded);
15699 /* an extra blank line should be printed separately since the buffer message handler only handles up to one
15700 * line correctly
15701 */
15703 }
15704 }
15705
15706 return SCIP_OKAY;
15707}
15708
15709
15710/** constraint activation notification method of constraint handler */
15711static
15712SCIP_DECL_CONSACTIVE(consActiveLinear)
15713{ /*lint --e{715}*/
15714 assert(cons != NULL);
15715
15717 {
15718 SCIP_CALL( addNlrow(scip, cons) );
15719 }
15720
15721 return SCIP_OKAY;
15722}
15723
15724/** constraint deactivation notification method of constraint handler */
15725static
15726SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
15727{ /*lint --e{715}*/
15728 SCIP_CONSDATA* consdata;
15729
15730 assert(scip != NULL);
15731 assert(conshdlr != NULL);
15732 assert(cons != NULL );
15733
15735
15736 /* get constraint data */
15737 consdata = SCIPconsGetData(cons);
15738 assert(consdata != NULL);
15739
15740 if( SCIPconsIsDeleted(cons) )
15741 {
15742 SCIP_CONSHDLRDATA* conshdlrdata;
15743
15744 /* check for event handler */
15745 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15746 assert(conshdlrdata != NULL);
15747 assert(conshdlrdata->eventhdlr != NULL);
15748
15749 /* free event data */
15750 if( consdata->eventdata != NULL )
15751 {
15752 /* drop bound change events of variables */
15753 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15754 }
15755 assert(consdata->eventdata == NULL);
15756 }
15757
15758 /* remove row from NLP, if still in solving
15759 * if we are in exitsolve, the whole NLP will be freed anyway
15760 */
15761 if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
15762 {
15763 SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
15764 }
15765
15766 return SCIP_OKAY;
15767}
15768
15769
15770/** frees specific constraint data */
15771static
15772SCIP_DECL_CONSDELETE(consDeleteLinear)
15773{ /*lint --e{715}*/
15774 assert(scip != NULL);
15775 assert(conshdlr != NULL);
15776
15778
15779 if( (*consdata)->eventdata != NULL )
15780 {
15781 SCIP_CONSHDLRDATA* conshdlrdata;
15782
15783 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15784 assert(conshdlrdata != NULL);
15785
15786 /* drop all events */
15787 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15788 assert((*consdata)->eventdata == NULL);
15789 }
15790
15791 /* free linear constraint */
15792 SCIP_CALL( consdataFree(scip, consdata) );
15793
15794 return SCIP_OKAY;
15795}
15796
15797
15798/** transforms constraint data into data belonging to the transformed problem */
15799static
15800SCIP_DECL_CONSTRANS(consTransLinear)
15801{ /*lint --e{715}*/
15802 SCIP_CONSDATA* sourcedata;
15803 SCIP_CONSDATA* targetdata;
15804
15805 /*debugMsg(scip, "Trans method of linear constraints\n");*/
15806
15807 assert(scip != NULL);
15808 assert(conshdlr != NULL);
15810 assert(sourcecons != NULL);
15811 assert(targetcons != NULL);
15812
15814
15815 sourcedata = SCIPconsGetData(sourcecons);
15816 assert(sourcedata != NULL);
15817 assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
15818
15819 /* create linear constraint data for target constraint */
15820 SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars, sourcedata->vals, sourcedata->lhs,
15821 sourcedata->rhs) );
15822
15823#ifndef NDEBUG
15824 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
15825 if( SCIPconsIsEnforced(sourcecons) || SCIPconsIsChecked(sourcecons) )
15826 {
15827 int n;
15828 for(n = targetdata->nvars - 1; n >= 0; --n )
15829 assert(!SCIPvarIsRelaxationOnly(targetdata->vars[n]));
15830 }
15831#endif
15832
15833 /* create target constraint */
15834 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
15835 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
15836 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
15837 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
15838 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
15839
15840 return SCIP_OKAY;
15841}
15842
15843
15844/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
15845static
15846SCIP_DECL_CONSINITLP(consInitlpLinear)
15847{ /*lint --e{715}*/
15848 int c;
15849
15850 assert(scip != NULL);
15851
15853
15854 *infeasible = FALSE;
15855
15856 for( c = 0; c < nconss && !(*infeasible); ++c )
15857 {
15858 assert(SCIPconsIsInitial(conss[c]));
15859 SCIP_CALL( addRelaxation(scip, conss[c], infeasible) );
15860 }
15861
15862 return SCIP_OKAY;
15863}
15864
15865
15866/** separation method of constraint handler for LP solutions */
15867static
15868SCIP_DECL_CONSSEPALP(consSepalpLinear)
15869{ /*lint --e{715}*/
15870 SCIP_CONSHDLRDATA* conshdlrdata;
15871 SCIP_Real loclowerbound;
15872 SCIP_Real glblowerbound;
15873 SCIP_Real cutoffbound;
15874 SCIP_Real maxbound;
15875 SCIP_Bool separatecards;
15877 int c;
15878 int depth;
15879 int nrounds;
15880 int maxsepacuts;
15881 int ncuts;
15882
15883 assert(scip != NULL);
15884 assert(conshdlr != NULL);
15885 assert(result != NULL);
15886
15888
15889 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15890 assert(conshdlrdata != NULL);
15892 nrounds = SCIPgetNSepaRounds(scip);
15893
15894 /*debugMsg(scip, "Sepa method of linear constraints\n");*/
15895
15897
15898 /* only call the separator a given number of times at each node */
15899 if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
15900 || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
15901 return SCIP_OKAY;
15902
15903 /* get the maximal number of cuts allowed in a separation round */
15904 maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
15905
15906 /* check if we want to produce knapsack cardinality cuts at this node */
15907 loclowerbound = SCIPgetLocalLowerbound(scip);
15908 glblowerbound = SCIPgetLowerbound(scip);
15909 cutoffbound = SCIPgetCutoffbound(scip);
15910 maxbound = glblowerbound + conshdlrdata->maxcardbounddist * (cutoffbound - glblowerbound);
15911 separatecards = SCIPisLE(scip, loclowerbound, maxbound);
15912 separatecards = separatecards && (SCIPgetNLPBranchCands(scip) > 0);
15913
15915 ncuts = 0;
15916 cutoff = FALSE;
15917
15918 /* check all useful linear constraints for feasibility */
15919 for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
15920 {
15921 /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
15922 SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, NULL, separatecards, conshdlrdata->separateall, &ncuts, &cutoff) );
15923 }
15924
15925 /* adjust return value */
15926 if( cutoff )
15928 else if( ncuts > 0 )
15930
15931 /* combine linear constraints to get more cuts */
15932 /**@todo further cuts of linear constraints */
15933
15934 return SCIP_OKAY;
15935}
15936
15937
15938/** separation method of constraint handler for arbitrary primal solutions */
15939static
15940SCIP_DECL_CONSSEPASOL(consSepasolLinear)
15941{ /*lint --e{715}*/
15942 SCIP_CONSHDLRDATA* conshdlrdata;
15943 int c;
15944 int depth;
15945 int nrounds;
15946 int maxsepacuts;
15947 int ncuts;
15949
15950 assert(scip != NULL);
15951 assert(conshdlr != NULL);
15952 assert(result != NULL);
15953
15955
15956 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15957 assert(conshdlrdata != NULL);
15959 nrounds = SCIPgetNSepaRounds(scip);
15960
15961 /*debugMsg(scip, "Sepa method of linear constraints\n");*/
15962
15964
15965 /* only call the separator a given number of times at each node */
15966 if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
15967 || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
15968 return SCIP_OKAY;
15969
15970 /* get the maximal number of cuts allowed in a separation round */
15971 maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
15972
15974 ncuts = 0;
15975 cutoff = FALSE;
15976
15977 /* check all useful linear constraints for feasibility */
15978 for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
15979 {
15980 /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
15981 SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, sol, TRUE, conshdlrdata->separateall, &ncuts, &cutoff) );
15982 }
15983
15984 /* adjust return value */
15985 if( cutoff )
15987 else if( ncuts > 0 )
15989
15990 /* combine linear constraints to get more cuts */
15991 /**@todo further cuts of linear constraints */
15992
15993 return SCIP_OKAY;
15994}
15995
15996
15997/** constraint enforcing method of constraint handler for LP solutions */
15998static
15999SCIP_DECL_CONSENFOLP(consEnfolpLinear)
16000{ /*lint --e{715}*/
16001 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
16002
16003 return SCIP_OKAY;
16004}
16005
16006/** constraint enforcing method of constraint handler for relaxation solutions */
16007static
16008SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
16009{ /*lint --e{715}*/
16010 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
16011
16012 return SCIP_OKAY;
16013}
16014
16015/** constraint enforcing method of constraint handler for pseudo solutions */
16016static
16017SCIP_DECL_CONSENFOPS(consEnfopsLinear)
16018{ /*lint --e{715}*/
16019 SCIP_CONSHDLRDATA* conshdlrdata;
16020 SCIP_Bool checkrelmaxabs;
16021 SCIP_Bool violated;
16022 int c;
16023
16024 assert(scip != NULL);
16025 assert(conshdlr != NULL);
16026 assert(result != NULL);
16027
16029
16030 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16031 assert(conshdlrdata != NULL);
16032
16033 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16034
16035 SCIPdebugMsg(scip, "Enfops method of linear constraints\n");
16036
16037 /* if the solution is infeasible anyway due to objective value, skip the enforcement */
16038 if( objinfeasible )
16039 {
16040 SCIPdebugMsg(scip, "-> pseudo solution is objective infeasible, return.\n");
16041
16043 return SCIP_OKAY;
16044 }
16045
16046 /* check all linear constraints for feasibility */
16047 violated = FALSE;
16048 for( c = 0; c < nconss && !violated; ++c )
16049 {
16050 SCIP_CALL( checkCons(scip, conss[c], NULL, TRUE, checkrelmaxabs, &violated) );
16051 }
16052
16053 if( violated )
16055 else
16057
16058 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
16059
16060 return SCIP_OKAY;
16061}
16062
16063
16064/** feasibility check method of constraint handler for integral solutions */
16065static
16066SCIP_DECL_CONSCHECK(consCheckLinear)
16067{ /*lint --e{715}*/
16068 SCIP_CONSHDLRDATA* conshdlrdata;
16069 SCIP_Bool checkrelmaxabs;
16070 int c;
16071
16072 assert(scip != NULL);
16073 assert(conshdlr != NULL);
16074 assert(result != NULL);
16075
16077
16079
16080 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16081 assert(conshdlrdata != NULL);
16082
16083 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16084
16085 /*debugMsg(scip, "Check method of linear constraints\n");*/
16086
16087 /* check all linear constraints for feasibility */
16088 for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
16089 {
16090 SCIP_Bool violated = FALSE;
16091 SCIP_CALL( checkCons(scip, conss[c], sol, checklprows, checkrelmaxabs, &violated) );
16092
16093 if( violated )
16094 {
16096
16097 if( printreason )
16098 {
16099 SCIP_CONSDATA* consdata;
16100 SCIP_Real activity;
16101
16102 consdata = SCIPconsGetData(conss[c]);
16103 assert( consdata != NULL);
16104
16105 activity = consdataGetActivity(scip, consdata, sol);
16106
16107 SCIP_CALL( consPrintConsSol(scip, conss[c], sol, NULL ) );
16108 SCIPinfoMessage(scip, NULL, ";\n");
16109
16110 if( activity == SCIP_INVALID || SCIPisInfinity(scip, ABS(activity)) ) /*lint !e777*/
16111 SCIPinfoMessage(scip, NULL, "activity invalid due to infinity contributions\n");
16112 else if( SCIPisFeasLT(scip, activity, consdata->lhs) )
16113 SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - activity);
16114 else if( SCIPisFeasGT(scip, activity, consdata->rhs) )
16115 SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - consdata->rhs);
16116 }
16117 }
16118 }
16119
16120 return SCIP_OKAY;
16121}
16122
16123
16124/** domain propagation method of constraint handler */
16125static
16126SCIP_DECL_CONSPROP(consPropLinear)
16127{ /*lint --e{715}*/
16128 SCIP_CONSHDLRDATA* conshdlrdata;
16129 SCIP_Bool rangedrowpropagation = FALSE;
16130 SCIP_Bool tightenbounds;
16132 int naddedconss = 0;
16133 int nchgbds = 0;
16134 int i;
16135
16136 assert(scip != NULL);
16137 assert(conshdlr != NULL);
16138 assert(result != NULL);
16139
16141
16142 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16143 assert(conshdlrdata != NULL);
16144
16145 /*debugMsg(scip, "Prop method of linear constraints\n");*/
16146
16147 /* check, if we want to tighten variable's bounds (in probing, we always want to tighten the bounds) */
16148 if( SCIPinProbing(scip) )
16149 tightenbounds = TRUE;
16150 else
16151 {
16152 int depth;
16153 int propfreq;
16154 int tightenboundsfreq;
16155 int rangedrowfreq;
16156
16158 propfreq = SCIPconshdlrGetPropFreq(conshdlr);
16159 tightenboundsfreq = propfreq * conshdlrdata->tightenboundsfreq;
16160 tightenbounds = (conshdlrdata->tightenboundsfreq >= 0)
16161 && ((tightenboundsfreq == 0 && depth == 0) || (tightenboundsfreq >= 1 && (depth % tightenboundsfreq == 0)));
16162
16163 /* check if we want to do ranged row propagation */
16164 rangedrowpropagation = conshdlrdata->rangedrowpropagation;
16165 rangedrowpropagation = rangedrowpropagation && !SCIPinRepropagation(scip);
16166 rangedrowpropagation = rangedrowpropagation && (depth <= conshdlrdata->rangedrowmaxdepth);
16167 rangedrowfreq = propfreq * conshdlrdata->rangedrowfreq;
16168 rangedrowpropagation = rangedrowpropagation && (conshdlrdata->rangedrowfreq >= 0)
16169 && ((rangedrowfreq == 0 && depth == 0) || (rangedrowfreq >= 1 && (depth % rangedrowfreq == 0)));
16170 rangedrowpropagation = rangedrowpropagation && (SCIPgetStage(scip) != SCIP_STAGE_PRESOLVING); /* ranged rows are also presolved */
16171 }
16172
16173 cutoff = FALSE;
16174
16175 /* process constraints marked for propagation */
16176 for( i = 0; i < nmarkedconss && !cutoff; i++ )
16177 {
16179 SCIP_CALL( propagateCons(scip, conss[i], tightenbounds, rangedrowpropagation,
16180 conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, &nchgbds, &naddedconss) );
16181 assert(naddedconss == 0 || (SCIPgetStage(scip) != SCIP_STAGE_PRESOLVING));
16182 }
16183
16184 /* adjust result code */
16185 if( cutoff )
16187 else if( nchgbds > 0 )
16189 else if( naddedconss > 0 )
16191 else
16193
16194 return SCIP_OKAY;
16195}
16196
16197
16198#define MAXCONSPRESOLROUNDS 10
16199/** presolving method of constraint handler */
16200static
16201SCIP_DECL_CONSPRESOL(consPresolLinear)
16202{ /*lint --e{715}*/
16203 SCIP_CONSHDLRDATA* conshdlrdata;
16204 SCIP_CONS* cons;
16205 SCIP_CONSDATA* consdata;
16206 SCIP_Real minactivity;
16207 SCIP_Real maxactivity;
16208 SCIP_Bool isminacttight;
16209 SCIP_Bool ismaxacttight;
16210 SCIP_Bool isminsettoinfinity;
16211 SCIP_Bool ismaxsettoinfinity;
16213 int oldnfixedvars;
16214 int oldnaggrvars;
16215 int oldnchgbds;
16216 int oldndelconss;
16217 int oldnupgdconss;
16218 int oldnchgcoefs;
16219 int oldnchgsides;
16220 int firstchange;
16221 int firstupgradetry;
16222 int c;
16223
16224 assert(scip != NULL);
16225 assert(conshdlr != NULL);
16226 assert(result != NULL);
16227
16229
16230 /* remember old preprocessing counters */
16231 cutoff = FALSE;
16232 oldnfixedvars = *nfixedvars;
16233 oldnaggrvars = *naggrvars;
16234 oldnchgbds = *nchgbds;
16235 oldndelconss = *ndelconss;
16236 oldnupgdconss = *nupgdconss;
16237 oldnchgcoefs = *nchgcoefs;
16238 oldnchgsides = *nchgsides;
16239
16240 /*debugMsg(scip, "Presol method of linear constraints\n");*/
16241
16242 /* get constraint handler data */
16243 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16244 assert(conshdlrdata != NULL);
16245
16246 /* process single constraints */
16247 firstchange = INT_MAX;
16248 firstupgradetry = INT_MAX;
16249 for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
16250 {
16251 int npresolrounds;
16252 SCIP_Bool infeasible;
16253
16254 infeasible = FALSE;
16255
16256 cons = conss[c];
16257 assert(SCIPconsIsActive(cons));
16258 consdata = SCIPconsGetData(cons);
16259 assert(consdata != NULL);
16260
16261 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
16262 if( SCIPisEQ(scip, consdata->rhs, consdata->lhs) )
16263 {
16264 consdata->lhs = consdata->rhs;
16265 assert(consdata->row == NULL);
16266 }
16267
16268 if( consdata->eventdata == NULL )
16269 {
16270 /* catch bound change events of variables */
16271 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
16272 assert(consdata->eventdata != NULL);
16273 }
16274
16275 /* constraint should not be already presolved in the initial round */
16276 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || SCIPconsIsMarkedPropagate(cons));
16277 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || consdata->boundstightened == 0);
16278 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->presolved);
16279 assert(!SCIPconsIsMarkedPropagate(cons) || !consdata->presolved);
16280
16281 /* incorporate fixings and aggregations in constraint */
16282 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
16283
16284 if( infeasible )
16285 {
16286 SCIPdebugMsg(scip, " -> infeasible fixing\n");
16287 cutoff = TRUE;
16288 break;
16289 }
16290
16291 assert(consdata->removedfixings);
16292
16293 /* we can only presolve linear constraints, that are not modifiable */
16294 if( SCIPconsIsModifiable(cons) )
16295 continue;
16296
16297 /* remember the first changed constraint to begin the next aggregation round with */
16298 if( firstchange == INT_MAX && consdata->changed )
16299 firstchange = c;
16300
16301 /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16302 if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16303 firstupgradetry = c;
16304
16305 /* check, if constraint is already preprocessed */
16306 if( consdata->presolved )
16307 continue;
16308
16309 assert(SCIPconsIsActive(cons));
16310
16311 SCIPdebugMsg(scip, "presolving linear constraint <%s>\n", SCIPconsGetName(cons));
16313
16314 /* apply presolving as long as possible on the single constraint (however, abort after a certain number of rounds
16315 * to avoid nearly infinite cycling due to very small bound changes)
16316 */
16317 npresolrounds = 0;
16318 while( !consdata->presolved && npresolrounds < MAXCONSPRESOLROUNDS && !SCIPisStopped(scip) )
16319 {
16320 assert(!cutoff);
16321 npresolrounds++;
16322
16323 /* mark constraint being presolved and propagated */
16324 consdata->presolved = TRUE;
16326
16327 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
16328
16329 if( infeasible )
16330 {
16331 SCIPdebugMsg(scip, " -> infeasible normalization\n");
16332 cutoff = TRUE;
16333 break;
16334 }
16335
16336 /* tighten left and right hand side due to integrality */
16337 SCIP_CALL( tightenSides(scip, cons, nchgsides, &infeasible) );
16338
16339 if( infeasible )
16340 {
16341 SCIPdebugMsg(scip, " -> infeasibility detected during tightening sides\n");
16342 cutoff = TRUE;
16343 break;
16344 }
16345
16346 /* check bounds */
16347 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16348 {
16349 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16350 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16351 cutoff = TRUE;
16352 break;
16353 }
16354
16355 /* tighten variable's bounds */
16356 SCIP_CALL( tightenBounds(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, nchgbds) );
16357 if( cutoff )
16358 break;
16359
16360 /* check for fixed variables */
16361 SCIP_CALL( fixVariables(scip, cons, &cutoff, nfixedvars) );
16362 if( cutoff )
16363 break;
16364
16365 /* if the maximal coefficient is large, recompute the activities before infeasibility and redundancy checks */
16366 if( ( consdata->validmaxabsval && consdata->maxabsval > MAXVALRECOMP )
16367 || ( consdata->validminabsval && consdata->minabsval < MINVALRECOMP ) )
16368 {
16371 }
16372
16373 /* get activity bounds */
16374 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
16375 &isminsettoinfinity, &ismaxsettoinfinity);
16376
16377 /* check constraint for infeasibility and redundancy */
16378 if( SCIPisFeasGT(scip, minactivity, consdata->rhs) || SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
16379 {
16380 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16381 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16382 cutoff = TRUE;
16383 break;
16384 }
16385 else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16386 {
16387 SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16388 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16389 SCIP_CALL( SCIPdelCons(scip, cons) );
16390 assert(!SCIPconsIsActive(cons));
16391
16392 if( !consdata->upgraded )
16393 (*ndelconss)++;
16394 break;
16395 }
16396 else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisGE(scip, minactivity, consdata->lhs) )
16397 {
16398 SCIPdebugMsg(scip, "linear constraint <%s> left hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16399 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16400 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
16401 if( !consdata->upgraded )
16402 (*nchgsides)++;
16403 }
16404 else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16405 {
16406 SCIPdebugMsg(scip, "linear constraint <%s> right hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16407 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16409 if( !consdata->upgraded )
16410 (*nchgsides)++;
16411 }
16412
16413 /* handle empty constraint */
16414 if( consdata->nvars == 0 )
16415 {
16416 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16417 {
16418 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16419 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16420 cutoff = TRUE;
16421 }
16422 else
16423 {
16424 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16425 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16426 SCIP_CALL( SCIPdelCons(scip, cons) );
16427 assert(!SCIPconsIsActive(cons));
16428
16429 if( !consdata->upgraded )
16430 (*ndelconss)++;
16431 }
16432 break;
16433 }
16434
16435 /* reduce big-M coefficients, that make the constraint redundant if the variable is on a bound */
16436 SCIP_CALL( consdataTightenCoefs(scip, cons, nchgcoefs, nchgsides) );
16437
16438 /* try to simplify inequalities */
16439 if( conshdlrdata->simplifyinequalities )
16440 {
16441 SCIP_CALL( simplifyInequalities(scip, cons, nchgcoefs, nchgsides, &cutoff) );
16442
16443 if( cutoff )
16444 break;
16445 }
16446
16447 /* aggregation variable in equations */
16448 if( conshdlrdata->aggregatevariables )
16449 {
16450 SCIP_CALL( aggregateVariables(scip, cons, &cutoff, nfixedvars, naggrvars) );
16451 if( cutoff )
16452 break;
16453 }
16454 }
16455
16456 if( !cutoff && !SCIPisStopped(scip) )
16457 {
16458 /* perform ranged row propagation */
16459 if( conshdlrdata->rangedrowpropagation )
16460 {
16461 int lastnfixedvars;
16462
16463 lastnfixedvars = *nfixedvars;
16464
16465 SCIP_CALL( rangedRowPropagation(scip, cons, &cutoff, nfixedvars, nchgbds, naddconss) );
16466 if( !cutoff )
16467 {
16468 if( lastnfixedvars < *nfixedvars )
16469 {
16470 SCIP_CALL( applyFixings(scip, cons, &cutoff) );
16471 }
16472 }
16473 }
16474
16475 /* extract cliques from constraint */
16476 if( conshdlrdata->extractcliques && !cutoff && SCIPconsIsActive(cons) )
16477 {
16478 SCIP_CALL( extractCliques(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars,
16479 nfixedvars, nchgbds, &cutoff) );
16480
16481 /* check if the constraint got redundant or infeasible */
16482 if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 0 )
16483 {
16484 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16485 {
16486 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16487 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16488 cutoff = TRUE;
16489 }
16490 else
16491 {
16492 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16493 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16494 SCIP_CALL( SCIPdelCons(scip, cons) );
16495 assert(!SCIPconsIsActive(cons));
16496
16497 if( !consdata->upgraded )
16498 (*ndelconss)++;
16499 }
16500 }
16501 }
16502
16503 /* convert special equalities */
16504 if( !cutoff && SCIPconsIsActive(cons) )
16505 {
16506 SCIP_CALL( convertEquality(scip, cons, conshdlrdata, &cutoff, nfixedvars, naggrvars, ndelconss, nchgvartypes) );
16507 }
16508
16509 /* apply dual presolving for variables that appear in only one constraint */
16510 if( !cutoff && SCIPconsIsActive(cons) && conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) )
16511 {
16512 SCIP_CALL( dualPresolve(scip, conshdlrdata, cons, &cutoff, nfixedvars, naggrvars, ndelconss, nchgvartypes) );
16513 }
16514
16515 /* check if an inequality is parallel to the objective function */
16516 if( !cutoff && SCIPconsIsActive(cons) )
16517 {
16518 SCIP_CALL( checkParallelObjective(scip, cons, conshdlrdata) );
16519 }
16520
16521 /* remember the first changed constraint to begin the next aggregation round with */
16522 if( firstchange == INT_MAX && consdata->changed )
16523 firstchange = c;
16524
16525 /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16526 if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16527 firstupgradetry = c;
16528 }
16529
16530 /* singleton column stuffing */
16531 if( !cutoff && SCIPconsIsActive(cons) && SCIPconsIsChecked(cons) &&
16532 (conshdlrdata->singletonstuffing || conshdlrdata->singlevarstuffing) && SCIPallowStrongDualReds(scip) )
16533 {
16534 SCIP_CALL( presolStuffing(scip, cons, conshdlrdata->singletonstuffing,
16535 conshdlrdata->singlevarstuffing, &cutoff, nfixedvars, nchgbds) );
16536
16537 /* handle empty constraint */
16538 if( consdata->nvars == 0 )
16539 {
16540 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16541 {
16542 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16543 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16544 cutoff = TRUE;
16545 }
16546 else
16547 {
16548 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16549 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16550 SCIP_CALL( SCIPdelCons(scip, cons) );
16551 assert(!SCIPconsIsActive(cons));
16552
16553 if( !consdata->upgraded )
16554 (*ndelconss)++;
16555 }
16556 break;
16557 }
16558 }
16559 }
16560
16561 /* process pairs of constraints: check them for redundancy and try to aggregate them;
16562 * only apply this expensive procedure in exhaustive presolving timing
16563 */
16564 if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && (conshdlrdata->presolusehashing || conshdlrdata->presolpairwise) && !SCIPisStopped(scip) )
16565 {
16566 assert(firstchange >= 0);
16567
16568 if( firstchange < nconss && conshdlrdata->presolusehashing )
16569 {
16570 /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
16571 SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff,
16572 ndelconss, nchgsides) );
16573 }
16574
16575 if( firstchange < nconss && conshdlrdata->presolpairwise )
16576 {
16577 SCIP_CONS** usefulconss;
16578 int nusefulconss;
16579 int firstchangenew;
16580 SCIP_Longint npaircomparisons;
16581
16582 npaircomparisons = 0;
16583 oldndelconss = *ndelconss;
16584 oldnchgsides = *nchgsides;
16585 oldnchgcoefs = *nchgcoefs;
16586
16587 /* allocate temporary memory */
16588 SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, nconss) );
16589
16590 nusefulconss = 0;
16591 firstchangenew = -1;
16592 for( c = 0; c < nconss; ++c )
16593 {
16594 /* update firstchange */
16595 if( c == firstchange )
16596 firstchangenew = nusefulconss;
16597
16598 /* ignore inactive and modifiable constraints */
16599 if( !SCIPconsIsActive(conss[c]) || SCIPconsIsModifiable(conss[c]) )
16600 continue;
16601
16602 usefulconss[nusefulconss] = conss[c];
16603 ++nusefulconss;
16604 }
16605 firstchange = firstchangenew;
16606 assert(firstchangenew >= 0 && firstchangenew <= nusefulconss);
16607
16608 for( c = firstchange; c < nusefulconss && !cutoff && !SCIPisStopped(scip); ++c )
16609 {
16610 /* constraint has become inactive or modifiable during pairwise presolving */
16611 if( usefulconss[c] == NULL )
16612 continue;
16613
16614 npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? c : (c - firstchange); /*lint !e776*/
16615
16616 assert(SCIPconsIsActive(usefulconss[c]) && !SCIPconsIsModifiable(usefulconss[c]));
16617 SCIP_CALL( preprocessConstraintPairs(scip, usefulconss, firstchange, c, conshdlrdata->maxaggrnormscale,
16618 &cutoff, ndelconss, nchgsides, nchgcoefs) );
16619
16620 if( npaircomparisons > conshdlrdata->nmincomparisons )
16621 {
16622 assert(npaircomparisons > 0);
16623 if( ((*ndelconss - oldndelconss) + (*nchgsides - oldnchgsides)/2.0 + (*nchgcoefs - oldnchgcoefs)/10.0) / ((SCIP_Real) npaircomparisons) < conshdlrdata->mingainpernmincomp )
16624 break;
16625 oldndelconss = *ndelconss;
16626 oldnchgsides = *nchgsides;
16627 oldnchgcoefs = *nchgcoefs;
16628 npaircomparisons = 0;
16629 }
16630 }
16631 /* free temporary memory */
16632 SCIPfreeBufferArray(scip, &usefulconss);
16633 }
16634 }
16635
16636 /* before upgrading, check whether we can apply some additional dual presolving, because a variable only appears
16637 * in linear constraints and we therefore have full information about it
16638 */
16639 if( !cutoff && firstupgradetry < nconss
16640 && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
16641 && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides
16642 )
16643 {
16644 if( conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) && !SCIPisStopped(scip) )
16645 {
16646 SCIP_CALL( fullDualPresolve(scip, conss, nconss, &cutoff, nchgbds, nchgvartypes) );
16647 }
16648 }
16649
16650 /* try to upgrade constraints into a more specific constraint type;
16651 * only upgrade constraints, if no reductions were found in this round (otherwise, the linear constraint handler
16652 * may find additional reductions before giving control away to other (less intelligent?) constraint handlers)
16653 */
16654 if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && SCIPisPresolveFinished(scip) )
16655 {
16656 for( c = firstupgradetry; c < nconss && !SCIPisStopped(scip); ++c )
16657 {
16658 cons = conss[c];
16659
16660 /* don't upgrade modifiable constraints */
16661 if( SCIPconsIsModifiable(cons) )
16662 continue;
16663
16664 consdata = SCIPconsGetData(cons);
16665 assert(consdata != NULL);
16666
16667 /* only upgrade completely presolved constraints, that changed since the last upgrading call */
16668 if( consdata->upgradetried )
16669 continue;
16670 /* @todo force that upgrade will be performed later? */
16671 if( !consdata->presolved )
16672 continue;
16673
16674 consdata->upgradetried = TRUE;
16675 if( SCIPconsIsActive(cons) )
16676 {
16677 SCIP_CONS* upgdcons;
16678
16679 SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
16680 if( upgdcons != NULL )
16681 {
16682 /* add the upgraded constraint to the problem */
16683 SCIP_CALL( SCIPaddConsUpgrade(scip, cons, &upgdcons) );
16684 ++(*nupgdconss);
16685
16686 /* mark the linear constraint being upgraded and to be removed after presolving;
16687 * don't delete it directly, because it may help to preprocess other linear constraints
16688 */
16689 assert(!consdata->upgraded);
16690 consdata->upgraded = TRUE;
16691
16692 /* delete upgraded inequalities immediately;
16693 * delete upgraded equalities, if we don't need it anymore for aggregation and redundancy checking
16694 */
16695 if( SCIPisLT(scip, consdata->lhs, consdata->rhs)
16696 || !conshdlrdata->presolpairwise
16697 || (conshdlrdata->maxaggrnormscale == 0.0) )
16698 {
16699 SCIP_CALL( SCIPdelCons(scip, cons) );
16700 }
16701 }
16702 }
16703 }
16704 }
16705
16706 /* return the correct result code */
16707 if( cutoff )
16709 else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss
16710 || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
16712 else
16714
16715 return SCIP_OKAY;
16716}
16717
16718
16719/** propagation conflict resolving method of constraint handler */
16720static
16721SCIP_DECL_CONSRESPROP(consRespropLinear)
16722{ /*lint --e{715}*/
16723 assert(scip != NULL);
16724 assert(cons != NULL);
16725 assert(result != NULL);
16726
16727 SCIP_CALL( resolvePropagation(scip, cons, infervar, intToInferInfo(inferinfo), boundtype, bdchgidx, result) );
16728
16729 return SCIP_OKAY;
16730}
16731
16732
16733/** variable rounding lock method of constraint handler */
16734static
16735SCIP_DECL_CONSLOCK(consLockLinear)
16736{ /*lint --e{715}*/
16737 SCIP_CONSDATA* consdata;
16738 SCIP_Bool haslhs;
16739 SCIP_Bool hasrhs;
16740 int i;
16741
16742 assert(scip != NULL);
16743 assert(cons != NULL);
16744 consdata = SCIPconsGetData(cons);
16745 assert(consdata != NULL);
16746
16747 haslhs = !SCIPisInfinity(scip, -consdata->lhs);
16748 hasrhs = !SCIPisInfinity(scip, consdata->rhs);
16749
16750 /* update rounding locks of every single variable */
16751 for( i = 0; i < consdata->nvars; ++i )
16752 {
16753 if( SCIPisPositive(scip, consdata->vals[i]) )
16754 {
16755 if( haslhs )
16756 {
16757 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16758 }
16759 if( hasrhs )
16760 {
16761 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16762 }
16763 }
16764 else
16765 {
16766 if( haslhs )
16767 {
16768 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16769 }
16770 if( hasrhs )
16771 {
16772 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16773 }
16774 }
16775 }
16776
16777 return SCIP_OKAY;
16778}
16779
16780
16781/** variable deletion method of constraint handler */
16782static
16783SCIP_DECL_CONSDELVARS(consDelvarsLinear)
16784{
16785 assert(scip != NULL);
16786 assert(conshdlr != NULL);
16787 assert(conss != NULL || nconss == 0);
16788
16789 if( nconss > 0 )
16790 {
16791 SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
16792 }
16793
16794 return SCIP_OKAY;
16795}
16796
16797/** constraint display method of constraint handler */
16798static
16799SCIP_DECL_CONSPRINT(consPrintLinear)
16800{ /*lint --e{715}*/
16801 assert(scip != NULL);
16802 assert(conshdlr != NULL);
16803 assert(cons != NULL);
16804
16806
16807 return SCIP_OKAY;
16808}
16809
16810/** constraint copying method of constraint handler */
16811static
16812SCIP_DECL_CONSCOPY(consCopyLinear)
16813{ /*lint --e{715}*/
16814 SCIP_VAR** sourcevars;
16815 SCIP_Real* sourcecoefs;
16816 const char* consname;
16817 int nvars;
16818
16819 assert(scip != NULL);
16820 assert(sourcescip != NULL);
16821 assert(sourcecons != NULL);
16822
16823 /* get variables and coefficients of the source constraint */
16824 sourcevars = SCIPgetVarsLinear(sourcescip, sourcecons);
16825 sourcecoefs = SCIPgetValsLinear(sourcescip, sourcecons);
16826 nvars = SCIPgetNVarsLinear(sourcescip, sourcecons);
16827
16828 if( name != NULL )
16829 consname = name;
16830 else
16831 consname = SCIPconsGetName(sourcecons);
16832
16833 SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, sourcecoefs,
16834 SCIPgetLhsLinear(sourcescip, sourcecons), SCIPgetRhsLinear(sourcescip, sourcecons), varmap, consmap,
16835 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
16836 assert(cons != NULL || *valid == FALSE);
16837
16838 /* @todo should also the checkabsolute flag of the constraint be copied? */
16839
16840 return SCIP_OKAY;
16841}
16842
16843/** find operators '<=', '==', '>=', [free] in input string and return those places
16844 *
16845 * There should only be one operator, except for ranged rows for which exactly two operators '<=' must be present.
16846 */
16847static
16849 const char* str, /**< null terminated input string */
16850 char** firstoperator, /**< pointer to store the string starting at the first operator */
16851 char** secondoperator, /**< pointer to store the string starting at the second operator */
16852 SCIP_Bool* success /**< pointer to store if the line contains a valid operator order */
16853 )
16854{
16855 char* curr;
16856
16857 assert(str != NULL);
16858 assert(firstoperator != NULL);
16859 assert(secondoperator != NULL);
16860
16861 *firstoperator = NULL;
16862 *secondoperator = NULL;
16863
16864 curr = (char*)str;
16865 *success = TRUE;
16866
16867 /* loop over the input string to find all operators */
16868 while( *curr && *success )
16869 {
16870 SCIP_Bool found = FALSE;
16871 int increment = 1;
16872
16873 /* try if we found a possible operator */
16874 switch( *curr )
16875 {
16876 case '<':
16877 case '=':
16878 case '>':
16879
16880 /* check if the two characters curr[0,1] form an operator together */
16881 if( curr[1] == '=' )
16882 {
16883 found = TRUE;
16884
16885 /* update increment to continue after this operator */
16886 increment = 2;
16887 }
16888 break;
16889 case '[':
16890 if( strncmp(curr, "[free]", 6) == 0 )
16891 {
16892 found = TRUE;
16893
16894 /* update increment to continue after this operator */
16895 increment = 6;
16896 }
16897 break;
16898 default:
16899 break;
16900 }
16901
16902 /* assign the found operator to the first or second pointer and check for violations of the linear constraint grammar */
16903 if( found )
16904 {
16905 if( *firstoperator == NULL )
16906 {
16907 *firstoperator = curr;
16908 }
16909 else
16910 {
16911 if( *secondoperator != NULL )
16912 {
16913 SCIPerrorMessage("Found more than two operators in line %s\n", str);
16914 *success = FALSE;
16915 }
16916 else if( strncmp(*firstoperator, "<=", 2) != 0 )
16917 {
16918 SCIPerrorMessage("Two operators in line that is not a ranged row: %s", str);
16919 *success = FALSE;
16920 }
16921 else if( strncmp(curr, "<=", 2) != 0 )
16922 {
16923 SCIPerrorMessage("Bad second operator, expected ranged row specification: %s", str);
16924 *success = FALSE;
16925 }
16926
16927 *secondoperator = curr;
16928 }
16929 }
16930
16931 curr += increment;
16932 }
16933
16934 /* check if we did find at least one operator */
16935 if( *success )
16936 {
16937 if( *firstoperator == NULL )
16938 {
16939 SCIPerrorMessage("Could not find any operator in line %s\n", str);
16940 *success = FALSE;
16941 }
16942 }
16943}
16944
16945/** constraint parsing method of constraint handler */
16946static
16947SCIP_DECL_CONSPARSE(consParseLinear)
16948{ /*lint --e{715}*/
16949 SCIP_VAR** vars;
16950 SCIP_Real* coefs = NULL;
16951 int nvars;
16952 int coefssize = 100;
16953 int requsize;
16954 SCIP_Real lhs;
16955 SCIP_Real rhs;
16956 char* endptr;
16957 char* firstop;
16958 char* secondop;
16959 SCIP_Bool operatorsuccess;
16960 char* lhsstrptr = NULL;
16961 char* rhsstrptr = NULL;
16962 char* varstrptr = (char*)str;
16963
16964 assert(scip != NULL);
16965 assert(success != NULL);
16966 assert(str != NULL);
16967 assert(name != NULL);
16968 assert(cons != NULL);
16969
16970 *success = FALSE;
16971
16972 /* return of string empty */
16973 if( !(*str) )
16974 return SCIP_OKAY;
16975
16976 /* set left and right hand side to their default values */
16977 lhs = -SCIPinfinity(scip);
16978 rhs = SCIPinfinity(scip);
16979
16980 /* ignore whitespace */
16981 SCIP_CALL( SCIPskipSpace((char**)&str) );
16982
16983 /* find operators in the line first, all other remaining parsing depends on occurence of the operators '<=', '>=', '==',
16984 * and the special word [free]
16985 */
16986 findOperators(str, &firstop, &secondop, &operatorsuccess);
16987
16988 /* if the grammar is not valid for parsing a linear constraint, return */
16989 if( ! operatorsuccess )
16990 return SCIP_OKAY;
16991 assert(firstop != NULL);
16992
16993 /* assign the strings for parsing the left hand side, right hand side, and the linear variable sum */
16994 switch( *firstop )
16995 {
16996 case '<':
16997 assert(firstop[1] == '=');
16998 /* we have ranged row lhs <= a_1 x_1 + ... + a_n x_n <= rhs */
16999 if( secondop != NULL )
17000 {
17001 assert(secondop[0] == '<' && secondop[1] == '=');
17002 lhsstrptr = (char *)str;
17003 varstrptr = firstop + 2;
17004 rhsstrptr = secondop + 2;
17005 }
17006 else
17007 {
17008 /* we have an inequality with infinite left hand side a_1 x_1 + ... + a_n x_n <= rhs */
17009 lhsstrptr = NULL;
17010 varstrptr = (char *)str;
17011 rhsstrptr = firstop + 2;
17012 }
17013 break;
17014 case '>':
17015 assert(firstop[1] == '=');
17016 assert(secondop == NULL);
17017 /* we have a_1 x_1 + ... + a_n x_n >= lhs */
17018 lhsstrptr = firstop + 2;
17019 break;
17020 case '=':
17021 assert(firstop[1] == '=');
17022 assert(secondop == NULL);
17023 /* we have a_1 x_1 + ... + a_n x_n == lhs (rhs) */
17024 rhsstrptr = firstop + 2;
17025 lhsstrptr = firstop + 2;
17026 break;
17027 case '[':
17028 assert(strncmp(firstop, "[free]", 6) == 0);
17029 assert(secondop == NULL);
17030 /* nothing to assign in case of a free a_1 x_1 + ... + a_n x_n [free] */
17031 break;
17032 default:
17033 /* it should not be possible that a different character appears in that position */
17034 SCIPerrorMessage("Parsing has wrong operator character '%c', should be one of <=>[", *firstop);
17035 return SCIP_READERROR;
17036 }
17037
17038 /* parse left hand side, if necessary */
17039 if( lhsstrptr != NULL )
17040 {
17041 if( ! SCIPparseReal(scip, lhsstrptr, &lhs, &endptr) )
17042 {
17043 SCIPerrorMessage("error parsing left hand side number from <%s>\n", lhsstrptr);
17044 return SCIP_OKAY;
17045 }
17046
17047 /* in case of an equation, assign the left also to the right hand side */
17048 if( rhsstrptr == lhsstrptr )
17049 rhs = lhs;
17050 }
17051
17052 /* parse right hand side, if different from left hand side */
17053 if( rhsstrptr != NULL && rhsstrptr != lhsstrptr )
17054 {
17055 if( ! SCIPparseReal(scip, rhsstrptr, &rhs, &endptr) )
17056 {
17057 SCIPerrorMessage("error parsing right hand side number from <%s>\n", lhsstrptr);
17058 return SCIP_OKAY;
17059 }
17060 }
17061
17062 /* initialize buffers for storing the variables and coefficients */
17063 SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) );
17064 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
17065
17066 assert(varstrptr != NULL);
17067
17068 /* parse linear sum to get variables and coefficients */
17069 SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17070
17071 if( *success && requsize > coefssize )
17072 {
17073 /* realloc buffers and try again */
17074 coefssize = requsize;
17075 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, coefssize) );
17076 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
17077
17078 SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17079 assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
17080 }
17081
17082 if( !*success )
17083 {
17084 SCIPerrorMessage("no luck in parsing linear sum '%s'\n", varstrptr);
17085 }
17086 else
17087 {
17088 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
17089 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17090 }
17091
17092 SCIPfreeBufferArray(scip, &coefs);
17094
17095 return SCIP_OKAY;
17096}
17097
17098
17099/** constraint method of constraint handler which returns the variables (if possible) */
17100static
17101SCIP_DECL_CONSGETVARS(consGetVarsLinear)
17102{ /*lint --e{715}*/
17103 SCIP_CONSDATA* consdata;
17104
17105 consdata = SCIPconsGetData(cons);
17106 assert(consdata != NULL);
17107
17108 if( varssize < consdata->nvars )
17109 (*success) = FALSE;
17110 else
17111 {
17112 assert(vars != NULL);
17113
17114 BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
17115 (*success) = TRUE;
17116 }
17117
17118 return SCIP_OKAY;
17119}
17120
17121/**! [Callback for the number of variables]*/
17122/** constraint method of constraint handler which returns the number of variables (if possible) */
17123static
17124SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
17125{ /*lint --e{715}*/
17126 SCIP_CONSDATA* consdata;
17127
17128 consdata = SCIPconsGetData(cons);
17129 assert(consdata != NULL);
17130
17131 (*nvars) = consdata->nvars;
17132 (*success) = TRUE;
17133
17134 return SCIP_OKAY;
17135}
17136/**! [Callback for the number of variables]*/
17137
17138/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
17139static
17140SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphLinear)
17141{ /*lint --e{715}*/
17142 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
17143
17144 return SCIP_OKAY;
17145}
17146
17147/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
17148static
17149SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphLinear)
17150{ /*lint --e{715}*/
17151 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
17152
17153 return SCIP_OKAY;
17154}
17155
17156/*
17157 * Callback methods of event handler
17158 */
17159
17160/** execution method of event handler */
17161static
17162SCIP_DECL_EVENTEXEC(eventExecLinear)
17163{ /*lint --e{715}*/
17164 SCIP_CONS* cons;
17165 SCIP_CONSDATA* consdata;
17166 SCIP_VAR* var;
17167 SCIP_EVENTTYPE eventtype;
17168
17169 assert(scip != NULL);
17170 assert(eventhdlr != NULL);
17171 assert(eventdata != NULL);
17172 assert(event != NULL);
17173
17175
17176 cons = eventdata->cons;
17177 assert(cons != NULL);
17178 consdata = SCIPconsGetData(cons);
17179 assert(consdata != NULL);
17180
17181 /* we can skip events droped for deleted constraints */
17182 if( SCIPconsIsDeleted(cons) )
17183 return SCIP_OKAY;
17184
17185 eventtype = SCIPeventGetType(event);
17186 var = SCIPeventGetVar(event);
17187
17189 {
17190 SCIP_Real oldbound;
17191 SCIP_Real newbound;
17192 SCIP_Real val;
17193 int varpos;
17194
17195 varpos = eventdata->varpos;
17196 assert(0 <= varpos && varpos < consdata->nvars);
17197 oldbound = SCIPeventGetOldbound(event);
17198 newbound = SCIPeventGetNewbound(event);
17199 assert(var != NULL);
17200 assert(consdata->vars[varpos] == var);
17201 val = consdata->vals[varpos];
17202
17203 /* we only need to update the activities if the constraint is active,
17204 * otherwise we mark them to be invalid
17205 */
17206 if( SCIPconsIsActive(cons) )
17207 {
17208 /* update the activity values */
17210 consdataUpdateActivitiesLb(scip, consdata, var, oldbound, newbound, val, TRUE);
17211 else
17212 {
17214 consdataUpdateActivitiesUb(scip, consdata, var, oldbound, newbound, val, TRUE);
17215 }
17216 }
17217 else
17219
17220 consdata->presolved = FALSE;
17221
17222 /* in probing do not reset disabled ranged row propagation */
17223 if( !SCIPinProbing(scip) )
17224 consdata->rangedrowpropagated = 0;
17225
17226 /* bound change can turn the constraint infeasible or redundant only if it was a tightening */
17228 {
17230
17231 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17232 if( consdata->maxactdeltavar == var )
17233 {
17234 consdata->maxactdelta = SCIP_INVALID;
17235 consdata->maxactdeltavar = NULL;
17236 }
17237
17238 /* check whether bound tightening might now be successful */
17239 if( consdata->boundstightened > 0)
17240 {
17241 switch( eventtype )
17242 {
17244 if( (val > 0.0 ? !SCIPisInfinity(scip, consdata->rhs) : !SCIPisInfinity(scip, -consdata->lhs)) )
17245 consdata->boundstightened = 0;
17246 break;
17248 if( (val > 0.0 ? !SCIPisInfinity(scip, -consdata->lhs) : !SCIPisInfinity(scip, consdata->rhs)) )
17249 consdata->boundstightened = 0;
17250 break;
17251 default:
17252 SCIPerrorMessage("invalid event type %" SCIP_EVENTTYPE_FORMAT "\n", eventtype);
17253 return SCIP_INVALIDDATA;
17254 }
17255 }
17256 }
17257 /* update maximal activity delta if a bound was relaxed */
17258 else if( !SCIPisInfinity(scip, consdata->maxactdelta) )
17259 {
17260 SCIP_Real lb;
17261 SCIP_Real ub;
17262 SCIP_Real domain;
17263 SCIP_Real delta;
17264
17266
17267 lb = SCIPvarGetLbLocal(var);
17268 ub = SCIPvarGetUbLocal(var);
17269
17270 domain = ub - lb;
17271 delta = REALABS(val) * domain;
17272
17273 if( delta > consdata->maxactdelta )
17274 {
17275 consdata->maxactdelta = delta;
17276 consdata->maxactdeltavar = var;
17277 }
17278 }
17279 }
17280 else if( (eventtype & SCIP_EVENTTYPE_VARFIXED) != SCIP_EVENTTYPE_DISABLED )
17281 {
17282 /* we want to remove the fixed variable */
17283 consdata->presolved = FALSE;
17284 consdata->removedfixings = FALSE;
17285 consdata->rangedrowpropagated = 0;
17286
17287 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17288 if( consdata->maxactdeltavar == var )
17289 {
17290 consdata->maxactdelta = SCIP_INVALID;
17291 consdata->maxactdeltavar = NULL;
17292 }
17293 }
17294 else if( (eventtype & SCIP_EVENTTYPE_VARUNLOCKED) != SCIP_EVENTTYPE_DISABLED )
17295 {
17296 /* there is only one lock left: we may multi-aggregate the variable as slack of an equation */
17299 consdata->presolved = FALSE;
17300 }
17301 else if( (eventtype & SCIP_EVENTTYPE_GBDCHANGED) != SCIP_EVENTTYPE_DISABLED )
17302 {
17303 SCIP_Real oldbound;
17304 SCIP_Real newbound;
17305 SCIP_Real val;
17306 int varpos;
17307
17308 varpos = eventdata->varpos;
17309 assert(0 <= varpos && varpos < consdata->nvars);
17310 oldbound = SCIPeventGetOldbound(event);
17311 newbound = SCIPeventGetNewbound(event);
17312 assert(var != NULL);
17313 assert(consdata->vars[varpos] == var);
17314 val = consdata->vals[varpos];
17315
17316 consdata->rangedrowpropagated = 0;
17317
17318 /* update the activity values */
17320 consdataUpdateActivitiesGlbLb(scip, consdata, oldbound, newbound, val, TRUE);
17321 else
17322 {
17324 consdataUpdateActivitiesGlbUb(scip, consdata, oldbound, newbound, val, TRUE);
17325 }
17326
17327 /* if the variable is binary but not fixed it had to become binary due to this global change */
17329 {
17331 consdata->indexsorted = FALSE;
17332 else
17333 consdata->coefsorted = FALSE;
17334 }
17335 }
17336 else if( (eventtype & SCIP_EVENTTYPE_TYPECHANGED) != SCIP_EVENTTYPE_DISABLED )
17337 {
17339
17340 /* for presolving it only matters if a variable becomes integral */
17341 consdata->presolved = (consdata->presolved && (SCIPeventGetOldtype(event) != SCIP_VARTYPE_CONTINUOUS || SCIPvarIsImpliedIntegral(var)));
17342
17343 /* the ordering is preserved if the variable remains binary */
17344 consdata->indexsorted = (consdata->indexsorted && SCIPvarIsBinary(var) && (SCIPeventGetOldtype(event) != SCIP_VARTYPE_CONTINUOUS || SCIPvarIsImpliedIntegral(var)));
17345 }
17347 {
17349
17350 /* for presolving it only matters if a variable becomes integral */
17351 consdata->presolved = (consdata->presolved && (SCIPeventGetOldImpltype(event) != SCIP_IMPLINTTYPE_NONE || SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS));
17352
17353 /* the ordering is preserved if the variable remains binary */
17354 consdata->indexsorted = (consdata->indexsorted && SCIPvarIsBinary(var) && (SCIPeventGetOldImpltype(event) != SCIP_IMPLINTTYPE_NONE || SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS));
17355 }
17356 else
17357 {
17359 consdata->varsdeleted = TRUE;
17360 }
17361
17362 return SCIP_OKAY;
17363}
17364
17365
17366/*
17367 * Callback methods of conflict handler
17368 */
17369
17370/** conflict processing method of conflict handler (called when conflict was found) */
17371static
17372SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
17373{ /*lint --e{715}*/
17374 SCIP_VAR** vars;
17375 SCIP_Real* vals;
17376 SCIP_Real lhs;
17377 int i;
17378
17379 assert(scip != NULL);
17380 assert(conflicthdlr != NULL);
17381 assert(bdchginfos != NULL || nbdchginfos == 0);
17382 assert(result != NULL);
17383
17385
17386 /* don't process already resolved conflicts */
17387 if( resolved )
17388 {
17390 return SCIP_OKAY;
17391 }
17392
17394
17395 /* create array of variables and coefficients: sum_{i \in P} x_i - sum_{i \in N} x_i >= 1 - |N| */
17396 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
17397 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nbdchginfos) );
17398 lhs = 1.0;
17399 for( i = 0; i < nbdchginfos; ++i )
17400 {
17401 assert(bdchginfos != NULL);
17402
17403 vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
17404
17405 /* we can only treat binary variables */
17406 /**@todo extend linear conflict constraints to some non-binary cases */
17407 if( !SCIPvarIsBinary(vars[i]) )
17408 break;
17409
17410 /* check whether the variable is fixed to zero (P) or one (N) in the conflict set */
17411 if( SCIPbdchginfoGetNewbound(bdchginfos[i]) < 0.5 )
17412 vals[i] = 1.0;
17413 else
17414 {
17415 vals[i] = -1.0;
17416 lhs -= 1.0;
17417 }
17418 }
17419
17420 if( i == nbdchginfos )
17421 {
17422 SCIP_CONS* cons;
17423 SCIP_CONS* upgdcons;
17424 char consname[SCIP_MAXSTRLEN];
17425
17426 /* create a constraint out of the conflict set */
17428 SCIP_CALL( SCIPcreateConsLinear(scip, &cons, consname, nbdchginfos, vars, vals, lhs, SCIPinfinity(scip),
17429 FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
17430
17431 /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
17432 SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
17433 if( upgdcons != NULL )
17434 {
17435 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
17436 cons = upgdcons;
17437 }
17438
17439 /* add conflict to SCIP */
17440 SCIP_CALL( SCIPaddConflict(scip, node, &cons, validnode, conftype, cutoffinvolved) );
17441
17443 }
17444
17445 /* free temporary memory */
17446 SCIPfreeBufferArray(scip, &vals);
17448
17449 return SCIP_OKAY;
17450}
17451
17452
17453/*
17454 * Nonlinear constraint upgrading
17455 */
17456
17457/** tries to upgrade a nonlinear constraint into a linear constraint */
17458static
17459SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
17460{
17461 SCIP_CONSDATA* consdata;
17462 SCIP_EXPR* expr;
17463 SCIP_Real lhs;
17464 SCIP_Real rhs;
17465 int i;
17466
17467 assert(nupgdconss != NULL);
17468 assert(upgdconss != NULL);
17469 assert(upgdconsssize > 0);
17470
17471 expr = SCIPgetExprNonlinear(cons);
17472 assert(expr != NULL);
17473
17474 /* not a linear constraint if the expression is not a sum
17475 * (unless the expression is a variable or a constant or a constant*variable, but these are simplified away in cons_nonlinear)
17476 */
17477 if( !SCIPisExprSum(scip, expr) )
17478 return SCIP_OKAY;
17479
17480 /* if at least one child is not a variable, then not a linear constraint */
17481 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17482 if( !SCIPisExprVar(scip, SCIPexprGetChildren(expr)[i]) )
17483 return SCIP_OKAY;
17484
17485 /* consider constant part of the sum expression */
17488
17489 SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
17490 0, NULL, NULL, lhs, rhs,
17494 SCIPconsIsStickingAtNode(cons)) );
17495 assert(upgdconss[0] != NULL);
17496
17497 consdata = SCIPconsGetData(upgdconss[0]);
17498
17499 /* add linear terms */
17501 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17502 {
17504 }
17505
17506 /* check violation of this linear constraint with absolute tolerances, to be consistent with the original nonlinear constraint */
17507 consdata->checkabsolute = TRUE;
17508
17509 *nupgdconss = 1;
17510
17511 SCIPdebugMsg(scip, "created linear constraint:\n");
17512 SCIPdebugPrintCons(scip, upgdconss[0], NULL);
17513
17514 return SCIP_OKAY;
17515} /*lint !e715*/
17516
17517/*
17518 * constraint specific interface methods
17519 */
17520
17521/** creates the handler for linear constraints and includes it in SCIP */
17523 SCIP* scip /**< SCIP data structure */
17524 )
17525{
17526 SCIP_CONSHDLRDATA* conshdlrdata;
17527 SCIP_CONSHDLR* conshdlr;
17528 SCIP_EVENTHDLR* eventhdlr;
17529 SCIP_CONFLICTHDLR* conflicthdlr;
17530
17531 assert(scip != NULL);
17532
17533 /* create event handler for bound change events */
17535 eventExecLinear, NULL) );
17536
17537 /* create conflict handler for linear constraints */
17539 conflictExecLinear, NULL) );
17540
17541 /* create constraint handler data */
17542 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
17543
17544 /* include constraint handler */
17547 consEnfolpLinear, consEnfopsLinear, consCheckLinear, consLockLinear,
17548 conshdlrdata) );
17549
17550 assert(conshdlr != NULL);
17551
17552 /* set non-fundamental callbacks via specific setter functions */
17553 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLinear, consCopyLinear) );
17554 SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveLinear) );
17555 SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveLinear) );
17556 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLinear) );
17557 SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsLinear) );
17558 SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitLinear) );
17559 SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLinear) );
17560 SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolLinear) );
17561 SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLinear) );
17562 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLinear) );
17563 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLinear) );
17564 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLinear) );
17565 SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitLinear) );
17566 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLinear) );
17567 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLinear) );
17569 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLinear) );
17572 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLinear) );
17573 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLinear, consSepasolLinear, CONSHDLR_SEPAFREQ,
17575 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLinear) );
17576 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLinear) );
17577 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphLinear) );
17578 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphLinear) );
17579
17580 if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
17581 {
17582 /* include the linear constraint upgrade in the nonlinear constraint handler */
17584 }
17585
17586 /* add linear constraint handler parameters */
17588 "constraints/" CONSHDLR_NAME "/tightenboundsfreq",
17589 "multiplier on propagation frequency, how often the bounds are tightened (-1: never, 0: only at root)",
17590 &conshdlrdata->tightenboundsfreq, TRUE, DEFAULT_TIGHTENBOUNDSFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17592 "constraints/" CONSHDLR_NAME "/maxrounds",
17593 "maximal number of separation rounds per node (-1: unlimited)",
17594 &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
17596 "constraints/" CONSHDLR_NAME "/maxroundsroot",
17597 "maximal number of separation rounds per node in the root node (-1: unlimited)",
17598 &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
17600 "constraints/" CONSHDLR_NAME "/maxsepacuts",
17601 "maximal number of cuts separated per separation round",
17602 &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
17604 "constraints/" CONSHDLR_NAME "/maxsepacutsroot",
17605 "maximal number of cuts separated per separation round in the root node",
17606 &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
17608 "constraints/" CONSHDLR_NAME "/presolpairwise",
17609 "should pairwise constraint comparison be performed in presolving?",
17610 &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
17612 "constraints/" CONSHDLR_NAME "/presolusehashing",
17613 "should hash table be used for detecting redundant constraints in advance",
17614 &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
17616 "constraints/" CONSHDLR_NAME "/nmincomparisons",
17617 "number for minimal pairwise presolve comparisons",
17618 &conshdlrdata->nmincomparisons, TRUE, DEFAULT_NMINCOMPARISONS, 1, INT_MAX, NULL, NULL) );
17620 "constraints/" CONSHDLR_NAME "/mingainpernmincomparisons",
17621 "minimal gain per minimal pairwise presolve comparisons to repeat pairwise comparison round",
17622 &conshdlrdata->mingainpernmincomp, TRUE, DEFAULT_MINGAINPERNMINCOMP, 0.0, 1.0, NULL, NULL) );
17624 "constraints/" CONSHDLR_NAME "/maxaggrnormscale",
17625 "maximal allowed relative gain in maximum norm for constraint aggregation (0.0: disable constraint aggregation)",
17626 &conshdlrdata->maxaggrnormscale, TRUE, DEFAULT_MAXAGGRNORMSCALE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17628 "constraints/" CONSHDLR_NAME "/maxeasyactivitydelta",
17629 "maximum activity delta to run easy propagation on linear constraint (faster, but numerically less stable)",
17630 &conshdlrdata->maxeasyactivitydelta, TRUE, DEFAULT_MAXEASYACTIVITYDELTA, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17632 "constraints/" CONSHDLR_NAME "/maxcardbounddist",
17633 "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for separating knapsack cardinality cuts",
17634 &conshdlrdata->maxcardbounddist, TRUE, DEFAULT_MAXCARDBOUNDDIST, 0.0, 1.0, NULL, NULL) );
17636 "constraints/" CONSHDLR_NAME "/separateall",
17637 "should all constraints be subject to cardinality cut generation instead of only the ones with non-zero dual value?",
17638 &conshdlrdata->separateall, FALSE, DEFAULT_SEPARATEALL, NULL, NULL) );
17640 "constraints/" CONSHDLR_NAME "/aggregatevariables",
17641 "should presolving search for aggregations in equations",
17642 &conshdlrdata->aggregatevariables, TRUE, DEFAULT_AGGREGATEVARIABLES, NULL, NULL) );
17644 "constraints/" CONSHDLR_NAME "/simplifyinequalities",
17645 "should presolving try to simplify inequalities",
17646 &conshdlrdata->simplifyinequalities, TRUE, DEFAULT_SIMPLIFYINEQUALITIES, NULL, NULL) );
17648 "constraints/" CONSHDLR_NAME "/dualpresolving",
17649 "should dual presolving steps be performed?",
17650 &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
17652 "constraints/" CONSHDLR_NAME "/singletonstuffing",
17653 "should stuffing of singleton continuous variables be performed?",
17654 &conshdlrdata->singletonstuffing, TRUE, DEFAULT_SINGLETONSTUFFING, NULL, NULL) );
17656 "constraints/" CONSHDLR_NAME "/singlevarstuffing",
17657 "should single variable stuffing be performed, which tries to fulfill constraints using the cheapest variable?",
17658 &conshdlrdata->singlevarstuffing, TRUE, DEFAULT_SINGLEVARSTUFFING, NULL, NULL) );
17660 "constraints/" CONSHDLR_NAME "/sortvars", "apply binaries sorting in decr. order of coeff abs value?",
17661 &conshdlrdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL) );
17663 "constraints/" CONSHDLR_NAME "/checkrelmaxabs",
17664 "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)?",
17665 &conshdlrdata->checkrelmaxabs, TRUE, DEFAULT_CHECKRELMAXABS, NULL, NULL) );
17667 "constraints/" CONSHDLR_NAME "/detectcutoffbound",
17668 "should presolving try to detect constraints parallel to the objective function defining an upper bound and prevent these constraints from entering the LP?",
17669 &conshdlrdata->detectcutoffbound, TRUE, DEFAULT_DETECTCUTOFFBOUND, NULL, NULL) );
17671 "constraints/" CONSHDLR_NAME "/detectlowerbound",
17672 "should presolving try to detect constraints parallel to the objective function defining a lower bound and prevent these constraints from entering the LP?",
17673 &conshdlrdata->detectlowerbound, TRUE, DEFAULT_DETECTLOWERBOUND, NULL, NULL) );
17675 "constraints/" CONSHDLR_NAME "/detectpartialobjective",
17676 "should presolving try to detect subsets of constraints parallel to the objective function?",
17677 &conshdlrdata->detectpartialobjective, TRUE, DEFAULT_DETECTPARTIALOBJECTIVE, NULL, NULL) );
17679 "constraints/" CONSHDLR_NAME "/rangedrowpropagation",
17680 "should presolving and propagation try to improve bounds, detect infeasibility, and extract sub-constraints from ranged rows and equations?",
17681 &conshdlrdata->rangedrowpropagation, TRUE, DEFAULT_RANGEDROWPROPAGATION, NULL, NULL) );
17683 "constraints/" CONSHDLR_NAME "/rangedrowartcons",
17684 "should presolving and propagation extract sub-constraints from ranged rows and equations?",
17685 &conshdlrdata->rangedrowartcons, TRUE, DEFAULT_RANGEDROWARTCONS, NULL, NULL) );
17687 "constraints/" CONSHDLR_NAME "/rangedrowmaxdepth",
17688 "maximum depth to apply ranged row propagation",
17689 &conshdlrdata->rangedrowmaxdepth, TRUE, DEFAULT_RANGEDROWMAXDEPTH, 0, INT_MAX, NULL, NULL) );
17691 "constraints/" CONSHDLR_NAME "/rangedrowfreq",
17692 "frequency for applying ranged row propagation",
17693 &conshdlrdata->rangedrowfreq, TRUE, DEFAULT_RANGEDROWFREQ, 1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17695 "constraints/" CONSHDLR_NAME "/multaggrremove",
17696 "should multi-aggregations only be performed if the constraint can be removed afterwards?",
17697 &conshdlrdata->multaggrremove, TRUE, DEFAULT_MULTAGGRREMOVE, NULL, NULL) );
17699 "constraints/" CONSHDLR_NAME "/maxmultaggrquot",
17700 "maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation",
17701 &conshdlrdata->maxmultaggrquot, TRUE, DEFAULT_MAXMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17703 "constraints/" CONSHDLR_NAME "/maxdualmultaggrquot",
17704 "maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation",
17705 &conshdlrdata->maxdualmultaggrquot, TRUE, DEFAULT_MAXDUALMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17707 "constraints/" CONSHDLR_NAME "/extractcliques",
17708 "should Cliques be extracted?",
17709 &conshdlrdata->extractcliques, TRUE, DEFAULT_EXTRACTCLIQUES, NULL, NULL) );
17710
17711 return SCIP_OKAY;
17712}
17713
17714/** includes a linear constraint update method into the linear constraint handler */
17716 SCIP* scip, /**< SCIP data structure */
17717 SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
17718 int priority, /**< priority of upgrading method */
17719 const char* conshdlrname /**< name of the constraint handler */
17720 )
17721{
17722 SCIP_CONSHDLR* conshdlr;
17723 SCIP_CONSHDLRDATA* conshdlrdata;
17724 SCIP_LINCONSUPGRADE* linconsupgrade;
17726 char paramdesc[SCIP_MAXSTRLEN];
17727
17728 assert(scip != NULL);
17729 assert(linconsupgd != NULL);
17730 assert(conshdlrname != NULL );
17731
17732 /* find the linear constraint handler */
17733 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17734 if( conshdlr == NULL )
17735 {
17736 SCIPerrorMessage("linear constraint handler not found\n");
17737 return SCIP_PLUGINNOTFOUND;
17738 }
17739
17740 conshdlrdata = SCIPconshdlrGetData(conshdlr);
17741 assert(conshdlrdata != NULL);
17742
17743 /* check if linear constraint update method already exists in constraint handler data */
17744 if( !conshdlrdataHasUpgrade(scip, conshdlrdata, linconsupgd, conshdlrname) )
17745 {
17746 /* create a linear constraint upgrade data object */
17747 SCIP_CALL( linconsupgradeCreate(scip, &linconsupgrade, linconsupgd, priority) );
17748
17749 /* insert linear constraint update method into constraint handler data */
17750 SCIP_CALL( conshdlrdataIncludeUpgrade(scip, conshdlrdata, linconsupgrade) );
17751
17752 /* adds parameter to turn on and off the upgrading step */
17753 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/linear/upgrade/%s", conshdlrname);
17754 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "enable linear upgrading for constraint handler <%s>", conshdlrname);
17756 paramname, paramdesc,
17757 &linconsupgrade->active, FALSE, TRUE, NULL, NULL) );
17758 }
17759
17760 return SCIP_OKAY;
17761}
17762
17763/** creates and captures a linear constraint
17764 *
17765 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17766 */
17768 SCIP* scip, /**< SCIP data structure */
17769 SCIP_CONS** cons, /**< pointer to hold the created constraint */
17770 const char* name, /**< name of constraint */
17771 int nvars, /**< number of nonzeros in the constraint */
17772 SCIP_VAR** vars, /**< array with variables of constraint entries */
17773 SCIP_Real* vals, /**< array with coefficients of constraint entries */
17774 SCIP_Real lhs, /**< left hand side of constraint */
17775 SCIP_Real rhs, /**< right hand side of constraint */
17776 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
17777 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
17778 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
17779 * Usually set to TRUE. */
17780 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
17781 * TRUE for model constraints, FALSE for additional, redundant constraints. */
17782 SCIP_Bool check, /**< should the constraint be checked for feasibility?
17783 * TRUE for model constraints, FALSE for additional, redundant constraints. */
17784 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
17785 * Usually set to TRUE. */
17786 SCIP_Bool local, /**< is constraint only valid locally?
17787 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
17788 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
17789 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
17790 * adds coefficients to this constraint. */
17791 SCIP_Bool dynamic, /**< is constraint subject to aging?
17792 * Usually set to FALSE. Set to TRUE for own cuts which
17793 * are separated as constraints. */
17794 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
17795 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
17796 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
17797 * if it may be moved to a more global node?
17798 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
17799 )
17800{
17801 SCIP_CONSHDLR* conshdlr;
17802 SCIP_CONSDATA* consdata;
17803 int i;
17804
17805 assert(scip != NULL);
17806 assert(cons != NULL);
17807
17808 /* find the linear constraint handler */
17809 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17810 if( conshdlr == NULL )
17811 {
17812 SCIPerrorMessage("linear constraint handler not found\n");
17813 return SCIP_PLUGINNOTFOUND;
17814 }
17815
17816 /* terminate if a coefficient is infinite */
17817 assert(SCIPisFinite(lhs));
17818 assert(SCIPisFinite(rhs));
17819 for( i = 0; i < nvars; ++i )
17820 {
17821 assert(SCIPisFinite(vals[i]));
17822 if( SCIPisInfinity(scip, REALABS(vals[i])) )
17823 {
17824 SCIPerrorMessage("coefficient of variable <%s> in constraint <%s> is infinite,"
17825 " consider adjusting the infinity threshold\n", SCIPvarGetName(vars[i]), name);
17826 SCIPABORT();
17827 return SCIP_INVALIDDATA;
17828 }
17829 }
17830
17831 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
17832 * constraint after presolving we have to ensure that it holds active variables
17833 */
17835 {
17836 SCIP_VAR** consvars;
17837 SCIP_Real* consvals;
17838 SCIP_Real constant = 0.0;
17839 int nconsvars;
17840 int requiredsize;
17841
17842 nconsvars = nvars;
17843 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, vars, nconsvars) );
17844 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) );
17845
17846 /* get active variables for new constraint */
17847 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize) );
17848
17849 /* if space was not enough we need to resize the buffers */
17850 if( requiredsize > nconsvars )
17851 {
17852 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
17853 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
17854
17855 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize) );
17856 }
17857 assert(requiredsize == nconsvars);
17858
17859 /* adjust sides and check that we do not subtract infinity values */
17860 if( SCIPisInfinity(scip, REALABS(constant)) )
17861 {
17862 SCIPfreeBufferArray(scip, &consvals);
17863 SCIPfreeBufferArray(scip, &consvars);
17864 SCIPerrorMessage("while creating constraint <%s> inactive variables lead to an infinite constant\n", name);
17865 SCIPABORT();
17866 return SCIP_INVALIDDATA;
17867 }
17868 else
17869 {
17870 if( !SCIPisInfinity(scip, REALABS(lhs)) )
17871 lhs -= constant;
17872 if( !SCIPisInfinity(scip, REALABS(rhs)) )
17873 rhs -= constant;
17874
17875 if( SCIPisInfinity(scip, -lhs) )
17876 lhs = -SCIPinfinity(scip);
17877 else if( SCIPisInfinity(scip, lhs) )
17878 lhs = SCIPinfinity(scip);
17879
17880 if( SCIPisInfinity(scip, rhs) )
17881 rhs = SCIPinfinity(scip);
17882 else if( SCIPisInfinity(scip, -rhs) )
17883 rhs = -SCIPinfinity(scip);
17884 }
17885
17886 /* create constraint data */
17887 SCIP_CALL( consdataCreate(scip, &consdata, nconsvars, consvars, consvals, lhs, rhs) );
17888
17889 SCIPfreeBufferArray(scip, &consvals);
17890 SCIPfreeBufferArray(scip, &consvars);
17891 }
17892 else
17893 {
17894 /* create constraint data */
17895 SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, vals, lhs, rhs) );
17896 }
17897 assert(consdata != NULL);
17898
17899#ifndef NDEBUG
17900 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
17901 if( check || enforce )
17902 {
17903 int n;
17904 for(n = consdata->nvars - 1; n >= 0; --n )
17905 assert(!SCIPvarIsRelaxationOnly(consdata->vars[n]));
17906 }
17907#endif
17908
17909 /* create constraint */
17910 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
17911 local, modifiable, dynamic, removable, stickingatnode) );
17912
17913 return SCIP_OKAY;
17914}
17915
17916/** creates and captures a linear constraint
17917 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
17918 * method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
17919 *
17920 * @see SCIPcreateConsLinear() for information about the basic constraint flag configuration
17921 *
17922 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17923 */
17925 SCIP* scip, /**< SCIP data structure */
17926 SCIP_CONS** cons, /**< pointer to hold the created constraint */
17927 const char* name, /**< name of constraint */
17928 int nvars, /**< number of nonzeros in the constraint */
17929 SCIP_VAR** vars, /**< array with variables of constraint entries */
17930 SCIP_Real* vals, /**< array with coefficients of constraint entries */
17931 SCIP_Real lhs, /**< left hand side of constraint */
17932 SCIP_Real rhs /**< right hand side of constraint */
17933 )
17934{
17935 assert(scip != NULL);
17936
17937 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, vals, lhs, rhs,
17939
17940 return SCIP_OKAY;
17941}
17942
17943/** creates by copying and captures a linear constraint */
17945 SCIP* scip, /**< target SCIP data structure */
17946 SCIP_CONS** cons, /**< pointer to store the created target constraint */
17947 SCIP* sourcescip, /**< source SCIP data structure */
17948 const char* name, /**< name of constraint */
17949 int nvars, /**< number of variables in source variable array */
17950 SCIP_VAR** sourcevars, /**< source variables of the linear constraints */
17951 SCIP_Real* sourcecoefs, /**< coefficient array of the linear constraint, or NULL if all coefficients are one */
17952 SCIP_Real lhs, /**< left hand side of the linear constraint */
17953 SCIP_Real rhs, /**< right hand side of the linear constraint */
17954 SCIP_HASHMAP* varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
17955 * variables of the target SCIP */
17956 SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
17957 * target constraints */
17958 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
17959 SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
17960 SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
17961 SCIP_Bool check, /**< should the constraint be checked for feasibility? */
17962 SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
17963 SCIP_Bool local, /**< is constraint only valid locally? */
17964 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
17965 SCIP_Bool dynamic, /**< is constraint subject to aging? */
17966 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
17967 SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even
17968 * if it may be moved to a more global node? */
17969 SCIP_Bool global, /**< create a global or a local copy? */
17970 SCIP_Bool* valid /**< pointer to store if the copying was valid */
17971 )
17972{
17973 SCIP_VAR** vars;
17974 SCIP_Real* coefs;
17975
17976 SCIP_Real constant;
17977 int requiredsize;
17978 int v;
17979 SCIP_Bool success;
17980
17981 if( SCIPisGT(scip, lhs, rhs) )
17982 {
17983 *valid = FALSE;
17984 return SCIP_OKAY;
17985 }
17986
17987 (*valid) = TRUE;
17988
17989 if( nvars == 0 )
17990 {
17991 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, 0, NULL, NULL, lhs, rhs,
17992 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17993 return SCIP_OKAY;
17994 }
17995
17996 /* duplicate variable array */
17998
17999 /* duplicate coefficient array */
18000 if( sourcecoefs != NULL )
18001 {
18002 SCIP_CALL( SCIPduplicateBufferArray(scip, &coefs, sourcecoefs, nvars) );
18003 }
18004 else
18005 {
18007 for( v = 0; v < nvars; ++v )
18008 coefs[v] = 1.0;
18009 }
18010
18011 constant = 0.0;
18012
18013 /* transform source variable to active variables of the source SCIP since only these can be mapped to variables of
18014 * the target SCIP
18015 */
18016 if( !SCIPvarIsOriginal(vars[0]) )
18017 {
18018 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize) );
18019
18020 if( requiredsize > nvars )
18021 {
18022 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
18023 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requiredsize) );
18024
18025 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize) );
18026 }
18027 assert(requiredsize == nvars);
18028 }
18029 else
18030 {
18031 for( v = 0; v < nvars; ++v )
18032 {
18034 SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &coefs[v], &constant) );
18035 assert(vars[v] != NULL);
18036 }
18037 }
18038
18039 success = TRUE;
18040 /* map variables of the source constraint to variables of the target SCIP */
18041 for( v = 0; v < nvars && success; ++v )
18042 {
18043 SCIP_VAR* var;
18044 var = vars[v];
18045
18046 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18047 assert(!SCIPvarIsRelaxationOnly(var) || (!check && !enforce));
18048
18049 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &vars[v], varmap, consmap, global, &success) );
18050 assert(!(success) || vars[v] != NULL);
18051 }
18052
18053 /* only create the target constraint, if all variables could be copied */
18054 if( success )
18055 {
18056 if( !SCIPisInfinity(scip, -lhs) )
18057 lhs -= constant;
18058
18059 if( !SCIPisInfinity(scip, rhs) )
18060 rhs -= constant;
18061
18062 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
18063 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18064 }
18065 else
18066 *valid = FALSE;
18067
18068 /* free buffer array */
18069 SCIPfreeBufferArray(scip, &coefs);
18071
18072 return SCIP_OKAY;
18073}
18074
18075/** adds coefficient to linear constraint (if it is not zero) */
18077 SCIP* scip, /**< SCIP data structure */
18078 SCIP_CONS* cons, /**< constraint data */
18079 SCIP_VAR* var, /**< variable of constraint entry */
18080 SCIP_Real val /**< coefficient of constraint entry */
18081 )
18082{
18083 assert(scip != NULL);
18084 assert(cons != NULL);
18085 assert(var != NULL);
18086
18088
18089 /* terminate if coefficient is infinite */
18090 assert(SCIPisFinite(val));
18091 if( SCIPisInfinity(scip, REALABS(val)) )
18092 {
18093 SCIPerrorMessage("coefficient of variable <%s> in constraint <%s> is infinite,"
18094 " consider adjusting the infinity threshold\n", SCIPvarGetName(var), SCIPconsGetName(cons));
18095 SCIPABORT();
18096 return SCIP_INVALIDDATA;
18097 }
18098
18099 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
18100 * constraint after presolving we have to ensure that it holds active variables
18101 */
18103 {
18104 SCIP_CONSDATA* consdata;
18105 SCIP_VAR** consvars;
18106 SCIP_Real* consvals;
18107 SCIP_Real constant = 0.0;
18108 SCIP_Real rhs;
18109 SCIP_Real lhs;
18110 int nconsvars;
18111 int requiredsize;
18112 int v;
18113
18114 nconsvars = 1;
18115 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
18116 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
18117 consvars[0] = var;
18118 consvals[0] = val;
18119
18120 /* get active variables for new constraint */
18121 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize) );
18122
18123 /* if space was not enough we need to resize the buffers */
18124 if( requiredsize > nconsvars )
18125 {
18126 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
18127 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
18128
18129 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize) );
18130 }
18131 assert(requiredsize == nconsvars);
18132
18133 consdata = SCIPconsGetData(cons);
18134 assert(consdata != NULL);
18135
18136 lhs = consdata->lhs;
18137 rhs = consdata->rhs;
18138
18139 /* adjust sides and check that we do not subtract infinity values */
18140 /* constant is infinite */
18141 if( SCIPisInfinity(scip, REALABS(constant)) )
18142 {
18143 if( constant < 0.0 )
18144 {
18145 if( SCIPisInfinity(scip, lhs) )
18146 {
18147 SCIPfreeBufferArray(scip, &consvals);
18148 SCIPfreeBufferArray(scip, &consvars);
18149
18150 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));
18151
18152 SCIPABORT();
18153 return SCIP_INVALIDDATA; /*lint !e527*/
18154 }
18155 if( SCIPisInfinity(scip, rhs) )
18156 {
18157 SCIPfreeBufferArray(scip, &consvals);
18158 SCIPfreeBufferArray(scip, &consvars);
18159
18160 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));
18161
18162 SCIPABORT();
18163 return SCIP_INVALIDDATA; /*lint !e527*/
18164 }
18165
18166 lhs = -SCIPinfinity(scip);
18167 rhs = -SCIPinfinity(scip);
18168 }
18169 else
18170 {
18171 if( SCIPisInfinity(scip, -lhs) )
18172 {
18173 SCIPfreeBufferArray(scip, &consvals);
18174 SCIPfreeBufferArray(scip, &consvars);
18175
18176 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));
18177
18178 SCIPABORT();
18179 return SCIP_INVALIDDATA; /*lint !e527*/
18180 }
18181 if( SCIPisInfinity(scip, -rhs) )
18182 {
18183 SCIPfreeBufferArray(scip, &consvals);
18184 SCIPfreeBufferArray(scip, &consvars);
18185
18186 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));
18187
18188 SCIPABORT();
18189 return SCIP_INVALIDDATA; /*lint !e527*/
18190 }
18191
18192 lhs = SCIPinfinity(scip);
18193 rhs = SCIPinfinity(scip);
18194 }
18195 }
18196 /* constant is not infinite */
18197 else
18198 {
18199 if( !SCIPisInfinity(scip, REALABS(lhs)) )
18200 lhs -= constant;
18201 if( !SCIPisInfinity(scip, REALABS(rhs)) )
18202 rhs -= constant;
18203
18204 if( SCIPisInfinity(scip, -lhs) )
18205 lhs = -SCIPinfinity(scip);
18206 else if( SCIPisInfinity(scip, lhs) )
18207 lhs = SCIPinfinity(scip);
18208
18209 if( SCIPisInfinity(scip, rhs) )
18210 rhs = SCIPinfinity(scip);
18211 else if( SCIPisInfinity(scip, -rhs) )
18212 rhs = -SCIPinfinity(scip);
18213 }
18214
18215 /* add all active variables to constraint */
18216 for( v = nconsvars - 1; v >= 0; --v )
18217 {
18218 if( !SCIPisZero(scip, consvals[v]) )
18219 {
18220 SCIP_CALL( addCoef(scip, cons, consvars[v], consvals[v]) );
18221 }
18222 }
18223
18224 /* update left and right hand sides */
18225 SCIP_CALL( chgLhs(scip, cons, lhs) );
18226 SCIP_CALL( chgRhs(scip, cons, rhs) );
18227
18228 SCIPfreeBufferArray(scip, &consvals);
18229 SCIPfreeBufferArray(scip, &consvars);
18230 }
18231 else if( !SCIPisZero(scip, val) )
18232 {
18233 SCIP_CALL( addCoef(scip, cons, var, val) );
18234 }
18235
18236 return SCIP_OKAY;
18237}
18238
18239/** changes coefficient of variable in linear constraint; deletes the variable if coefficient is zero; adds variable if
18240 * not yet contained in the constraint
18241 *
18242 * @note This method may only be called during problem creation stage for an original constraint and variable.
18243 *
18244 * @note This method requires linear time to search for occurences of the variable in the constraint data.
18245 */
18247 SCIP* scip, /**< SCIP data structure */
18248 SCIP_CONS* cons, /**< constraint data */
18249 SCIP_VAR* var, /**< variable of constraint entry */
18250 SCIP_Real val /**< new coefficient of constraint entry */
18251 )
18252{
18253 SCIP_CONSDATA* consdata;
18254 SCIP_VAR** vars;
18255 SCIP_Bool found;
18256 int i;
18257
18258 assert(scip != NULL);
18259 assert(cons != NULL);
18260 assert(var != NULL);
18261
18263
18265 {
18266 SCIPerrorMessage("method may only be called during problem creation stage for original constraints and variables\n");
18267 return SCIP_INVALIDDATA;
18268 }
18269
18270 consdata = SCIPconsGetData(cons);
18271 assert(consdata != NULL);
18272
18273 vars = consdata->vars;
18274 found = FALSE;
18275 i = 0;
18276 while( i < consdata->nvars )
18277 {
18278 if( vars[i] == var )
18279 {
18280 if( found || SCIPisZero(scip, val) )
18281 {
18282 SCIP_CALL( delCoefPos(scip, cons, i) );
18283
18284 /* decrease i by one since otherwise we would skip the coefficient which has been switched to position i */
18285 i--;
18286 }
18287 else
18288 {
18289 SCIP_CALL( chgCoefPos(scip, cons, i, val) );
18290 }
18291 found = TRUE;
18292 }
18293 i++;
18294 }
18295
18296 if( !found )
18297 {
18298 SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
18299 }
18300
18301 return SCIP_OKAY;
18302}
18303
18304/** deletes variable from linear constraint
18305 *
18306 * @note This method may only be called during problem creation stage for an original constraint and variable.
18307 *
18308 * @note This method requires linear time to search for occurences of the variable in the constraint data.
18309 */
18311 SCIP* scip, /**< SCIP data structure */
18312 SCIP_CONS* cons, /**< constraint data */
18313 SCIP_VAR* var /**< variable of constraint entry */
18314 )
18315{
18316 assert(scip != NULL);
18317 assert(cons != NULL);
18318 assert(var != NULL);
18319
18320 SCIP_CALL( SCIPchgCoefLinear(scip, cons, var, 0.0) );
18321
18322 return SCIP_OKAY;
18323}
18324
18325/** gets left hand side of linear constraint */
18327 SCIP* scip, /**< SCIP data structure */
18328 SCIP_CONS* cons /**< constraint data */
18329 )
18330{
18331 SCIP_CONSDATA* consdata;
18332
18333 assert(scip != NULL);
18334 assert(cons != NULL);
18335
18337
18338 consdata = SCIPconsGetData(cons);
18339 assert(consdata != NULL);
18340
18341 return consdata->lhs;
18342}
18343
18344/** gets right hand side of linear constraint */
18346 SCIP* scip, /**< SCIP data structure */
18347 SCIP_CONS* cons /**< constraint data */
18348 )
18349{
18350 SCIP_CONSDATA* consdata;
18351
18352 assert(scip != NULL);
18353 assert(cons != NULL);
18354
18356
18357 consdata = SCIPconsGetData(cons);
18358 assert(consdata != NULL);
18359
18360 return consdata->rhs;
18361}
18362
18363/** changes left hand side of linear constraint */
18365 SCIP* scip, /**< SCIP data structure */
18366 SCIP_CONS* cons, /**< constraint data */
18367 SCIP_Real lhs /**< new left hand side */
18368 )
18369{
18370 assert(scip != NULL);
18371 assert(cons != NULL);
18372
18374
18375 SCIP_CALL( chgLhs(scip, cons, lhs) );
18376
18377 return SCIP_OKAY;
18378}
18379
18380/** changes right hand side of linear constraint */
18382 SCIP* scip, /**< SCIP data structure */
18383 SCIP_CONS* cons, /**< constraint data */
18384 SCIP_Real rhs /**< new right hand side */
18385 )
18386{
18387 assert(scip != NULL);
18388 assert(cons != NULL);
18389
18391
18392 SCIP_CALL( chgRhs(scip, cons, rhs) );
18393
18394 return SCIP_OKAY;
18395}
18396
18397/** gets the number of variables in the linear constraint */
18399 SCIP* scip, /**< SCIP data structure */
18400 SCIP_CONS* cons /**< constraint data */
18401 )
18402{
18403 SCIP_CONSDATA* consdata;
18404
18405 assert(scip != NULL);
18406 assert(cons != NULL);
18407
18409
18410 consdata = SCIPconsGetData(cons);
18411 assert(consdata != NULL);
18412
18413 return consdata->nvars;
18414}
18415
18416/** gets the array of variables in the linear constraint; the user must not modify this array! */
18418 SCIP* scip, /**< SCIP data structure */
18419 SCIP_CONS* cons /**< constraint data */
18420 )
18421{
18422 SCIP_CONSDATA* consdata;
18423
18424 assert(scip != NULL);
18425 assert(cons != NULL);
18426
18428
18429 consdata = SCIPconsGetData(cons);
18430 assert(consdata != NULL);
18431
18432 return consdata->vars;
18433}
18434
18435/** gets the array of coefficient values in the linear constraint; the user must not modify this array! */
18437 SCIP* scip, /**< SCIP data structure */
18438 SCIP_CONS* cons /**< constraint data */
18439 )
18440{
18441 SCIP_CONSDATA* consdata;
18442
18443 assert(scip != NULL);
18444 assert(cons != NULL);
18445
18447
18448 consdata = SCIPconsGetData(cons);
18449 assert(consdata != NULL);
18450
18451 return consdata->vals;
18452}
18453
18454/** gets the activity of the linear constraint in the given solution
18455 *
18456 * @note if the solution contains values at infinity, this method will return SCIP_INVALID in case the activity
18457 * comprises positive and negative infinity contributions
18458 */
18460 SCIP* scip, /**< SCIP data structure */
18461 SCIP_CONS* cons, /**< constraint data */
18462 SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18463 )
18464{
18465 SCIP_CONSDATA* consdata;
18466
18467 assert(scip != NULL);
18468 assert(cons != NULL);
18469
18471
18472 consdata = SCIPconsGetData(cons);
18473 assert(consdata != NULL);
18474
18475 if( consdata->row != NULL )
18476 return SCIPgetRowSolActivity(scip, consdata->row, sol);
18477 else
18478 return consdataGetActivity(scip, consdata, sol);
18479}
18480
18481/** gets the feasibility of the linear constraint in the given solution */
18483 SCIP* scip, /**< SCIP data structure */
18484 SCIP_CONS* cons, /**< constraint data */
18485 SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18486 )
18487{
18488 SCIP_CONSDATA* consdata;
18489
18490 assert(scip != NULL);
18491 assert(cons != NULL);
18492
18494
18495 consdata = SCIPconsGetData(cons);
18496 assert(consdata != NULL);
18497
18498 if( consdata->row != NULL )
18499 return SCIPgetRowSolFeasibility(scip, consdata->row, sol);
18500 else
18501 return consdataGetFeasibility(scip, consdata, sol);
18502}
18503
18504/** gets the dual solution of the linear constraint in the current LP */
18506 SCIP* scip, /**< SCIP data structure */
18507 SCIP_CONS* cons /**< constraint data */
18508 )
18509{
18510 SCIP_CONSDATA* consdata;
18511
18512 assert(scip != NULL);
18513 assert(cons != NULL);
18514 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18515
18517
18518 consdata = SCIPconsGetData(cons);
18519 assert(consdata != NULL);
18520
18521 if( consdata->row != NULL )
18522 return SCIProwGetDualsol(consdata->row);
18523 else
18524 return 0.0;
18525}
18526
18527/** gets the dual Farkas value of the linear constraint in the current infeasible LP */
18529 SCIP* scip, /**< SCIP data structure */
18530 SCIP_CONS* cons /**< constraint data */
18531 )
18532{
18533 SCIP_CONSDATA* consdata;
18534
18535 assert(scip != NULL);
18536 assert(cons != NULL);
18537 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18538
18540
18541 consdata = SCIPconsGetData(cons);
18542 assert(consdata != NULL);
18543
18544 if( consdata->row != NULL )
18545 return SCIProwGetDualfarkas(consdata->row);
18546 else
18547 return 0.0;
18548}
18549
18550/** returns the linear relaxation of the given linear constraint; may return NULL if no LP row was yet created;
18551 * the user must not modify the row!
18552 */
18554 SCIP* scip, /**< SCIP data structure */
18555 SCIP_CONS* cons /**< constraint data */
18556 )
18557{
18558 SCIP_CONSDATA* consdata;
18559
18560 assert(scip != NULL);
18561 assert(cons != NULL);
18562
18564
18565 consdata = SCIPconsGetData(cons);
18566 assert(consdata != NULL);
18567
18568 return consdata->row;
18569}
18570
18571/** creates and returns the row of the given linear constraint */
18573 SCIP* scip, /**< SCIP data structure */
18574 SCIP_CONS* cons /**< constraint data */
18575 )
18576{
18577 SCIP_CONSDATA* consdata;
18578
18579 assert(scip != NULL);
18580 assert(cons != NULL);
18581
18583
18584 consdata = SCIPconsGetData(cons);
18585 assert(consdata != NULL);
18586
18587 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
18589
18590 SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) ) ;
18591
18592 return SCIP_OKAY;
18593}
18594
18595/** tries to automatically convert a linear constraint into a more specific and more specialized constraint */
18597 SCIP* scip, /**< SCIP data structure */
18598 SCIP_CONS* cons, /**< source constraint to try to convert */
18599 SCIP_CONS** upgdcons /**< pointer to store upgraded constraint, or NULL if not successful */
18600 )
18601{
18602 SCIP_CONSHDLR* conshdlr;
18603 SCIP_CONSHDLRDATA* conshdlrdata;
18604 SCIP_CONSDATA* consdata;
18605 SCIP_VAR* var;
18606 SCIP_Real val;
18607 SCIP_Real lb;
18608 SCIP_Real ub;
18609 SCIP_Real poscoeffsum;
18610 SCIP_Real negcoeffsum;
18611 SCIP_Bool infeasible;
18612 SCIP_Bool integral;
18613 int nchgsides = 0;
18614 int nposbin;
18615 int nnegbin;
18616 int nposint;
18617 int nnegint;
18618 int nposimpl;
18619 int nnegimpl;
18620 int nposimplbin;
18621 int nnegimplbin;
18622 int nposcont;
18623 int nnegcont;
18624 int ncoeffspone;
18625 int ncoeffsnone;
18626 int ncoeffspint;
18627 int ncoeffsnint;
18628 int ncoeffspfrac;
18629 int ncoeffsnfrac;
18630 int i;
18631
18632 assert(scip != NULL);
18633 assert(cons != NULL);
18634 assert(upgdcons != NULL);
18635
18636 *upgdcons = NULL;
18637
18638 /* we cannot upgrade a modifiable linear constraint, since we don't know what additional coefficients to expect */
18639 if( SCIPconsIsModifiable(cons) )
18640 return SCIP_OKAY;
18641
18642 /* check for upgradability */
18643 if( SCIPconsGetNUpgradeLocks(cons) > 0 )
18644 return SCIP_OKAY;
18645
18646 /* get the constraint handler and check, if it's really a linear constraint */
18647 conshdlr = SCIPconsGetHdlr(cons);
18648
18650
18651 /* get constraint handler data and constraint data */
18652 conshdlrdata = SCIPconshdlrGetData(conshdlr);
18653 assert(conshdlrdata != NULL);
18654 consdata = SCIPconsGetData(cons);
18655 assert(consdata != NULL);
18656
18657 /* check, if the constraint was already upgraded and will be deleted anyway after preprocessing */
18658 if( consdata->upgraded )
18659 return SCIP_OKAY;
18660
18661 /* check, if the constraint is already stored as LP row */
18662 if( consdata->row != NULL )
18663 {
18664 if( SCIProwIsInLP(consdata->row) )
18665 {
18666 SCIPerrorMessage("cannot upgrade linear constraint that is already stored as row in the LP\n");
18667 return SCIP_INVALIDDATA;
18668 }
18669 else
18670 {
18671 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
18672 }
18673 }
18674
18675 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
18676
18677 /* normalizeCons() can only detect infeasibility when scaling with the gcd. in that case, the scaling was
18678 * skipped and we hope that the infeasibility gets detected later again.
18679 *
18680 * TODO: do we want to try to upgrade the constraint anyway?
18681 *
18682 * TODO: this needs to be fixed on master by changing the API and passing a pointer to whether the constraint is
18683 * proven to be infeasible.
18684 */
18685 if( infeasible ) /*lint !e774*/
18686 return SCIP_OKAY;
18687
18688 /* tighten sides */
18689 SCIP_CALL( tightenSides(scip, cons, &nchgsides, &infeasible) );
18690
18691 if( infeasible ) /*lint !e774*/
18692 return SCIP_OKAY;
18693
18694 /*
18695 * calculate some statistics on linear constraint
18696 */
18697
18698 nposbin = 0;
18699 nnegbin = 0;
18700 nposint = 0;
18701 nnegint = 0;
18702 nposimpl = 0;
18703 nnegimpl = 0;
18704 nposimplbin = 0;
18705 nnegimplbin = 0;
18706 nposcont = 0;
18707 nnegcont = 0;
18708 ncoeffspone = 0;
18709 ncoeffsnone = 0;
18710 ncoeffspint = 0;
18711 ncoeffsnint = 0;
18712 ncoeffspfrac = 0;
18713 ncoeffsnfrac = 0;
18714 integral = TRUE;
18715 poscoeffsum = 0.0;
18716 negcoeffsum = 0.0;
18717
18718 for( i = 0; i < consdata->nvars; ++i )
18719 {
18720 var = consdata->vars[i];
18721 val = consdata->vals[i];
18722 lb = SCIPvarGetLbLocal(var);
18723 ub = SCIPvarGetUbLocal(var);
18724 assert(!SCIPisZero(scip, val));
18725
18727 {
18728 if( SCIPvarIsBinary(var) )
18729 {
18730 if( val >= 0.0 )
18731 ++nposimplbin;
18732 else
18733 ++nnegimplbin;
18734 }
18735 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18736 integral = integral && SCIPisIntegral(scip, val);
18737 if( val >= 0.0 )
18738 ++nposimpl;
18739 else
18740 ++nnegimpl;
18741 }
18742 else
18743 {
18744 switch( SCIPvarGetType(var) )
18745 {
18747 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18748 integral = integral && SCIPisIntegral(scip, val);
18749 if( val >= 0.0 )
18750 ++nposbin;
18751 else
18752 ++nnegbin;
18753 break;
18755 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18756 integral = integral && SCIPisIntegral(scip, val);
18757 if( val >= 0.0 )
18758 ++nposint;
18759 else
18760 ++nnegint;
18761 break;
18763 integral = integral && SCIPisEQ(scip, lb, ub) && SCIPisIntegral(scip, val * lb);
18764 if( val >= 0.0 )
18765 ++nposcont;
18766 else
18767 ++nnegcont;
18768 break;
18769 default:
18770 SCIPerrorMessage("unknown variable type\n");
18771 return SCIP_INVALIDDATA;
18772 } /*lint !e788*/
18773 }
18774
18775 if( SCIPisEQ(scip, val, 1.0) )
18776 ncoeffspone++;
18777 else if( SCIPisEQ(scip, val, -1.0) )
18778 ncoeffsnone++;
18779 else if( SCIPisIntegral(scip, val) )
18780 {
18781 if( SCIPisPositive(scip, val) )
18782 ncoeffspint++;
18783 else
18784 ncoeffsnint++;
18785 }
18786 else
18787 {
18788 if( SCIPisPositive(scip, val) )
18789 ncoeffspfrac++;
18790 else
18791 ncoeffsnfrac++;
18792 }
18793 if( SCIPisPositive(scip, val) )
18794 poscoeffsum += val;
18795 else
18796 negcoeffsum += val;
18797 }
18798
18799 /*
18800 * call the upgrading methods
18801 */
18802
18803 SCIPdebugMsg(scip, "upgrading linear constraint <%s> (%d upgrade methods):\n",
18804 SCIPconsGetName(cons), conshdlrdata->nlinconsupgrades);
18805 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",
18806 nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposcont, nnegcont,
18807 ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18808 poscoeffsum, negcoeffsum, integral);
18809
18810 /* try all upgrading methods in priority order in case the upgrading step is enable */
18811 for( i = 0; i < conshdlrdata->nlinconsupgrades && *upgdcons == NULL; ++i )
18812 {
18813 if( conshdlrdata->linconsupgrades[i]->active )
18814 {
18815 SCIP_CALL( conshdlrdata->linconsupgrades[i]->linconsupgd(scip, cons, consdata->nvars,
18816 consdata->vars, consdata->vals, consdata->lhs, consdata->rhs,
18817 nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposimplbin, nnegimplbin, nposcont, nnegcont,
18818 ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18819 poscoeffsum, negcoeffsum, integral,
18820 upgdcons) );
18821 }
18822 }
18823
18824#ifdef SCIP_DEBUG
18825 if( *upgdcons != NULL )
18826 {
18828 SCIPdebugMsg(scip, " -> upgraded to constraint type <%s>\n", SCIPconshdlrGetName(SCIPconsGetHdlr(*upgdcons)));
18829 SCIPdebugPrintCons(scip, *upgdcons, NULL);
18830 }
18831#endif
18832
18833 return SCIP_OKAY; /*lint !e438*/
18834}
18835
18836/** cleans up (multi-)aggregations and fixings from linear constraints */
18838 SCIP* scip, /**< SCIP data structure */
18839 SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
18840 SCIP_Bool* infeasible, /**< pointer to return whether the problem was detected to be infeasible */
18841 int* ndelconss /**< pointer to count number of deleted constraints */
18842 )
18843{
18844 SCIP_CONSHDLR* conshdlr;
18845 SCIP_CONS** conss;
18846 int nconss;
18847 int i;
18848
18849 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
18850 if( conshdlr == NULL )
18851 return SCIP_OKAY;
18852
18853 assert(infeasible != NULL);
18854 *infeasible = FALSE;
18855
18856 nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr);
18857 conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);
18858
18859 /* loop backwards since then deleted constraints do not interfere with the loop */
18860 for( i = nconss - 1; i >= 0; --i )
18861 {
18862 SCIP_CALL( applyFixings(scip, conss[i], infeasible) );
18863
18864 if( *infeasible )
18865 break;
18866
18867 if( SCIPconsGetData(conss[i])->nvars >= 1 )
18868 continue;
18869
18870 SCIP_CALL( SCIPdelCons(scip, conss[i]) );
18871 ++(*ndelconss);
18872 }
18873
18874 return SCIP_OKAY;
18875}
static long bound
#define EVENTHDLR_NAME
SCIP_VAR * w
SCIP_VAR * a
SCIP_VAR ** b
SCIP_VAR ** x
#define EVENTHDLR_DESC
enum Proprule PROPRULE
Definition cons_and.c:172
#define DEFAULT_DUALPRESOLVING
Definition cons_and.c:109
#define CONSHDLR_NEEDSCONS
Definition cons_and.c:96
#define CONSHDLR_SEPAFREQ
Definition cons_and.c:89
#define CONSHDLR_CHECKPRIORITY
Definition cons_and.c:88
#define CONSHDLR_DESC
Definition cons_and.c:85
#define CONSHDLR_PROP_TIMING
Definition cons_and.c:99
#define CONSHDLR_MAXPREROUNDS
Definition cons_and.c:93
#define DEFAULT_PRESOLPAIRWISE
Definition cons_and.c:104
#define CONSHDLR_SEPAPRIORITY
Definition cons_and.c:86
Proprule
Definition cons_and.c:165
@ PROPRULE_INVALID
Definition cons_and.c:166
#define DEFAULT_PRESOLUSEHASHING
Definition cons_and.c:112
#define CONSHDLR_PROPFREQ
Definition cons_and.c:90
#define CONSHDLR_PRESOLTIMING
Definition cons_and.c:98
#define CONSHDLR_EAGERFREQ
Definition cons_and.c:91
#define CONSHDLR_ENFOPRIORITY
Definition cons_and.c:87
#define CONSHDLR_DELAYSEPA
Definition cons_and.c:94
#define CONSHDLR_NAME
Definition cons_and.c:84
#define CONSHDLR_DELAYPROP
Definition cons_and.c:95
#define CONFLICTHDLR_PRIORITY
#define CONFLICTHDLR_NAME
#define CONFLICTHDLR_DESC
struct InferInfo INFERINFO
#define DEFAULT_MAXROUNDSROOT
#define DEFAULT_SORTVARS
#define DEFAULT_MAXSEPACUTSROOT
@ PROPRULE_1_RANGEDROW
@ PROPRULE_1_LHS
@ PROPRULE_1_RHS
#define DEFAULT_MAXSEPACUTS
#define DEFAULT_TIGHTENBOUNDSFREQ
#define DEFAULT_MAXROUNDS
static int getInferInt(PROPRULE proprule, int pos)
#define MAXTIGHTENROUNDS
#define DEFAULT_DETECTCUTOFFBOUND
#define DEFAULT_MAXCARDBOUNDDIST
#define DEFAULT_SIMPLIFYINEQUALITIES
#define DEFAULT_DETECTLOWERBOUND
Constraint handler for knapsack constraints of the form , x binary and .
#define MAX_CLIQUE_NONZEROS_PER_CONS
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_EXTRACTCLIQUES
static void permSortConsdata(SCIP_CONSDATA *consdata, int *perm, int nvars)
static void consdataRecomputeMaxActivityDelta(SCIP *scip, SCIP_CONSDATA *consdata)
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)
static void consdataGetReliableResidualActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *cancelvar, SCIP_Real *resactivity, SCIP_Bool isminresact, SCIP_Bool useglobalbounds)
static SCIP_RETCODE convertEquality(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss, int *nchgvartypes)
static SCIP_Bool checkEqualObjective(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real *scale, SCIP_Real *offset)
#define 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 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)
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)
static SCIP_RETCODE fullDualPresolve(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_Bool *cutoff, int *nchgbds, int *nchgvartypes)
static SCIP_RETCODE convertLongEquality(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_CONS *cons, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss, int *nchgvartypes)
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)
static void conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
static void calculateMinvalAndMaxval(SCIP *scip, SCIP_Real side, SCIP_Real val, SCIP_Real minresactivity, SCIP_Real maxresactivity, SCIP_Real *minval, SCIP_Real *maxval)
static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
static void consdataRecomputeGlbMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
static void consdataUpdateActivitiesUb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldub, SCIP_Real newub, SCIP_Real val, SCIP_Bool checkreliability)
static SCIP_RETCODE tightenSides(SCIP *scip, SCIP_CONS *cons, int *nchgsides, SCIP_Bool *infeasible)
static void consdataUpdateActivitiesGlbLb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real val, SCIP_Bool checkreliability)
static void consdataUpdateActivitiesLb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real val, SCIP_Bool checkreliability)
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_MAXAGGRNORMSCALE
static SCIP_RETCODE performVarDeletions(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss)
#define checkMaxActivityDelta(scip, consdata)
static SCIP_Bool isFiniteNonnegativeIntegral(SCIP *scip, SCIP_Real x)
#define DEFAULT_SINGLETONSTUFFING
static void consdataUpdateSignatures(SCIP_CONSDATA *consdata, int pos)
#define MINVALRECOMP
#define DEFAULT_MAXEASYACTIVITYDELTA
static SCIP_RETCODE scaleCons(SCIP *scip, SCIP_CONS *cons, SCIP_Real scalar)
static int inferInfoGetPos(INFERINFO inferinfo)
static SCIP_RETCODE detectRedundantConstraints(SCIP *scip, BMS_BLKMEM *blkmem, SCIP_CONS **conss, int nconss, int *firstchange, SCIP_Bool *cutoff, int *ndelconss, int *nchgsides)
#define DEFAULT_CHECKRELMAXABS
#define DEFAULT_MAXDUALMULTAGGRQUOT
static void linconsupgradeFree(SCIP *scip, SCIP_LINCONSUPGRADE **linconsupgrade)
static SCIP_RETCODE aggregateConstraints(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1, int *commonidx0, int *commonidx1, int *diffidx0minus1, int *diffidx1minus0, int nvarscommon, int commonidxweight, int diffidx0minus1weight, int diffidx1minus0weight, SCIP_Real maxaggrnormscale, int *nchgcoefs, SCIP_Bool *aggregated, SCIP_Bool *infeasible)
static SCIP_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons, SCIP_Bool reasonisrhs)
static SCIP_RETCODE rangedRowPropagation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *nchgbds, int *naddconss)
static INFERINFO intToInferInfo(int i)
static SCIP_RETCODE mergeMultiples(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE separateCons(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_SOL *sol, SCIP_Bool separatecards, SCIP_Bool separateall, int *ncuts, SCIP_Bool *cutoff)
static SCIP_RETCODE addSymmetryInformation(SCIP *scip, SYM_SYMTYPE symtype, SCIP_CONS *cons, SYM_GRAPH *graph, SCIP_Bool *success)
static void consdataGetActivityBounds(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Bool goodrelax, SCIP_Real *minactivity, SCIP_Real *maxactivity, SCIP_Bool *ismintight, SCIP_Bool *ismaxtight, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
static void consdataCheckNonbinvar(SCIP_CONSDATA *consdata)
static SCIP_RETCODE chgLhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
#define DEFAULT_MAXMULTAGGRQUOT
static void consdataUpdateActivitiesGlbUb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldub, SCIP_Real newub, SCIP_Real val, SCIP_Bool checkreliability)
static SCIP_RETCODE consCatchEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
static void consdataCalcMinAbsval(SCIP_CONSDATA *consdata)
static SCIP_RETCODE addConflictBounds(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, int inferpos, SCIP_Bool reasonisrhs)
#define MAXCONSPRESOLROUNDS
static SCIP_RETCODE consdataEnsureVarsSize(SCIP *scip, SCIP_CONSDATA *consdata, int num)
#define MAXACTVAL
#define NONLINCONSUPGD_PRIORITY
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)
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 updateCutoffbound(SCIP *scip, SCIP_CONS *cons, SCIP_Real primalbound)
static void consdataUpdateDelCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
#define DEFAULT_RANGEDROWARTCONS
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, int pos)
#define MAXSCALEDCOEFINTEGER
static void consdataUpdateAddCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
static void getMinActivity(SCIP *scip, SCIP_CONSDATA *consdata, int posinf, int neginf, int poshuge, int neghuge, SCIP_Real delta, SCIP_Bool global, SCIP_Bool goodrelax, SCIP_Real *minactivity, SCIP_Bool *istight, SCIP_Bool *issettoinfinity)
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
#define BINWEIGHT
static SCIP_RETCODE chgRhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
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 unsigned int getParallelConsKey(SCIP_CONS *cons)
#define CONTWEIGHT
static SCIP_RETCODE fixVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars)
#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 void consdataGetActivityResiduals(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool goodrelax, SCIP_Real *minresactivity, SCIP_Real *maxresactivity, SCIP_Bool *ismintight, SCIP_Bool *ismaxtight, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
static SCIP_Real consdataGetMaxAbsval(SCIP_CONSDATA *consdata)
static SCIP_RETCODE addNlrow(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE consPrintConsSol(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, FILE *file)
static void getMaxActivity(SCIP *scip, SCIP_CONSDATA *consdata, int posinf, int neginf, int poshuge, int neghuge, SCIP_Real delta, SCIP_Bool global, SCIP_Bool goodrelax, SCIP_Real *maxactivity, SCIP_Bool *istight, SCIP_Bool *issettoinfinity)
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)
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)
static void consdataGetGlbActivityResiduals(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool goodrelax, SCIP_Real *minresactivity, SCIP_Real *maxresactivity, SCIP_Bool *ismintight, SCIP_Bool *ismaxtight, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
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)
static SCIP_RETCODE dualPresolve(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss, int *nchgvartypes)
#define DEFAULT_MINGAINPERNMINCOMP
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)
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, int *naddconss)
#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)
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 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)
static SCIP_RETCODE checkPartialObjective(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata)
#define MAXVALRECOMP
static void consdataGetGlbActivityBounds(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Bool goodrelax, SCIP_Real *glbminactivity, SCIP_Real *glbmaxactivity, SCIP_Bool *ismintight, SCIP_Bool *ismaxtight, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
static SCIP_Bool canTightenBounds(SCIP_CONS *cons)
#define DEFAULT_SEPARATEALL
static void findOperators(const char *str, char **firstoperator, char **secondoperator, SCIP_Bool *success)
static INFERINFO getInferInfo(PROPRULE proprule, int pos)
Constraint handler for linear constraints in their most general form, .
constraint handler for nonlinear constraints specified by algebraic expressions
defines macros for basic operations in double-double arithmetic giving roughly twice the precision of...
#define QUAD_MEMBER(x)
Definition dbldblarith.h:48
#define SCIPquadprecSumQD(r, a, b)
Definition dbldblarith.h:62
#define QUAD_ASSIGN(a, constant)
Definition dbldblarith.h:51
#define QUAD(x)
Definition dbldblarith.h:47
#define QUAD_ASSIGN_Q(a, b)
Definition dbldblarith.h:52
#define QUAD_TO_DBL(x)
Definition dbldblarith.h:49
methods for debugging
#define SCIPdebugGetSolVal(scip, var, val)
Definition debug.h:313
#define SCIPdebugAddSolVal(scip, var, val)
Definition debug.h:312
#define NULL
Definition def.h:257
#define SCIP_MAXSTRLEN
Definition def.h:278
#define COPYSIGN
Definition def.h:248
#define SCIP_Longint
Definition def.h:150
#define SCIP_MAXTREEDEPTH
Definition def.h:306
#define SCIP_REAL_MAX
Definition def.h:167
#define SCIP_INVALID
Definition def.h:187
#define SCIP_Bool
Definition def.h:100
#define MIN(x, y)
Definition def.h:233
#define MAX3(x, y, z)
Definition def.h:237
#define SCIP_STRINGEQ(name, reference, retcode)
Definition def.h:454
#define SCIP_Real
Definition def.h:165
#define ABS(x)
Definition def.h:225
#define TRUE
Definition def.h:102
#define FALSE
Definition def.h:103
#define MAX(x, y)
Definition def.h:229
#define SCIP_CALL_ABORT(x)
Definition def.h:343
#define SCIP_LONGINT_FORMAT
Definition def.h:157
#define MIN3(x, y, z)
Definition def.h:241
#define SCIPABORT()
Definition def.h:336
#define REALABS(x)
Definition def.h:191
#define EPSGT(x, y, eps)
Definition def.h:195
#define SCIP_CALL(x)
Definition def.h:364
SCIP_RETCODE SCIPcreateRowLinear(SCIP *scip, SCIP_CONS *cons)
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 SCIPcleanupConssLinear(SCIP *scip, SCIP_Bool onlychecked, SCIP_Bool *infeasible, int *ndelconss)
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 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)
struct SCIP_LinConsUpgrade SCIP_LINCONSUPGRADE
Definition cons_linear.h:87
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:2052
SCIP_Bool SCIPisConsCompressionEnabled(SCIP *scip)
Definition scip_copy.c:662
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:713
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:2616
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition scip_prob.c:1907
SCIP_RETCODE SCIPaddConsUpgrade(SCIP *scip, SCIP_CONS *oldcons, SCIP_CONS **newcons)
Definition scip_prob.c:3368
int SCIPgetNContVars(SCIP *scip)
Definition scip_prob.c:2569
SCIP_CONS ** SCIPgetConss(SCIP *scip)
Definition scip_prob.c:3666
SCIP_RETCODE SCIPaddObjoffset(SCIP *scip, SCIP_Real addval)
Definition scip_prob.c:1443
int SCIPgetNVars(SCIP *scip)
Definition scip_prob.c:2246
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition scip_prob.c:3420
int SCIPgetNConss(SCIP *scip)
Definition scip_prob.c:3620
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition scip_prob.c:2201
int SCIPgetNBinVars(SCIP *scip)
Definition scip_prob.c:2293
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition misc.c:2348
#define SCIPhashFour(a, b, c, d)
Definition pub_misc.h:573
SCIP_RETCODE SCIPhashtableSafeInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition misc.c:2567
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:2298
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition misc.c:2596
void SCIPhashtablePrintStatistics(SCIP_HASHTABLE *hashtable, SCIP_MESSAGEHDLR *messagehdlr)
Definition misc.c:2792
SCIP_RETCODE SCIPhashtableRemove(SCIP_HASHTABLE *hashtable, void *element)
Definition misc.c:2665
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition misc.c:2535
#define SCIPhashSignature64(a)
Definition pub_misc.h:566
SCIP_RETCODE SCIPupdateLocalLowerbound(SCIP *scip, SCIP_Real newbound)
Definition scip_prob.c:4289
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition scip_prob.c:4067
SCIP_Real SCIPgetLocalLowerbound(SCIP *scip)
Definition scip_prob.c:4178
SCIP_RETCODE SCIPaddConflict(SCIP *scip, SCIP_NODE *node, SCIP_CONS **cons, SCIP_NODE *validnode, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
Definition scip_prob.c:3806
SCIP_RETCODE SCIPaddConsLocal(SCIP *scip, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition scip_prob.c:3986
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:9197
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition misc.c:9449
SCIP_Real SCIPselectSimpleValue(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom)
Definition misc.c:10041
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *numerator, SCIP_Longint *denominator)
Definition misc.c:9470
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition misc.c:11162
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
void SCIPswapPointers(void **pointer1, void **pointer2)
Definition misc.c:10511
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:4802
void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
Definition cons.c:4350
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:4759
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:5286
SCIP_RETCODE SCIPsetConshdlrGetSignedPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:924
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4782
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4320
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:940
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:4340
int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4816
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:4739
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:8423
int SCIPconsGetPos(SCIP_CONS *cons)
Definition cons.c:8403
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition cons.c:8652
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition cons.c:8413
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition cons.c:8562
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition scip_cons.c:2536
int SCIPconsGetNUpgradeLocks(SCIP_CONS *cons)
Definition cons.c:8845
SCIP_RETCODE SCIPsetConsSeparated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool separate)
Definition scip_cons.c:1296
SCIP_Bool SCIPconsIsMarkedPropagate(SCIP_CONS *cons)
Definition cons.c:8602
SCIP_Bool SCIPconsIsOriginal(SCIP_CONS *cons)
Definition cons.c:8692
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition cons.c:8592
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition cons.c:8522
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition cons.c:8702
int SCIPconsGetNLocksPos(SCIP_CONS *cons)
Definition cons.c:8742
SCIP_RETCODE SCIPsetConsInitial(SCIP *scip, SCIP_CONS *cons, SCIP_Bool initial)
Definition scip_cons.c:1271
SCIP_RETCODE SCIPsetConsEnforced(SCIP *scip, SCIP_CONS *cons, SCIP_Bool enforce)
Definition scip_cons.c:1321
SCIP_Bool SCIPconsIsLockedType(SCIP_CONS *cons, SCIP_LOCKTYPE locktype)
Definition cons.c:8786
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition cons.c:8582
SCIP_RETCODE SCIPunmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition scip_cons.c:2042
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition cons.c:8454
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:997
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition cons.c:8612
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition cons.c:8632
int SCIPconsGetNLocksNeg(SCIP_CONS *cons)
Definition cons.c:8752
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition cons.c:8393
SCIP_Bool SCIPconsIsLocked(SCIP_CONS *cons)
Definition cons.c:8732
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition scip_cons.c:1812
SCIP_RETCODE SCIPmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition scip_cons.c:2014
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition cons.c:8642
SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
Definition scip_cons.c:1524
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition cons.c:8672
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition scip_cons.c:1173
SCIP_RETCODE SCIPsetConsPropagated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool propagate)
Definition scip_cons.c:1371
SCIP_RETCODE SCIPsetConsChecked(SCIP *scip, SCIP_CONS *cons, SCIP_Bool check)
Definition scip_cons.c:1346
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition cons.c:8572
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition scip_cons.c:1784
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition cons.c:8662
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition scip_cut.c:225
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition scip_event.c:111
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition event.c:396
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition event.c:1194
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition scip_event.c:367
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition scip_event.c:413
SCIP_Real SCIPeventGetOldbound(SCIP_EVENT *event)
Definition event.c:1391
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition event.c:1217
SCIP_IMPLINTTYPE SCIPeventGetOldImpltype(SCIP_EVENT *event)
Definition event.c:1496
SCIP_Real SCIPeventGetNewbound(SCIP_EVENT *event)
Definition event.c:1415
SCIP_VARTYPE SCIPeventGetOldtype(SCIP_EVENT *event)
Definition event.c:1462
int SCIPexprGetNChildren(SCIP_EXPR *expr)
Definition expr.c:3872
SCIP_Bool SCIPisExprSum(SCIP *scip, SCIP_EXPR *expr)
Definition scip_expr.c:1479
SCIP_Real * SCIPgetCoefsExprSum(SCIP_EXPR *expr)
Definition expr_sum.c:1554
SCIP_Bool SCIPisExprVar(SCIP *scip, SCIP_EXPR *expr)
Definition scip_expr.c:1457
SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
Definition expr.c:3882
SCIP_Real SCIPgetConstantExprSum(SCIP_EXPR *expr)
Definition expr_sum.c:1569
SCIP_VAR * SCIPgetVarExprVar(SCIP_EXPR *expr)
Definition expr_var.c:423
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition scip_lp.c:87
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:110
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition scip_mem.c:57
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:1953
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:8288
void SCIPlinConsStatsReset(SCIP_LINCONSSTATS *linconsstats)
Definition cons.c:8257
SCIP_Bool SCIProwIsModifiable(SCIP_ROW *row)
Definition lp.c:17805
SCIP_RETCODE SCIPchgRowLhs(SCIP *scip, SCIP_ROW *row, SCIP_Real lhs)
Definition scip_lp.c:1529
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:1398
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition scip_lp.c:1646
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition scip_lp.c:2176
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition scip_lp.c:2131
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition scip_lp.c:1508
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition lp.c:17719
SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
Definition scip_lp.c:1553
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition lp.c:17917
SCIP_RETCODE SCIPaddVarsToRow(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition scip_lp.c:1672
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition lp.c:17706
SCIP_Real SCIPgetRowSolActivity(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition scip_lp.c:2108
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition scip_sol.c:1763
void SCIPupdateSolLPConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
Definition scip_sol.c:467
SCIP_RETCODE SCIPupdateCutoffbound(SCIP *scip, SCIP_Real cutoffbound)
int SCIPgetNSepaRounds(SCIP *scip)
SCIP_Real SCIPgetLowerbound(SCIP *scip)
int SCIPgetNRuns(SCIP *scip)
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
SCIP_Longint SCIPgetNConflictConssApplied(SCIP *scip)
SCIP_Bool SCIPisUbBetter(SCIP *scip, SCIP_Real newub, SCIP_Real oldlb, SCIP_Real oldub)
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisSumRelLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisSumRelEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLbBetter(SCIP *scip, SCIP_Real newlb, SCIP_Real oldlb, SCIP_Real oldub)
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisHugeValue(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeastol(SCIP *scip)
SCIP_Real SCIPgetHugeValue(SCIP *scip)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisSumRelGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisScalingIntegral(SCIP *scip, SCIP_Real val, SCIP_Real scalar)
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPcutoffbounddelta(SCIP *scip)
SCIP_Bool SCIPisUpdateUnreliable(SCIP *scip, SCIP_Real newvalue, SCIP_Real oldvalue)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPepsilon(SCIP *scip)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisSumGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPparseReal(SCIP *scip, const char *str, SCIP_Real *value, char **endptr)
SCIP_Bool SCIPinRepropagation(SCIP *scip)
Definition scip_tree.c:146
int SCIPgetDepth(SCIP *scip)
Definition scip_tree.c:672
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition var.c:23546
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition scip_var.c:6401
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition var.c:18365
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition var.c:23566
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition scip_var.c:5210
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition var.c:23875
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition var.c:23900
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition var.c:23674
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition var.c:23510
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:8882
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition scip_var.c:2119
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition var.c:23418
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4380
SCIP_Bool SCIPdoNotAggr(SCIP *scip)
Definition scip_var.c:10909
SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
Definition var.c:23530
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24300
SCIP_Bool SCIPdoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:10942
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition var.c:23462
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:10550
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:7069
SCIP_Bool SCIPvarIsNonimpliedIntegral(SCIP_VAR *var)
Definition var.c:23538
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition var.c:23932
SCIP_RETCODE SCIPchgVarImplType(SCIP *scip, SCIP_VAR *var, SCIP_IMPLINTTYPE impltype, SCIP_Bool *infeasible)
Definition scip_var.c:10218
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition scip_var.c:6651
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition var.c:23485
SCIP_RETCODE SCIPgetProbvarSum(SCIP *scip, SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition scip_var.c:2499
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition var.c:24174
int SCIPvarGetIndex(SCIP_VAR *var)
Definition var.c:23684
SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
Definition scip_var.c:5118
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition scip_var.c:5296
SCIP_RETCODE SCIPcreateVarImpl(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_IMPLINTTYPE impltype, 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:225
SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition scip_var.c:2872
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition var.c:23694
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:23299
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:10834
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24961
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition scip_var.c:1887
SCIP_Real SCIPadjustedVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real ub)
Definition scip_var.c:5634
SCIP_Real SCIPvarGetBestBoundLocal(SCIP_VAR *var)
Definition var.c:24344
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:899
SCIP_RETCODE SCIPgetProbvarLinearSum(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize)
Definition scip_var.c:2378
SCIP_Real SCIPadjustedVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real lb)
Definition scip_var.c:5570
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition var.c:23522
SCIP_RETCODE SCIPchgVarType(SCIP *scip, SCIP_VAR *var, SCIP_VARTYPE vartype, SCIP_Bool *infeasible)
Definition scip_var.c:10113
SCIP_RETCODE SCIPflattenVarAggregationGraph(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:2332
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition var.c:23838
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition var.c:23826
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:8740
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition var.c:23556
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24266
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition var.c:23475
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition var.c:23632
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition var.c:23449
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition var.c:24152
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition scip_var.c:10318
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:6964
SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition scip_var.c:2736
SCIP_IMPLINTTYPE SCIPvarGetImplType(SCIP_VAR *var)
Definition var.c:23495
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition var.c:17319
SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
Definition scip_var.c:361
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition scip_var.c:5372
SCIP_RETCODE SCIPwriteVarsLinearsum(SCIP *scip, FILE *file, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_Bool type)
Definition scip_var.c:474
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24951
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4322
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition scip_var.c:2078
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:1853
SCIP_Bool SCIPallowStrongDualReds(SCIP *scip)
Definition scip_var.c:10984
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:6895
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition var.c:23850
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:5581
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition misc.c:10827
SCIP_RETCODE SCIPskipSpace(char **s)
Definition misc.c:10816
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)
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
static const SCIP_Real scalars[]
Definition lp.c:5959
static const char * paramname[]
Definition lpi_msk.c:5172
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
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
#define SCIPisFinite(x)
Definition pub_misc.h:82
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
static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
Main separation function.
SCIP_DECL_LINCONSUPGD((*linconsupgd))
structs for symmetry computations
methods for dealing with symmetry detection graphs
struct SCIP_Conflicthdlr SCIP_CONFLICTHDLR
#define SCIP_DECL_CONFLICTEXEC(x)
@ SCIP_CONFTYPE_PROPAGATION
#define SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(x)
Definition type_cons.h:956
#define SCIP_DECL_CONSGETPERMSYMGRAPH(x)
Definition type_cons.h:938
#define SCIP_DECL_CONSENFOLP(x)
Definition type_cons.h:363
#define SCIP_DECL_CONSDELETE(x)
Definition type_cons.h:229
struct SCIP_Cons SCIP_CONS
Definition type_cons.h:63
#define SCIP_DECL_CONSEXIT(x)
Definition type_cons.h:136
#define SCIP_DECL_CONSGETVARS(x)
Definition type_cons.h:867
#define SCIP_DECL_CONSINITSOL(x)
Definition type_cons.h:201
#define SCIP_DECL_CONSPRINT(x)
Definition type_cons.h:769
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition type_cons.h:64
#define SCIP_DECL_CONSSEPALP(x)
Definition type_cons.h:288
struct SYM_Graph SYM_GRAPH
Definition type_cons.h:68
#define SCIP_DECL_CONSENFORELAX(x)
Definition type_cons.h:388
struct SCIP_LinConsStats SCIP_LINCONSSTATS
Definition type_cons.h:67
#define SCIP_DECL_CONSPROP(x)
Definition type_cons.h:506
#define SCIP_DECL_CONSGETNVARS(x)
Definition type_cons.h:885
#define SCIP_DECL_CONSRESPROP(x)
Definition type_cons.h:612
@ 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:691
#define SCIP_DECL_CONSENFOPS(x)
Definition type_cons.h:431
#define SCIP_DECL_CONSPARSE(x)
Definition type_cons.h:845
#define SCIP_DECL_CONSTRANS(x)
Definition type_cons.h:239
#define SCIP_DECL_CONSDEACTIVE(x)
Definition type_cons.h:706
#define SCIP_DECL_CONSPRESOL(x)
Definition type_cons.h:561
#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:676
struct SCIP_Conshdlr SCIP_CONSHDLR
Definition type_cons.h:62
#define SCIP_DECL_CONSCOPY(x)
Definition type_cons.h:810
#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
#define SCIP_DECL_CONSDELVARS(x)
Definition type_cons.h:753
struct SCIP_Eventhdlr SCIP_EVENTHDLR
Definition type_event.h:159
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition type_event.h:127
#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:122
struct SCIP_EventData SCIP_EVENTDATA
Definition type_event.h:179
#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:259
#define SCIP_EVENTTYPE_FORMAT
Definition type_event.h:157
#define SCIP_EVENTTYPE_GLBCHANGED
Definition type_event.h:75
#define SCIP_EVENTTYPE_BOUNDRELAXED
Definition type_event.h:126
#define SCIP_EVENTTYPE_LBCHANGED
Definition type_event.h:123
#define SCIP_EVENTTYPE_UBCHANGED
Definition type_event.h:124
uint64_t SCIP_EVENTTYPE
Definition type_event.h:156
#define SCIP_EVENTTYPE_IMPLTYPECHANGED
Definition type_event.h:87
#define SCIP_EVENTTYPE_DISABLED
Definition type_event.h:67
#define SCIP_EVENTTYPE_BOUNDTIGHTENED
Definition type_event.h:125
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition type_event.h:77
struct SCIP_Expr SCIP_EXPR
Definition type_expr.h:55
@ SCIP_EXPRCURV_LINEAR
Definition type_expr.h:65
struct SCIP_Row SCIP_ROW
Definition type_lp.h:105
@ SCIP_BOUNDTYPE_UPPER
Definition type_lp.h:58
@ SCIP_BOUNDTYPE_LOWER
Definition type_lp.h:57
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition type_lp.h:60
@ SCIP_VERBLEVEL_HIGH
struct SCIP_HashMap SCIP_HASHMAP
Definition type_misc.h:106
#define SCIP_DECL_HASHKEYEQ(x)
Definition type_misc.h:195
#define SCIP_DECL_SORTINDCOMP(x)
Definition type_misc.h:181
#define SCIP_DECL_HASHGETKEY(x)
Definition type_misc.h:192
#define SCIP_DECL_HASHKEYVAL(x)
Definition type_misc.h:198
struct SCIP_HashTable SCIP_HASHTABLE
Definition type_misc.h:88
struct SCIP_NlRow SCIP_NLROW
Definition type_nlp.h:41
@ 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
@ SCIP_INVALIDCALL
@ SCIP_ERROR
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
@ SCIP_STAGE_PROBLEM
Definition type_set.h:45
@ SCIP_STAGE_PRESOLVING
Definition type_set.h:49
@ 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
struct SCIP_Sol SCIP_SOL
Definition type_sol.h:57
enum SYM_Symtype SYM_SYMTYPE
@ SYM_SYMTYPE_SIGNPERM
@ SYM_SYMTYPE_PERM
#define SCIP_PRESOLTIMING_EXHAUSTIVE
Definition type_timing.h:54
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
#define NLOCKTYPES
Definition type_var.h:138
enum SCIP_ImplintType SCIP_IMPLINTTYPE
Definition type_var.h:117
@ SCIP_IMPLINTTYPE_NONE
Definition type_var.h:90
@ SCIP_IMPLINTTYPE_STRONG
Definition type_var.h:106
@ SCIP_IMPLINTTYPE_WEAK
Definition type_var.h:91
struct SCIP_BdChgIdx SCIP_BDCHGIDX
Definition type_var.h:151
#define SCIP_DEPRECATED_VARTYPE_IMPLINT
Definition type_var.h:79
@ SCIP_VARTYPE_INTEGER
Definition type_var.h:65
@ SCIP_VARTYPE_CONTINUOUS
Definition type_var.h:71
@ SCIP_VARTYPE_BINARY
Definition type_var.h:64
@ SCIP_VARSTATUS_ORIGINAL
Definition type_var.h:51
@ SCIP_VARSTATUS_FIXED
Definition type_var.h:54
@ SCIP_VARSTATUS_COLUMN
Definition type_var.h:53
@ SCIP_VARSTATUS_MULTAGGR
Definition type_var.h:56
@ SCIP_VARSTATUS_NEGATED
Definition type_var.h:57
@ SCIP_VARSTATUS_AGGREGATED
Definition type_var.h:55
@ SCIP_VARSTATUS_LOOSE
Definition type_var.h:52
enum SCIP_LockType SCIP_LOCKTYPE
Definition type_var.h:144
@ SCIP_LOCKTYPE_MODEL
Definition type_var.h:141
enum SCIP_Vartype SCIP_VARTYPE
Definition type_var.h:73
enum SCIP_Varstatus SCIP_VARSTATUS
Definition type_var.h:59