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 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4107
4108 /* iterate over all constraints */
4109 for( i = 0; i < nconss; i++ )
4110 {
4111 consdata = SCIPconsGetData(conss[i]);
4112
4113 /* constraint is marked, that some of its variables were deleted */
4114 if( consdata->varsdeleted )
4115 {
4116 /* iterate over all variables of the constraint and delete them from the constraint */
4117 for( v = consdata->nvars - 1; v >= 0; --v )
4118 {
4119 if( SCIPvarIsDeleted(consdata->vars[v]) )
4120 {
4121 SCIP_CALL( delCoefPos(scip, conss[i], v) );
4122 }
4123 }
4124 consdata->varsdeleted = FALSE;
4125 }
4126 }
4127
4128 return SCIP_OKAY;
4129}
4130
4131
4132/** normalizes a linear constraint with the following rules:
4133 * - if all coefficients have them same absolute value, change them to (-)1.0
4134 * - multiplication with +1 or -1:
4135 * Apply the following rules in the given order, until the sign of the factor is determined. Later rules only apply,
4136 * if the current rule doesn't determine the sign):
4137 * 1. the right hand side must not be negative
4138 * 2. the right hand side must not be infinite
4139 * 3. the absolute value of the right hand side must be greater than that of the left hand side
4140 * 4. the number of positive coefficients must not be smaller than the number of negative coefficients
4141 * 5. multiply with +1
4142 * - rationals to integrals
4143 * Try to identify a rational representation of the fractional coefficients, and multiply all coefficients
4144 * by the smallest common multiple of all denominators to get integral coefficients.
4145 * Forbid large denominators due to numerical stability.
4146 * - division by greatest common divisor
4147 * If all coefficients are integral, divide them by the greatest common divisor.
4148 */
4149static
4151 SCIP* scip, /**< SCIP data structure */
4152 SCIP_CONS* cons, /**< linear constraint to normalize */
4153 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
4154 )
4155{
4156 SCIP_CONSDATA* consdata;
4157 SCIP_Real* vals;
4158 SCIP_Longint scm;
4159 SCIP_Longint numerator;
4160 SCIP_Longint denominator;
4161 SCIP_Longint gcd;
4162 SCIP_Longint maxmult;
4163 SCIP_Real epsilon;
4164 SCIP_Real feastol;
4165 SCIP_Real maxabsval;
4166 SCIP_Real minabsval;
4167 SCIP_Bool success;
4168 SCIP_Bool onlyintegral;
4169 int nvars;
4170 int mult;
4171 int nposcoeffs;
4172 int nnegcoeffs;
4173 int i;
4174
4175 assert(scip != NULL);
4176 assert(cons != NULL);
4177 assert(infeasible != NULL);
4178
4179 *infeasible = FALSE;
4180
4181 /* we must not change a modifiable constraint in any way */
4182 if( SCIPconsIsModifiable(cons) )
4183 return SCIP_OKAY;
4184
4185 /* get constraint data */
4186 consdata = SCIPconsGetData(cons);
4187 assert(consdata != NULL);
4188
4189 /* check, if the constraint is already normalized */
4190 if( consdata->normalized )
4191 return SCIP_OKAY;
4192
4193 /* get coefficient arrays */
4194 vals = consdata->vals;
4195 nvars = consdata->nvars;
4196 assert(nvars == 0 || vals != NULL);
4197
4198 if( nvars == 0 )
4199 {
4200 consdata->normalized = TRUE;
4201 return SCIP_OKAY;
4202 }
4203
4204 assert(vals != NULL);
4205
4206 /* get maximum and minimum absolute coefficient */
4207 maxabsval = consdataGetMaxAbsval(consdata);
4208 minabsval = consdataGetMinAbsval(consdata);
4209
4210 /* return if scaling by maxval will eliminate coefficients */
4211 if( SCIPisZero(scip, minabsval/maxabsval) )
4212 return SCIP_OKAY;
4213
4214 /* return if scaling by maxval will eliminate or generate non-zero sides */
4215 if( !SCIPisInfinity(scip, consdata->lhs) && SCIPisFeasZero(scip, consdata->lhs) != SCIPisFeasZero(scip, consdata->lhs/maxabsval) )
4216 return SCIP_OKAY;
4217 if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisFeasZero(scip, consdata->rhs) != SCIPisFeasZero(scip, consdata->rhs/maxabsval) )
4218 return SCIP_OKAY;
4219
4220 /* check if not all absolute coefficients are near 1.0 but scaling could do */
4221 if( SCIPisLT(scip, minabsval, 1.0) != SCIPisGT(scip, maxabsval, 1.0) )
4222 {
4223 SCIP_Real scalar;
4224
4225 /* calculate scale of the average minimum and maximum absolute coefficient to 1.0 */
4226 scalar = 2.0 / (minabsval + maxabsval);
4227
4228 /* check if all scaled absolute coefficients are near 1.0
4229 * we can relax EQ(x,1.0) to LE(x,1.0), as LT(x,1.0) is not possible
4230 */
4231 if( SCIPisLE(scip, scalar * maxabsval, 1.0) )
4232 {
4233 SCIPdebugMsg(scip, "divide linear constraint with %g, because all coefficients are in absolute value the same\n", maxabsval);
4235 SCIP_CALL( scaleCons(scip, cons, scalar) );
4236
4237 /* get new consdata information, because scaleCons() might have deleted variables */
4238 vals = consdata->vals;
4239 nvars = consdata->nvars;
4240
4241 assert(nvars == 0 || vals != NULL);
4242 }
4243 }
4244
4245 /* nvars might have changed */
4246 if( nvars == 0 )
4247 {
4248 consdata->normalized = TRUE;
4249 return SCIP_OKAY;
4250 }
4251
4252 assert(vals != NULL);
4253
4254 /* calculate the maximal multiplier for common divisor calculation:
4255 * |p/q - val| < epsilon and q < feastol/epsilon => |p - q*val| < feastol
4256 * which means, a value of feastol/epsilon should be used as maximal multiplier;
4257 * additionally, we don't want to scale the constraint if this would lead to too
4258 * large coefficients
4259 */
4260 epsilon = SCIPepsilon(scip) * 0.9; /* slightly decrease epsilon to be safe in rational conversion below */
4261 feastol = SCIPfeastol(scip);
4262 maxmult = (SCIP_Longint)(feastol/epsilon + feastol);
4263
4264 if( !consdata->hasnonbinvalid )
4265 consdataCheckNonbinvar(consdata);
4266
4267 /* get maximum absolute coefficient */
4268 maxabsval = consdataGetMaxAbsval(consdata);
4269
4270 /* if all variables are of integral type we will allow a greater multiplier */
4271 if( !consdata->hascontvar )
4272 maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEFINTEGER / MAX(maxabsval, 1.0))); /*lint !e835*/
4273 else
4274 maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEF / MAX(maxabsval, 1.0))); /*lint !e835*/
4275
4276 /*
4277 * multiplication with +1 or -1
4278 */
4279 mult = 0;
4280
4281 /* 1. the right hand side must not be negative */
4282 if( SCIPisPositive(scip, consdata->lhs) )
4283 mult = +1;
4284 else if( SCIPisNegative(scip, consdata->rhs) )
4285 mult = -1;
4286
4287 if( mult == 0 )
4288 {
4289 /* 2. the right hand side must not be infinite */
4290 if( SCIPisInfinity(scip, -consdata->lhs) )
4291 mult = +1;
4292 else if( SCIPisInfinity(scip, consdata->rhs) )
4293 mult = -1;
4294 }
4295
4296 if( mult == 0 )
4297 {
4298 /* 3. the absolute value of the right hand side must be greater than that of the left hand side */
4299 if( SCIPisGT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4300 mult = +1;
4301 else if( SCIPisLT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4302 mult = -1;
4303 }
4304
4305 if( mult == 0 )
4306 {
4307 /* 4. the number of positive coefficients must not be smaller than the number of negative coefficients */
4308 nposcoeffs = 0;
4309 nnegcoeffs = 0;
4310 for( i = 0; i < nvars; ++i )
4311 {
4312 if( vals[i] > 0.0 )
4313 nposcoeffs++;
4314 else
4315 nnegcoeffs++;
4316 }
4317 if( nposcoeffs > nnegcoeffs )
4318 mult = +1;
4319 else if( nposcoeffs < nnegcoeffs )
4320 mult = -1;
4321 }
4322
4323 if( mult == 0 )
4324 {
4325 /* 5. multiply with +1 */
4326 mult = +1;
4327 }
4328
4329 assert(mult == +1 || mult == -1);
4330 if( mult == -1 )
4331 {
4332 /* scale the constraint with -1 */
4333 SCIPdebugMsg(scip, "multiply linear constraint with -1.0\n");
4335 SCIP_CALL( scaleCons(scip, cons, -1.0) );
4336
4337 /* scalecons() can delete variables, but scaling with -1 should not do that */
4338 assert(nvars == consdata->nvars);
4339 }
4340
4341 /*
4342 * rationals to integrals
4343 *
4344 * @todo try scaling only on behalf of non-continuous variables
4345 */
4346 success = TRUE;
4347 scm = 1;
4348 for( i = 0; i < nvars && success && scm <= maxmult; ++i )
4349 {
4350 if( !SCIPisIntegral(scip, vals[i]) )
4351 {
4352 /* epsilon has been slightly decreased above - to be on the safe side */
4353 success = SCIPrealToRational(vals[i], -epsilon, epsilon , maxmult, &numerator, &denominator);
4354 if( success )
4355 scm = SCIPcalcSmaComMul(scm, denominator);
4356 }
4357 }
4358 assert(scm >= 1);
4359
4360 /* it might be that we have really big coefficients, but all are integral, in that case we want to divide them by
4361 * their greatest common divisor
4362 */
4363 onlyintegral = TRUE;
4364 if( scm == 1 )
4365 {
4366 for( i = nvars - 1; i >= 0; --i )
4367 {
4368 if( !SCIPisIntegral(scip, vals[i]) )
4369 {
4370 onlyintegral = FALSE;
4371 break;
4372 }
4373 }
4374 }
4375
4376 success = success && (scm <= maxmult || (scm == 1 && onlyintegral));
4377 if( success && scm != 1 )
4378 {
4379 /* scale the constraint with the smallest common multiple of all denominators */
4380 SCIPdebugMsg(scip, "scale linear constraint with %" SCIP_LONGINT_FORMAT " to make coefficients integral\n", scm);
4382 SCIP_CALL( scaleCons(scip, cons, (SCIP_Real)scm) );
4383
4384 if( consdata->validmaxabsval )
4385 {
4386 consdata->maxabsval *= REALABS((SCIP_Real)scm);
4387 if( !SCIPisIntegral(scip, consdata->maxabsval) )
4388 {
4389 consdata->validmaxabsval = FALSE;
4390 consdata->maxabsval = SCIP_INVALID;
4391 consdataCalcMaxAbsval(consdata);
4392 }
4393 }
4394
4395 if( consdata->validminabsval )
4396 {
4397 consdata->minabsval *= REALABS((SCIP_Real)scm);
4398 if( !SCIPisIntegral(scip, consdata->minabsval) )
4399 {
4400 consdata->validminabsval = FALSE;
4401 consdata->minabsval = SCIP_INVALID;
4402 consdataCalcMinAbsval(consdata);
4403 }
4404 }
4405
4406 /* get new consdata information, because scalecons() might have deleted variables */
4407 vals = consdata->vals;
4408 nvars = consdata->nvars;
4409 assert(nvars == 0 || vals != NULL);
4410 }
4411
4412 /*
4413 * division by greatest common divisor
4414 */
4415 if( success && nvars >= 1 )
4416 {
4417 /* all coefficients are integral: divide them by their greatest common divisor */
4418 assert(SCIPisIntegral(scip, vals[0]));
4419
4420 gcd = (SCIP_Longint)(REALABS(vals[0]) + feastol);
4421 for( i = 1; i < nvars && gcd > 1; ++i )
4422 {
4423 assert(SCIPisIntegral(scip, vals[i]));
4424 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[i]) + feastol));
4425 }
4426
4427 if( gcd > 1 )
4428 {
4429 /* since the lhs/rhs is not respected for gcd calculation it can happen that we detect infeasibility */
4430 if( !consdata->hascontvar && onlyintegral )
4431 {
4432 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) && !SCIPisFeasIntegral(scip, consdata->rhs / gcd) )
4433 {
4434 *infeasible = TRUE;
4435
4436 SCIPdebugMsg(scip, "detected infeasibility of constraint after scaling with gcd=%" SCIP_LONGINT_FORMAT ":\n", gcd);
4438
4439 return SCIP_OKAY;
4440 }
4441 }
4442
4443 /* divide the constraint by the greatest common divisor of the coefficients */
4444 SCIPdebugMsg(scip, "divide linear constraint by greatest common divisor %" SCIP_LONGINT_FORMAT "\n", gcd);
4446 SCIP_CALL( scaleCons(scip, cons, 1.0/(SCIP_Real)gcd) );
4447
4448 if( consdata->validmaxabsval )
4449 {
4450 consdata->maxabsval /= REALABS((SCIP_Real)gcd);
4451 }
4452 if( consdata->validminabsval )
4453 {
4454 consdata->minabsval /= REALABS((SCIP_Real)gcd);
4455 }
4456 }
4457 }
4458
4459 /* mark constraint to be normalized */
4460 consdata->normalized = TRUE;
4461
4462 SCIPdebugMsg(scip, "normalized constraint:\n");
4464
4465 return SCIP_OKAY;
4466}
4467
4468/** replaces multiple occurrences of a variable by a single non-zero coefficient */
4469static
4471 SCIP* scip, /**< SCIP data structure */
4472 SCIP_CONS* cons /**< linear constraint */
4473 )
4474{
4475 SCIP_CONSDATA* consdata;
4476 SCIP_VAR* var;
4477 SCIP_Real valsum;
4478 int v;
4479
4480 assert(scip != NULL);
4481 assert(cons != NULL);
4482
4483 consdata = SCIPconsGetData(cons);
4484 assert(consdata != NULL);
4485
4486 if( consdata->merged )
4487 return SCIP_OKAY;
4488
4489 /* sort the constraint */
4490 SCIP_CALL( consdataSort(scip, consdata) );
4491
4492 v = consdata->nvars - 1;
4493
4494 /* go backwards through the constraint looking for multiple occurrences of the same variable;
4495 * backward direction is necessary, since delCoefPos() modifies the given position and
4496 * the subsequent ones
4497 */
4498 while( v >= 0 )
4499 {
4500 var = consdata->vars[v];
4501 valsum = consdata->vals[v];
4502
4503 /* sum multiple occurrences */
4504 while( v >= 1 && consdata->vars[v-1] == var )
4505 {
4506 SCIP_CALL( delCoefPos(scip, cons, v) );
4507 --v;
4508 valsum += consdata->vals[v];
4509 }
4510
4511 assert(consdata->vars[v] == var);
4512
4513 /* modify the last existing occurrence of the variable */
4514 if( SCIPisZero(scip, valsum) )
4515 {
4516 SCIP_CALL( delCoefPos(scip, cons, v) );
4517 }
4518 else if( valsum != consdata->vals[v] ) /*lint !e777*/
4519 {
4520 SCIP_CALL( chgCoefPos(scip, cons, v, valsum) );
4521 }
4522
4523 --v;
4524 }
4525
4526 consdata->merged = TRUE;
4527
4528 return SCIP_OKAY;
4529}
4530
4531/** replaces all fixed and aggregated variables by their non-fixed counterparts */
4532static
4534 SCIP* scip, /**< SCIP data structure */
4535 SCIP_CONS* cons, /**< linear constraint */
4536 SCIP_Bool* infeasible /**< pointer to store if infeasibility is detected; or NULL if this
4537 * information is not needed; in this case, we apply all fixings
4538 * instead of stopping after the first infeasible one */
4539 )
4540{
4541 SCIP_CONSDATA* consdata;
4542 int v;
4543
4544 assert(scip != NULL);
4545 assert(cons != NULL);
4546
4547 if( infeasible != NULL )
4548 *infeasible = FALSE;
4549
4550 consdata = SCIPconsGetData(cons);
4551 assert(consdata != NULL);
4552
4553 if( consdata->eventdata == NULL )
4554 {
4555 SCIP_CONSHDLR* conshdlr;
4556 SCIP_CONSHDLRDATA* conshdlrdata;
4557
4558 conshdlr = SCIPconsGetHdlr(cons);
4559 assert(conshdlr != NULL);
4560
4561 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4562 assert(conshdlrdata != NULL);
4563
4564 /* catch bound change events of variables */
4565 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
4566 assert(consdata->eventdata != NULL);
4567 }
4568
4569 if( !consdata->removedfixings )
4570 {
4571 SCIP_Real lhssubtrahend;
4572 SCIP_Real rhssubtrahend;
4573
4574 /* if an unmodifiable row has been added to the LP, then we cannot apply fixing anymore (cannot change a row)
4575 * this should not happen, as applyFixings is called in addRelaxation() before creating and adding a row
4576 */
4577 assert(consdata->row == NULL || !SCIProwIsInLP(consdata->row) || SCIProwIsModifiable(consdata->row));
4578
4579 lhssubtrahend = 0.0;
4580 rhssubtrahend = 0.0;
4581
4582 SCIPdebugMsg(scip, "applying fixings:\n");
4584
4585 v = 0;
4586 while( v < consdata->nvars )
4587 {
4588 SCIP_VAR* var = consdata->vars[v];
4589 SCIP_Real scalar = consdata->vals[v];
4590 SCIP_Real constant = 0.0;
4592
4593 SCIP_CALL( SCIPgetProbvarSum(scip, &var, &scalar, &constant) );
4594
4595 switch( SCIPvarGetStatus(var) )
4596 {
4598 SCIPerrorMessage("original variable in transformed linear constraint\n");
4599 return SCIP_INVALIDDATA;
4600
4603 SCIPerrorMessage("aggregated variable after resolving linear term\n");
4604 return SCIP_INVALIDDATA;
4605
4608 if( var != consdata->vars[v] )
4609 {
4610 assert(scalar != 0.0);
4611 SCIP_CALL( addCoef(scip, cons, var, scalar) );
4612 SCIP_CALL( delCoefPos(scip, cons, v) );
4613
4614 assert(!SCIPisInfinity(scip, ABS(constant)));
4615 if( !SCIPisInfinity(scip, -consdata->lhs) )
4616 lhssubtrahend += constant;
4617 if( !SCIPisInfinity(scip, consdata->rhs) )
4618 rhssubtrahend += constant;
4619 }
4620 ++v;
4621 break;
4622
4624 if( scalar != 0.0 )
4625 {
4626 SCIP_VAR** aggrvars;
4627 SCIP_Real* aggrscalars;
4628 SCIP_Real aggrconstant;
4629 int naggrvars;
4630 int i;
4631
4633 aggrvars = SCIPvarGetMultaggrVars(var);
4634 aggrscalars = SCIPvarGetMultaggrScalars(var);
4635 aggrconstant = SCIPvarGetMultaggrConstant(var);
4636 naggrvars = SCIPvarGetMultaggrNVars(var);
4637
4638 for( i = 0; i < naggrvars; ++i )
4639 {
4640 SCIP_CALL( addCoef(scip, cons, aggrvars[i], scalar * aggrscalars[i]) );
4641 }
4642
4643 constant += scalar * aggrconstant;
4644 }
4645 /*lint -fallthrough*/
4646
4648 if( !SCIPisInfinity(scip, -consdata->lhs) )
4649 {
4650 if( SCIPisInfinity(scip, ABS(constant)) )
4651 {
4652 /* if lhs gets infinity it means that the problem is infeasible */
4653 if( constant < 0.0 )
4654 {
4656
4657 if( infeasible != NULL )
4658 {
4659 *infeasible = TRUE;
4660 return SCIP_OKAY;
4661 }
4662 }
4663 else
4664 {
4665 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
4666 }
4667 }
4668 else
4669 lhssubtrahend += constant;
4670 }
4671 if( !SCIPisInfinity(scip, consdata->rhs) )
4672 {
4673 if( SCIPisInfinity(scip, ABS(constant)) )
4674 {
4675 /* if rhs gets -infinity it means that the problem is infeasible */
4676 if( constant > 0.0 )
4677 {
4678 SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
4679
4680 if( infeasible != NULL )
4681 {
4682 *infeasible = TRUE;
4683 return SCIP_OKAY;
4684 }
4685 }
4686 else
4687 {
4689 }
4690 }
4691 else
4692 rhssubtrahend += constant;
4693 }
4694 SCIP_CALL( delCoefPos(scip, cons, v) );
4695 break;
4696
4697 default:
4698 SCIPerrorMessage("unknown variable status\n");
4699 SCIPABORT();
4700 return SCIP_INVALIDDATA; /*lint !e527*/
4701 }
4702 }
4703
4704 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->lhs) )
4705 {
4706 /* check left hand side of unmodifiable empty constraint with former feasibility tolerance */
4707 if( !SCIPconsIsModifiable(cons) && consdata->nvars == 0 )
4708 {
4709 if( SCIPisFeasLT(scip, lhssubtrahend, consdata->lhs) )
4710 {
4712
4713 if( infeasible != NULL )
4714 {
4715 *infeasible = TRUE;
4716 return SCIP_OKAY;
4717 }
4718 }
4719 else
4720 {
4721 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
4722 }
4723 }
4724 /* for normal numbers that are relatively equal, subtraction can lead to cancellation,
4725 * causing wrong fixings of other variables --> better use a real zero here
4726 */
4727 else if( SCIPisGE(scip, ABS(consdata->lhs), 1.0) && SCIPisEQ(scip, lhssubtrahend, consdata->lhs) )
4728 {
4729 SCIP_CALL( chgLhs(scip, cons, 0.0) );
4730 }
4731 else
4732 {
4733 SCIP_CALL( chgLhs(scip, cons, consdata->lhs - lhssubtrahend) );
4734 }
4735 }
4736 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs) )
4737 {
4738 /* check right hand side of unmodifiable empty constraint with former feasibility tolerance */
4739 if( !SCIPconsIsModifiable(cons) && consdata->nvars == 0 )
4740 {
4741 if( SCIPisFeasGT(scip, rhssubtrahend, consdata->rhs) )
4742 {
4743 SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
4744
4745 if( infeasible != NULL )
4746 {
4747 *infeasible = TRUE;
4748 return SCIP_OKAY;
4749 }
4750 }
4751 else
4752 {
4754 }
4755 }
4756 /* for normal numbers that are relatively equal, subtraction can lead to cancellation,
4757 * causing wrong fixings of other variables --> better use a real zero here
4758 */
4759 else if( SCIPisGE(scip, ABS(consdata->rhs), 1.0) && SCIPisEQ(scip, rhssubtrahend, consdata->rhs) )
4760 {
4761 SCIP_CALL( chgRhs(scip, cons, 0.0) );
4762 }
4763 else
4764 {
4765 SCIP_CALL( chgRhs(scip, cons, consdata->rhs - rhssubtrahend) );
4766 }
4767 }
4768 consdata->removedfixings = TRUE;
4769
4770 SCIPdebugMsg(scip, "after fixings:\n");
4772
4773 /* if aggregated variables have been replaced, multiple entries of the same variable are possible and we have
4774 * to clean up the constraint
4775 */
4776 SCIP_CALL( mergeMultiples(scip, cons) );
4777
4778 SCIPdebugMsg(scip, "after merging:\n");
4780 }
4781 assert(consdata->removedfixings);
4782
4783#ifndef NDEBUG
4784 /* check, if all fixings are applied */
4785 for( v = 0; v < consdata->nvars; ++v )
4786 assert(SCIPvarIsActive(consdata->vars[v]));
4787#endif
4788
4789 return SCIP_OKAY;
4790}
4791
4792/** for each variable in the linear constraint, except the inferred variable, adds one bound to the conflict analysis'
4793 * candidate store (bound depends on sign of coefficient and whether the left or right hand side was the reason for the
4794 * inference variable's bound change); the conflict analysis can be initialized with the linear constraint being the
4795 * conflict detecting constraint by using NULL as inferred variable
4796 */
4797static
4799 SCIP* scip, /**< SCIP data structure */
4800 SCIP_CONS* cons, /**< constraint that inferred the bound change */
4801 SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
4802 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4803 int inferpos, /**< position of the inferred variable in the vars array */
4804 SCIP_Bool reasonisrhs /**< is the right hand side responsible for the bound change? */
4805 )
4806{
4807 SCIP_CONSDATA* consdata;
4808 SCIP_VAR** vars;
4809 SCIP_Real* vals;
4810 int nvars;
4811 int i;
4812
4813 assert(scip != NULL);
4814 assert(cons != NULL);
4815
4816 consdata = SCIPconsGetData(cons);
4817
4818 assert(consdata != NULL);
4819
4820 vars = consdata->vars;
4821 vals = consdata->vals;
4822 nvars = consdata->nvars;
4823
4824 assert(vars != NULL || nvars == 0);
4825 assert(vals != NULL || nvars == 0);
4826
4827 assert(-1 <= inferpos && inferpos < nvars);
4828 assert((infervar == NULL) == (inferpos == -1));
4829 assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
4830
4831 /* for each variable, add the bound to the conflict queue, that is responsible for the minimal or maximal
4832 * residual value, depending on whether the left or right hand side is responsible for the bound change:
4833 * - if the right hand side is the reason, the minimal residual activity is responsible
4834 * - if the left hand side is the reason, the maximal residual activity is responsible
4835 */
4836
4837 /* if the variable is integral we only need to add reason bounds until the propagation could be applied */
4838 if( infervar == NULL || SCIPvarIsIntegral(infervar) )
4839 {
4840 SCIP_Real minresactivity;
4841 SCIP_Real maxresactivity;
4842 SCIP_Bool ismintight;
4843 SCIP_Bool ismaxtight;
4844 SCIP_Bool isminsettoinfinity;
4845 SCIP_Bool ismaxsettoinfinity;
4846
4847 minresactivity = -SCIPinfinity(scip);
4848 maxresactivity = SCIPinfinity(scip);
4849
4850 /* calculate the minimal and maximal global activity of all other variables involved in the constraint */
4851 if( infervar != NULL )
4852 {
4853 assert(vals != NULL); /* for flexelint */
4854 if( reasonisrhs )
4855 consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, &minresactivity, NULL,
4856 &ismintight, NULL, &isminsettoinfinity, NULL);
4857 else
4858 consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, NULL, &maxresactivity,
4859 NULL, &ismaxtight, NULL, &ismaxsettoinfinity);
4860 }
4861 else
4862 {
4863 if( reasonisrhs )
4864 consdataGetGlbActivityBounds(scip, consdata, FALSE, &minresactivity, NULL,
4865 &ismintight, NULL, &isminsettoinfinity, NULL);
4866 else
4867 consdataGetGlbActivityBounds(scip, consdata, FALSE, NULL, &maxresactivity,
4868 NULL, &ismaxtight, NULL, &ismaxsettoinfinity);
4869 }
4870
4871 /* we can only do something clever, if the residual activity is finite and not relaxed */
4872 if( (reasonisrhs && !isminsettoinfinity && ismintight) || (!reasonisrhs && !ismaxsettoinfinity && ismaxtight) ) /*lint !e644*/
4873 {
4874 SCIP_Real rescap;
4875 SCIP_Bool resactisinf;
4876
4877 resactisinf = FALSE;
4878
4879 /* calculate the residual capacity that would be left, if the variable would be set to one more / one less
4880 * than its inferred bound
4881 */
4882 if( infervar != NULL )
4883 {
4884 assert(vals != NULL); /* for flexelint */
4885
4886 if( reasonisrhs )
4887 {
4888 if( SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
4889 {
4890 consdataGetReliableResidualActivity(scip, consdata, infervar, &minresactivity, TRUE, TRUE);
4891 if( SCIPisInfinity(scip, -minresactivity) )
4892 resactisinf = TRUE;
4893 }
4894 rescap = consdata->rhs - minresactivity;
4895 }
4896 else
4897 {
4898 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
4899 {
4900 consdataGetReliableResidualActivity(scip, consdata, infervar, &maxresactivity, FALSE, TRUE);
4901 if( SCIPisInfinity(scip, maxresactivity) )
4902 resactisinf = TRUE;
4903 }
4904 rescap = consdata->lhs - maxresactivity;
4905 }
4906
4907 if( reasonisrhs == (vals[inferpos] > 0.0) )
4908 rescap -= vals[inferpos] * (SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) + 1.0);
4909 else
4910 rescap -= vals[inferpos] * (SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) - 1.0);
4911 }
4912 else
4913 rescap = (reasonisrhs ? consdata->rhs - minresactivity : consdata->lhs - maxresactivity);
4914
4915 if( !resactisinf )
4916 {
4917 /* now add bounds as reasons until the residual capacity is exceeded */
4918 for( i = 0; i < nvars; ++i )
4919 {
4920 assert( vars != NULL && vals != NULL ); /* for lint */
4921
4922 /* zero coefficients and the inferred variable can be ignored */
4923 if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
4924 continue;
4925
4926 /* check if the residual capacity is exceeded */
4927 if( (reasonisrhs && SCIPisFeasNegative(scip, rescap))
4928 || (!reasonisrhs && SCIPisFeasPositive(scip, rescap)) )
4929 break;
4930
4931 /* update the residual capacity due to the local bound of this variable */
4932 if( reasonisrhs == (vals[i] > 0.0) )
4933 {
4934 /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound */
4935 SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
4936 rescap -= vals[i] * (SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetLbGlobal(vars[i]));
4937 }
4938 else
4939 {
4940 /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound */
4941 SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
4942 rescap -= vals[i] * (SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetUbGlobal(vars[i]));
4943 }
4944 }
4945 return SCIP_OKAY;
4946 }
4947 }
4948 }
4949
4950 /* for a bound change on a continuous variable, all locally changed bounds are responsible */
4951 for( i = 0; i < nvars; ++i )
4952 {
4953 assert(vars != NULL); /* for flexelint */
4954 assert(vals != NULL); /* for flexelint */
4955
4956 /* zero coefficients and the inferred variable can be ignored */
4957 if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
4958 continue;
4959
4960 if( reasonisrhs == (vals[i] > 0.0) )
4961 {
4962 /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound is responsible */
4963 SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
4964 }
4965 else
4966 {
4967 /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound is responsible */
4968 SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
4969 }
4970 }
4971
4972 return SCIP_OKAY;
4973}
4974
4975/** for each variable in the linear ranged row constraint, except the inferred variable, adds the bounds of all fixed
4976 * variables to the conflict analysis' candidate store; the conflict analysis can be initialized
4977 * with the linear constraint being the conflict detecting constraint by using NULL as inferred variable
4978 */
4979static
4981 SCIP* scip, /**< SCIP data structure */
4982 SCIP_CONS* cons, /**< constraint that inferred the bound change */
4983 SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
4984 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4985 int inferpos /**< position of the inferred variable in the vars array, or -1 */
4986 )
4987{
4988 SCIP_CONSDATA* consdata;
4989 SCIP_VAR** vars;
4990 int nvars;
4991 int v;
4992
4993 assert(scip != NULL);
4994 assert(cons != NULL);
4995
4996 consdata = SCIPconsGetData(cons);
4997 assert(consdata != NULL);
4998 vars = consdata->vars;
4999 nvars = consdata->nvars;
5000 assert(vars != NULL || nvars == 0);
5001 assert(-1 <= inferpos && inferpos < nvars);
5002 assert((infervar == NULL) == (inferpos == -1));
5003 assert(inferpos == -1 || vars != NULL);
5004 assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
5005
5006 /* collect all fixed variables */
5007 for( v = nvars - 1; v >= 0; --v )
5008 {
5009 assert(vars != NULL); /* for flexelint */
5010
5011 /* need to add old bounds before propagation of inferrence variable */
5012 if( vars[v] == infervar )
5013 {
5014 assert(vars[v] != NULL);
5015
5017 {
5018 /* @todo get boundchange index before this last boundchange and correct the index */
5019 SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5020 }
5021
5023 {
5024 /* @todo get boundchange index before this last boundchange and correct the index */
5025 SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5026 }
5027
5028 continue;
5029 }
5030
5031 /* check for fixed variables */
5032 if( SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE)) )
5033 {
5034 /* add all bounds of fixed variables which lead to the boundchange of the given inference variable */
5035 SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5036 SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5037 }
5038 }
5039
5040 return SCIP_OKAY;
5041}
5042
5043/** add reasoning variables to conflict candidate queue which led to the conflict */
5044static
5046 SCIP* scip, /**< SCIP data structure */
5047 SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5048 int nvars, /**< number of variables reasoning the infeasibility */
5049 SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5050 SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5051 )
5052{
5053 int v;
5054
5055 assert(scip != NULL);
5056
5057 /* collect all variables for which the local bounds differ from their global bounds */
5058 for( v = nvars - 1; v >= 0; --v )
5059 {
5060 assert(vars != NULL);
5061
5062 /* check for local bound changes variables */
5064 {
5065 /* add conflict bound */
5067 }
5068
5070 {
5072 }
5073 }
5074
5075 if( var != NULL )
5076 {
5077 if( bound < SCIPvarGetLbLocal(var) )
5078 {
5080 }
5081
5082 if( bound > SCIPvarGetUbLocal(var) )
5083 {
5085 }
5086 }
5087
5088 return SCIP_OKAY;
5089}
5090
5091/** resolves a propagation on the given variable by supplying the variables needed for applying the corresponding
5092 * propagation rule (see propagateCons()):
5093 * (1) activity residuals of all other variables tighten bounds of single variable
5094 */
5095static
5097 SCIP* scip, /**< SCIP data structure */
5098 SCIP_CONS* cons, /**< constraint that inferred the bound change */
5099 SCIP_VAR* infervar, /**< variable that was deduced */
5100 INFERINFO inferinfo, /**< inference information */
5101 SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
5102 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
5103 SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
5104 )
5105{
5106 SCIP_CONSDATA* consdata;
5107 SCIP_VAR** vars;
5108#ifndef NDEBUG
5109 SCIP_Real* vals;
5110#endif
5111 int nvars;
5112 int inferpos;
5113
5114 assert(scip != NULL);
5115 assert(cons != NULL);
5116 assert(result != NULL);
5117
5118 consdata = SCIPconsGetData(cons);
5119 assert(consdata != NULL);
5120 vars = consdata->vars;
5121 nvars = consdata->nvars;
5122#ifndef NDEBUG
5123 vals = consdata->vals;
5124 assert(vars != NULL);
5125 assert(vals != NULL);
5126#endif
5127
5128 /* get the position of the inferred variable in the vars array */
5129 inferpos = inferInfoGetPos(inferinfo);
5130 if( inferpos >= nvars || vars[inferpos] != infervar )
5131 {
5132 /* find inference variable in constraint */
5133 /**@todo use a binary search here; the variables can be sorted by variable index */
5134 for( inferpos = 0; inferpos < nvars && vars[inferpos] != infervar; ++inferpos )
5135 {}
5136 }
5137 assert(inferpos < nvars);
5138 assert(vars[inferpos] == infervar);
5139 assert(!SCIPisZero(scip, vals[inferpos]));
5140
5141 switch( inferInfoGetProprule(inferinfo) )
5142 {
5143 case PROPRULE_1_RHS:
5144 /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5145 * constraint (only taking the other variables into account) didn't leave enough space for a larger
5146 * domain in order to not exceed the right hand side of the inequality
5147 */
5148 assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_UPPER));
5149 SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, TRUE) );
5151 break;
5152
5153 case PROPRULE_1_LHS:
5154 /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5155 * constraint (only taking the other variables into account) didn't leave enough space for a larger
5156 * domain in order to not fall below the left hand side of the inequality
5157 */
5158 assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_LOWER));
5159 SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, FALSE) );
5161 break;
5162
5164 /* the bound of the variable was tightened, because some variables were already fixed and the leftover only allow
5165 * the given inference variable to their bounds in this given ranged row
5166 */
5167
5168 /* check that we really have a ranged row here */
5169 assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5170 SCIP_CALL( addConflictFixedVars(scip, cons, infervar, bdchgidx, inferpos) );
5172 break;
5173
5174 case PROPRULE_INVALID:
5175 default:
5176 SCIPerrorMessage("invalid inference information %d in linear constraint <%s> at position %d for %s bound of variable <%s>\n",
5177 inferInfoGetProprule(inferinfo), SCIPconsGetName(cons), inferInfoGetPos(inferinfo),
5178 boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(infervar));
5179 SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
5180 SCIPinfoMessage(scip, NULL, ";\n");
5181 return SCIP_INVALIDDATA;
5182 }
5183
5184 return SCIP_OKAY;
5185}
5186
5187/** analyzes conflicting bounds on given constraint, and adds conflict constraint to problem */
5188static
5190 SCIP* scip, /**< SCIP data structure */
5191 SCIP_CONS* cons, /**< conflict detecting constraint */
5192 SCIP_Bool reasonisrhs /**< is the right hand side responsible for the conflict? */
5193 )
5194{
5195 /* conflict analysis can only be applied in solving stage and if it is turned on */
5197 return SCIP_OKAY;
5198
5199 /* initialize conflict analysis */
5201
5202 /* add the conflicting bound for each variable of infeasible constraint to conflict candidate queue */
5203 SCIP_CALL( addConflictBounds(scip, cons, NULL, NULL, -1, reasonisrhs) );
5204
5205 /* analyze the conflict */
5207
5208 return SCIP_OKAY;
5209}
5210
5211/** check if there is any hope of tightening some bounds */
5212static
5214 SCIP_CONS* cons /**< linear constraint */
5215 )
5216{
5217 SCIP_CONSDATA* consdata;
5218 int infcountmin;
5219 int infcountmax;
5220
5221 consdata = SCIPconsGetData(cons);
5222 assert(consdata != NULL);
5223
5224 infcountmin = consdata->minactivityneginf
5225 + consdata->minactivityposinf
5226 + consdata->minactivityneghuge
5227 + consdata->minactivityposhuge;
5228 infcountmax = consdata->maxactivityneginf
5229 + consdata->maxactivityposinf
5230 + consdata->maxactivityneghuge
5231 + consdata->maxactivityposhuge;
5232
5233 if( infcountmin > 1 && infcountmax > 1 )
5234 return FALSE;
5235
5236 return TRUE;
5237}
5238
5239/** tighten upper bound */
5240static
5242 SCIP* scip, /**< SCIP data structure */
5243 SCIP_CONS* cons, /**< linear constraint */
5244 int pos, /**< variable position */
5245 PROPRULE proprule, /**< propagation rule that deduced the value */
5246 SCIP_Real newub, /**< new upper bound */
5247 SCIP_Real oldub, /**< old upper bound */
5248 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5249 int* nchgbds, /**< pointer to count the total number of tightened bounds */
5250 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5251 )
5252{
5253 SCIP_CONSDATA* consdata;
5254 SCIP_VAR* var;
5255 SCIP_Real lb;
5256 SCIP_Bool infeasible;
5257 SCIP_Bool tightened;
5258
5259 assert(cons != NULL);
5260 assert(!SCIPisInfinity(scip, newub));
5261
5262 consdata = SCIPconsGetData(cons);
5263 assert(consdata != NULL);
5264 var = consdata->vars[pos];
5265 assert(var != NULL);
5266
5267 lb = SCIPvarGetLbLocal(var);
5268 newub = SCIPadjustedVarUb(scip, var, newub);
5269
5270 if( force || SCIPisUbBetter(scip, newub, lb, oldub) )
5271 {
5272 SCIP_VARTYPE vartype = SCIPvarGetType(var);
5274
5275 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
5276 SCIPconsGetName(cons), SCIPvarGetName(var), lb, oldub, consdata->vals[pos],
5277 QUAD_TO_DBL(consdata->minactivity), QUAD_TO_DBL(consdata->maxactivity), consdata->lhs, consdata->rhs, newub);
5278
5279 /* tighten upper bound */
5280 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5281
5282 if( infeasible )
5283 {
5284 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5285 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5286
5287 /* analyze conflict */
5289
5290 *cutoff = TRUE;
5291 }
5292 else if( tightened )
5293 {
5295 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5297
5298 (*nchgbds)++;
5299
5300 /* if variable type was changed we might be able to upgrade the constraint */
5301 if( SCIPvarGetType(var) != vartype || SCIPvarGetImplType(var) != impltype )
5302 consdata->upgradetried = FALSE;
5303 }
5304 }
5305 return SCIP_OKAY;
5306}
5307
5308/** tighten lower bound */
5309static
5311 SCIP* scip, /**< SCIP data structure */
5312 SCIP_CONS* cons, /**< linear constraint */
5313 int pos, /**< variable position */
5314 PROPRULE proprule, /**< propagation rule that deduced the value */
5315 SCIP_Real newlb, /**< new lower bound */
5316 SCIP_Real oldlb, /**< old lower bound */
5317 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5318 int* nchgbds, /**< pointer to count the total number of tightened bounds */
5319 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5320 )
5321{
5322 SCIP_CONSDATA* consdata;
5323 SCIP_VAR* var;
5324 SCIP_Real ub;
5325 SCIP_Bool infeasible;
5326 SCIP_Bool tightened;
5327
5328 assert(cons != NULL);
5329 assert(!SCIPisInfinity(scip, newlb));
5330
5331 consdata = SCIPconsGetData(cons);
5332 assert(consdata != NULL);
5333 var = consdata->vars[pos];
5334 assert(var != NULL);
5335
5336 ub = SCIPvarGetUbLocal(var);
5337 newlb = SCIPadjustedVarLb(scip, var, newlb);
5338
5339 if( force || SCIPisLbBetter(scip, newlb, oldlb, ub) )
5340 {
5341 SCIP_VARTYPE vartype = SCIPvarGetType(var);
5343
5344 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
5345 SCIPconsGetName(cons), SCIPvarGetName(var), oldlb, ub, consdata->vals[pos],
5346 QUAD_TO_DBL(consdata->minactivity), QUAD_TO_DBL(consdata->maxactivity), consdata->lhs, consdata->rhs, newlb);
5347
5348 /* tighten lower bound */
5349 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5350
5351 if( infeasible )
5352 {
5353 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5354 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5355
5356 /* analyze conflict */
5358
5359 *cutoff = TRUE;
5360 }
5361 else if( tightened )
5362 {
5364 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5366
5367 (*nchgbds)++;
5368
5369 /* if variable type was changed we might be able to upgrade the constraint */
5370 if( SCIPvarGetType(var) != vartype || SCIPvarGetImplType(var) != impltype )
5371 consdata->upgradetried = FALSE;
5372 }
5373 }
5374 return SCIP_OKAY;
5375}
5376
5377/** tightens bounds of a single variable due to activity bounds (easy case) */
5378static
5380 SCIP* scip, /**< SCIP data structure */
5381 SCIP_CONS* cons, /**< linear constraint */
5382 int pos, /**< position of the variable in the vars array */
5383 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5384 int* nchgbds, /**< pointer to count the total number of tightened bounds */
5385 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5386 )
5387{
5388 SCIP_CONSDATA* consdata;
5389 SCIP_VAR* var;
5390 SCIP_Real val;
5391 SCIP_Real lb;
5392 SCIP_Real ub;
5393 SCIP_Real lhs;
5394 SCIP_Real rhs;
5395
5396 assert(scip != NULL);
5397 assert(cons != NULL);
5398 assert(cutoff != NULL);
5399 assert(nchgbds != NULL);
5400
5401 /* we cannot tighten variables' bounds, if the constraint may be not complete */
5402 if( SCIPconsIsModifiable(cons) )
5403 return SCIP_OKAY;
5404
5405 consdata = SCIPconsGetData(cons);
5406 assert(consdata != NULL);
5407 assert(0 <= pos && pos < consdata->nvars);
5408
5409 *cutoff = FALSE;
5410
5411 var = consdata->vars[pos];
5412 assert(var != NULL);
5413
5414 /* we cannot tighten bounds of multi-aggregated variables */
5416 return SCIP_OKAY;
5417
5418 val = consdata->vals[pos];
5419 lhs = consdata->lhs;
5420 rhs = consdata->rhs;
5421 assert(!SCIPisZero(scip, val));
5422 assert(!SCIPisInfinity(scip, lhs));
5423 assert(!SCIPisInfinity(scip, -rhs));
5424
5425 lb = SCIPvarGetLbLocal(var);
5426 ub = SCIPvarGetUbLocal(var);
5427 assert(SCIPisLE(scip, lb, ub));
5428
5429 /* recompute activities if needed */
5430 if( !consdata->validactivities )
5431 consdataCalcActivities(scip, consdata);
5432 assert(consdata->validactivities);
5433 if( !consdata->validminact )
5435 assert(consdata->validminact);
5436
5437 if( val > 0.0 )
5438 {
5439 /* check, if we can tighten the variable's upper bound */
5440 if( !SCIPisInfinity(scip, rhs) )
5441 {
5442 SCIP_Real slack;
5444
5445 /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
5446 assert(consdata->validminact);
5447
5448 /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5449 if( SCIPisFeasLT(scip, rhs, QUAD_TO_DBL(consdata->minactivity)) )
5450 {
5451 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5452 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->minactivity), rhs);
5453
5454 *cutoff = TRUE;
5455 return SCIP_OKAY;
5456 }
5457
5458 slack = rhs - QUAD_TO_DBL(consdata->minactivity);
5459
5460 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5461 * it to zero
5462 */
5463 if( !SCIPisPositive(scip, slack) )
5464 slack = 0.0;
5465
5466 alpha = val * (ub - lb);
5468
5469 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5470 {
5471 SCIP_Real newub;
5472
5473 /* compute new upper bound */
5474 newub = lb + (slack / val);
5475
5476 SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_RHS, newub, ub, cutoff, nchgbds, force) );
5477
5478 if( *cutoff )
5479 {
5480 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5481 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5482
5483 return SCIP_OKAY;
5484 }
5485
5486 /* collect the new upper bound which is needed for the lower bound computation */
5487 ub = SCIPvarGetUbLocal(var);
5488 }
5489 }
5490
5491 /* check, if we can tighten the variable's lower bound */
5492 if( !SCIPisInfinity(scip, -lhs) )
5493 {
5494 SCIP_Real slack;
5496
5497 /* make sure the max activity is reliable */
5498 if( !consdata->validmaxact )
5499 {
5501 }
5502 assert(consdata->validmaxact);
5503
5504 /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5505 if( SCIPisFeasLT(scip, QUAD_TO_DBL(consdata->maxactivity), lhs) )
5506 {
5507 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5508 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->maxactivity), lhs);
5509
5510 *cutoff = TRUE;
5511 return SCIP_OKAY;
5512 }
5513
5514 slack = QUAD_TO_DBL(consdata->maxactivity) - lhs;
5515
5516 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5517 * it to zero
5518 */
5519 if( !SCIPisPositive(scip, slack) )
5520 slack = 0.0;
5521
5522 alpha = val * (ub - lb);
5524
5525 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5526 {
5527 SCIP_Real newlb;
5528
5529 /* compute new lower bound */
5530 newlb = ub - (slack / val);
5531
5532 SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_LHS, newlb, lb, cutoff, nchgbds, force) );
5533
5534 if( *cutoff )
5535 {
5536 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5537 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5538
5539 return SCIP_OKAY;
5540 }
5541 }
5542 }
5543 }
5544 else
5545 {
5546 /* check, if we can tighten the variable's lower bound */
5547 if( !SCIPisInfinity(scip, rhs) )
5548 {
5549 SCIP_Real slack;
5551
5552 /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
5553 assert(consdata->validminact);
5554
5555 /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5556 if( SCIPisFeasLT(scip, rhs, QUAD_TO_DBL(consdata->minactivity)) )
5557 {
5558 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5559 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->minactivity), rhs);
5560
5561 *cutoff = TRUE;
5562 return SCIP_OKAY;
5563 }
5564
5565 slack = rhs - QUAD_TO_DBL(consdata->minactivity);
5566
5567 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5568 * it to zero
5569 */
5570 if( !SCIPisPositive(scip, slack) )
5571 slack = 0.0;
5572
5573 alpha = val * (lb - ub);
5575
5576 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5577 {
5578 SCIP_Real newlb;
5579
5580 /* compute new lower bound */
5581 newlb = ub + slack / val;
5582
5583 SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_RHS, newlb, lb, cutoff, nchgbds, force) );
5584
5585 if( *cutoff )
5586 {
5587 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5588 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5589
5590 return SCIP_OKAY;
5591 }
5592 /* collect the new lower bound which is needed for the upper bound computation */
5593 lb = SCIPvarGetLbLocal(var);
5594 }
5595 }
5596
5597 /* check, if we can tighten the variable's upper bound */
5598 if( !SCIPisInfinity(scip, -lhs) )
5599 {
5600 SCIP_Real slack;
5602
5603 /* make sure the max activity is reliable */
5604 if( !consdata->validmaxact )
5605 {
5607 }
5608 assert(consdata->validmaxact);
5609
5610 /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5611 if( SCIPisFeasLT(scip, QUAD_TO_DBL(consdata->maxactivity), lhs) )
5612 {
5613 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5614 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->maxactivity), lhs);
5615
5616 *cutoff = TRUE;
5617 return SCIP_OKAY;
5618 }
5619
5620 slack = QUAD_TO_DBL(consdata->maxactivity) - lhs;
5621
5622 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5623 * it to zero
5624 */
5625 if( !SCIPisPositive(scip, slack) )
5626 slack = 0.0;
5627
5628 alpha = val * (lb - ub);
5630
5631 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5632 {
5633 SCIP_Real newub;
5634
5635 /* compute new upper bound */
5636 newub = lb - (slack / val);
5637
5638 SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_LHS, newub, ub, cutoff, nchgbds, force) );
5639
5640 if( *cutoff )
5641 {
5642 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5643 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5644
5645 return SCIP_OKAY;
5646 }
5647 }
5648 }
5649 }
5650
5651 return SCIP_OKAY;
5652}
5653
5654/** analyzes conflicting bounds on given ranged row constraint, and adds conflict constraint to problem */
5655static
5657 SCIP* scip, /**< SCIP data structure */
5658 SCIP_CONS* cons, /**< conflict detecting constraint */
5659 SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5660 int nvars, /**< number of variables reasoning the infeasibility */
5661 SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5662 SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5663 )
5664{
5665#ifndef NDEBUG
5666 SCIP_CONSDATA* consdata;
5667
5668 assert(scip != NULL);
5669 assert(cons != NULL);
5670
5671 consdata = SCIPconsGetData(cons);
5672 assert(consdata != NULL);
5673 assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5674#endif
5675
5676 /* conflict analysis can only be applied in solving stage and if it is turned on */
5678 return SCIP_OKAY;
5679
5680 /* initialize conflict analysis */
5682
5683 /* add the conflicting fixed variables of this ranged row constraint to conflict candidate queue */
5685
5686 /* add reasoning variables to conflict candidate queue which led to the conflict */
5688
5689 /* analyze the conflict */
5691
5692 return SCIP_OKAY;
5693}
5694
5695/** propagate ranged rows
5696 *
5697 * Check ranged rows for possible solutions, possibly detect infeasibility, fix variables due to having only one possible
5698 * solution, tighten bounds if having only two possible solutions or add constraints which propagate a subset of
5699 * variables better.
5700 *
5701 * Example:
5702 * c1: 12 x1 + 9 x2 - x3 = 0 with x1, x2 free and 1 <= x3 <= 2
5703 *
5704 * x3 needs to be a multiple of 3, so the instance is infeasible.
5705 *
5706 * Example:
5707 * c1: 12 x1 + 9 x2 - x3 = 1 with x1, x2 free and 1 <= x3 <= 2
5708 *
5709 * The only possible value for x3 is 2, so the variable will be fixed.
5710 *
5711 * @todo add holes if possible
5712 */
5713static
5715 SCIP* scip, /**< SCIP data structure */
5716 SCIP_CONS* cons, /**< linear constraint */
5717 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
5718 int* nfixedvars, /**< pointer to count number of fixed variables */
5719 int* nchgbds, /**< pointer to count the number of bound changes */
5720 int* naddconss /**< pointer to count number of added constraints */
5721 )
5722{
5723 SCIP_CONSHDLRDATA* conshdlrdata;
5724 SCIP_CONSHDLR* conshdlr;
5725 SCIP_CONSDATA* consdata;
5726 SCIP_VAR** infcheckvars;
5727 SCIP_Real* infcheckvals;
5728 SCIP_Real minactinfvars;
5729 SCIP_Real maxactinfvars;
5730 SCIP_Real lb;
5731 SCIP_Real ub;
5732 SCIP_Real feastol;
5733 SCIP_Real fixedact;
5734 SCIP_Real lhs;
5735 SCIP_Real rhs;
5736 SCIP_Real absminbincoef;
5737 SCIP_Longint gcd;
5738 SCIP_Longint gcdtmp;
5739 SCIP_Bool minactinfvarsinvalid;
5740 SCIP_Bool maxactinfvarsinvalid;
5741 SCIP_Bool possiblegcd;
5742 SCIP_Bool gcdisone;
5743 SCIP_Bool addartconss;
5744 int ninfcheckvars;
5745 int nunfixedvars;
5746 int nfixedconsvars;
5747 int ncontvars;
5748 int pos;
5749 int v;
5750
5751 assert(scip != NULL);
5752 assert(cons != NULL);
5753 assert(cutoff != NULL);
5754 assert(nfixedvars != NULL);
5755 assert(nchgbds != NULL);
5756 assert(naddconss != NULL);
5757
5758 /* modifiable constraint can be changed so we do not have all necessary information */
5759 if( SCIPconsIsModifiable(cons) )
5760 return SCIP_OKAY;
5761
5762 consdata = SCIPconsGetData(cons);
5763 assert(consdata != NULL);
5764
5765 /* we already did full ranged row propagation */
5766 if( consdata->rangedrowpropagated == 2 )
5767 return SCIP_OKAY;
5768
5769 /* at least three variables are needed */
5770 if( consdata->nvars < 3 )
5771 return SCIP_OKAY;
5772
5773 /* do nothing on normal inequalities */
5774 if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
5775 return SCIP_OKAY;
5776
5777 /* get constraint handler data */
5778 conshdlr = SCIPconsGetHdlr(cons);
5779 assert(conshdlr != NULL);
5780 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5781 assert(conshdlrdata != NULL);
5782
5783 addartconss = conshdlrdata->rangedrowartcons && SCIPgetDepth(scip) < 1 && !SCIPinProbing(scip) && !SCIPinRepropagation(scip);
5784
5785 /* we may add artificial constraints */
5786 if( addartconss )
5787 consdata->rangedrowpropagated = 2;
5788 /* we are not allowed to add artificial constraints during propagation; if nothing changed on this constraint since
5789 * the last rangedrowpropagation, we can stop; otherwise, we mark this constraint to be rangedrowpropagated without
5790 * artificial constraints
5791 */
5792 else
5793 {
5794 if( consdata->rangedrowpropagated > 0 )
5795 return SCIP_OKAY;
5796
5797 consdata->rangedrowpropagated = 1;
5798 }
5799 fixedact = 0;
5800 nfixedconsvars = 0;
5801 /* calculate fixed activity and number of fixed variables */
5802 for( v = consdata->nvars - 1; v >= 0; --v )
5803 {
5804 /* all zero coefficients should be eliminated */
5805 assert(!SCIPisZero(scip, consdata->vals[v]));
5806
5807 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5808 {
5809 fixedact += SCIPvarGetLbLocal(consdata->vars[v]) * consdata->vals[v];
5810 ++nfixedconsvars;
5811 }
5812 }
5813
5814 /* do not work with huge fixed activities */
5815 if( SCIPisHugeValue(scip, REALABS(fixedact)) )
5816 return SCIP_OKAY;
5817
5818 /* compute lhs and rhs for unfixed variables only and get number of unfixed variables */
5819 assert(!SCIPisInfinity(scip, -fixedact) && !SCIPisInfinity(scip, fixedact));
5820 lhs = consdata->lhs - fixedact;
5821 rhs = consdata->rhs - fixedact;
5822 nunfixedvars = consdata->nvars - nfixedconsvars;
5823
5824 /* allocate temporary memory for variables and coefficients which may lead to infeasibility */
5825 SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvars, nunfixedvars) );
5826 SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvals, nunfixedvars) );
5827
5828 absminbincoef = SCIP_REAL_MAX;
5829 ncontvars = 0;
5830 gcdisone = TRUE;
5831 possiblegcd = TRUE;
5832
5833 /* we now partition all unfixed variables in two groups:
5834 *
5835 * the first one contains all integral variable with integral
5836 * coefficient so that all variables in this group will have a gcd greater than 1, this group will be implicitly
5837 * given
5838 *
5839 * the second group will contain all left unfixed variables and will be saved as infcheckvars with corresponding
5840 * coefficients as infcheckvals, the order of these variables should be the same as in the consdata object
5841 */
5842
5843 /* find first integral variables with integral coefficient greater than 1, thereby collecting all other unfixed
5844 * variables
5845 */
5846 ninfcheckvars = 0;
5847 v = -1;
5848 pos = -1;
5849 do
5850 {
5851 ++v;
5852
5853 /* partition the variables, do not change the order of collection, because it might be used later on */
5854 while( v < consdata->nvars && ( !SCIPvarIsIntegral(consdata->vars[v])
5855 || !SCIPisIntegral(scip, consdata->vals[v]) || SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0) ) )
5856 {
5857 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5858 {
5859 if( !SCIPvarIsIntegral(consdata->vars[v]) )
5860 ++ncontvars;
5861 else if( SCIPvarIsBinary(consdata->vars[v]) )
5862 {
5863 SCIP_Real absval;
5864
5865 absval = REALABS(consdata->vals[v]);
5866
5867 if( absminbincoef > absval )
5868 absminbincoef = absval;
5869 }
5870
5871 gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5872 possiblegcd = FALSE;
5873 infcheckvars[ninfcheckvars] = consdata->vars[v];
5874 infcheckvals[ninfcheckvars] = consdata->vals[v];
5875 ++ninfcheckvars;
5876
5877 if( pos == -1 )
5878 pos = v;
5879 }
5880 ++v;
5881 }
5882 }
5883 while( v < consdata->nvars && SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) );
5884
5885 /* if the first group of variables is empty, we stop */
5886 /* @todo try to propagate/split up a constraint of the form:
5887 * x_1 + ... + x_m + a_1*y_1 + ... + a_n*y_n = k + c,
5888 * 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]
5889 */
5890 if( v == consdata->nvars )
5891 goto TERMINATE;
5892
5893 /* we need at least two non-continuous variables */
5894 if( ncontvars + 2 > nunfixedvars )
5895 goto TERMINATE;
5896
5897 assert(!SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])));
5898 assert(SCIPvarIsIntegral(consdata->vars[v]) && SCIPisIntegral(scip, consdata->vals[v]) && REALABS(consdata->vals[v]) > 1.5);
5899
5900 feastol = SCIPfeastol(scip);
5901
5902 gcd = (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol);
5903 assert(gcd >= 2);
5904
5905 /* go on to partition the variables, do not change the order of collection, because it might be used later on;
5906 * calculate gcd over the first part of variables */
5907 for( ; v < consdata->nvars; ++v )
5908 {
5909 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5910 continue;
5911
5912 if( SCIPvarIsBinary(consdata->vars[v]) )
5913 {
5914 SCIP_Real absval;
5915
5916 absval = REALABS(consdata->vals[v]);
5917
5918 if( absminbincoef > absval )
5919 absminbincoef = absval;
5920 }
5921
5922 if( !SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v])
5923 || SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0) )
5924 {
5925 if( !SCIPvarIsIntegral(consdata->vars[v]) )
5926 ++ncontvars;
5927
5928 gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5929 possiblegcd = FALSE;
5930 infcheckvars[ninfcheckvars] = consdata->vars[v];
5931 infcheckvals[ninfcheckvars] = consdata->vals[v];
5932
5933 ++ninfcheckvars;
5934
5935 if( pos == -1 )
5936 pos = v;
5937 }
5938 else
5939 {
5940 assert(REALABS(consdata->vals[v]) > 1.5);
5941
5942 gcdtmp = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol));
5943 assert(gcdtmp >= 1);
5944
5945 if( gcdtmp == 1 )
5946 {
5947 infcheckvars[ninfcheckvars] = consdata->vars[v];
5948 infcheckvals[ninfcheckvars] = consdata->vals[v];
5949
5950 ++ninfcheckvars;
5951
5952 if( pos == -1 )
5953 pos = v;
5954 }
5955 else
5956 gcd = gcdtmp;
5957 }
5958 }
5959 assert(gcd >= 2);
5960
5961 /* it should not happen that all variables are of integral type and have a gcd >= 2, this should be done by
5962 * normalizeCons() */
5963 if( ninfcheckvars == 0 )
5964 goto TERMINATE;
5965
5966 assert(pos >= 0);
5967
5968 minactinfvarsinvalid = FALSE;
5969 maxactinfvarsinvalid = FALSE;
5970 maxactinfvars = 0.0;
5971 minactinfvars = 0.0;
5972
5973 /* calculate activities over all infcheckvars */
5974 for( v = ninfcheckvars - 1; v >= 0; --v )
5975 {
5976 lb = SCIPvarGetLbLocal(infcheckvars[v]);
5977 ub = SCIPvarGetUbLocal(infcheckvars[v]);
5978
5979 if( SCIPisInfinity(scip, -lb) )
5980 {
5981 if( infcheckvals[v] < 0.0 )
5982 maxactinfvarsinvalid = TRUE;
5983 else
5984 minactinfvarsinvalid = TRUE;
5985 }
5986 else
5987 {
5988 if( infcheckvals[v] < 0.0 )
5989 maxactinfvars += infcheckvals[v] * lb;
5990 else
5991 minactinfvars += infcheckvals[v] * lb;
5992 }
5993
5994 if( SCIPisInfinity(scip, ub) )
5995 {
5996 if( infcheckvals[v] > 0.0 )
5997 maxactinfvarsinvalid = TRUE;
5998 else
5999 minactinfvarsinvalid = TRUE;
6000 }
6001 else
6002 {
6003 if( infcheckvals[v] > 0.0 )
6004 maxactinfvars += infcheckvals[v] * ub;
6005 else
6006 minactinfvars += infcheckvals[v] * ub;
6007 }
6008
6009 /* better abort on to big values */
6010 if( SCIPisHugeValue(scip, -minactinfvars) )
6011 minactinfvarsinvalid = TRUE;
6012 if( SCIPisHugeValue(scip, maxactinfvars) )
6013 maxactinfvarsinvalid = TRUE;
6014
6015 if( minactinfvarsinvalid || maxactinfvarsinvalid )
6016 goto TERMINATE;
6017 }
6018 assert(!minactinfvarsinvalid && !maxactinfvarsinvalid);
6019
6020 SCIPdebugMsg(scip, "minactinfvarsinvalid = %u, minactinfvars = %g, maxactinfvarsinvalid = %u, maxactinfvars = %g, gcd = %lld, ninfcheckvars = %d, ncontvars = %d\n",
6021 minactinfvarsinvalid, minactinfvars, maxactinfvarsinvalid, maxactinfvars, gcd, ninfcheckvars, ncontvars);
6022
6023 /* @todo maybe we took the wrong variables as infcheckvars we could try to exchange integer variables */
6024 /* @todo if minactinfvarsinvalid or maxactinfvarsinvalid are true, try to exchange both partitions to maybe get valid
6025 * activities */
6026 /* @todo calculate minactivity and maxactivity for all non-intcheckvars, and use this for better bounding,
6027 * !!!note!!!
6028 * that therefore the conflict variables in addConflictFixedVars() need to be extended by all variables which
6029 * are not at their global bound
6030 */
6031
6032 /* check if between left hand side and right hand side exist a feasible point, if not the constraint leads to
6033 * infeasibility */
6034 if( !SCIPisIntegral(scip, (lhs - maxactinfvars) / gcd) &&
6035 SCIPisGT(scip, SCIPceil(scip, (lhs - maxactinfvars) / gcd) * gcd, rhs - minactinfvars) )
6036 {
6037 SCIPdebugMsg(scip, "no feasible value exist, constraint <%s> lead to infeasibility", SCIPconsGetName(cons));
6039
6040 /* start conflict analysis */
6041 /* @todo improve conflict analysis by adding relaxed bounds */
6042 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6043
6044 *cutoff = TRUE;
6045 }
6046 else if( ncontvars == 0 )
6047 {
6048 SCIP_Longint gcdinfvars = -1;
6049
6050 /* check for gcd over all infcheckvars */
6051 if( possiblegcd )
6052 {
6053 v = ninfcheckvars - 1;
6054 gcdinfvars = (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol);
6055 assert(gcdinfvars >= 2);
6056
6057 for( ; v >= 0 && gcdinfvars >= 2; --v )
6058 {
6059 gcdinfvars = SCIPcalcGreComDiv(gcdinfvars, (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol));
6060 }
6061 }
6062 else if( gcdisone )
6063 gcdinfvars = 1;
6064
6065 SCIPdebugMsg(scip, "gcdinfvars =%lld, possiblegcd = %u\n", gcdinfvars, possiblegcd);
6066
6067 /* compute solutions for this ranged row, if all variables are of integral type with integral coefficients */
6068 if( gcdinfvars >= 1 )
6069 {
6070 SCIP_Real value;
6071 SCIP_Real value2;
6072 SCIP_Real minvalue = SCIP_INVALID;
6073 SCIP_Real maxvalue = SCIP_INVALID;
6074 int nsols = 0;
6075
6076 value = SCIPceil(scip, minactinfvars - SCIPfeastol(scip));
6077
6078 /* check how many possible solutions exist */
6079 while( SCIPisLE(scip, value, maxactinfvars) )
6080 {
6081 value2 = value + gcd * (SCIPceil(scip, (lhs - value) / gcd));
6082
6083 /* value2 might violate lhs due to numerics, in this case take the next divisible number */
6084 if( !SCIPisGE(scip, value2, lhs) )
6085 {
6086 value2 += gcd;
6087 }
6088
6089 if( SCIPisLE(scip, value2, rhs) )
6090 {
6091 ++nsols;
6092
6093 /* early termination if we found more than two solutions */
6094 if( nsols == 3 )
6095 break;
6096
6097 if( minvalue == SCIP_INVALID ) /*lint !e777*/
6098 minvalue = value;
6099
6100 maxvalue = value;
6101 }
6102 value += gcdinfvars;
6103 }
6104 assert(nsols < 2 || minvalue <= maxvalue);
6105
6106 /* determine last possible solution for better bounding */
6107 if( nsols == 3 )
6108 {
6109#ifndef NDEBUG
6110 SCIP_Real secondsolval = maxvalue;
6111#endif
6112 value = SCIPfloor(scip, maxactinfvars + SCIPfeastol(scip));
6113
6114 /* check how many possible solutions exist */
6115 while( SCIPisGE(scip, value, minactinfvars) )
6116 {
6117 value2 = value + gcd * (SCIPfloor(scip, (rhs - value) / gcd));
6118
6119 /* value2 might violate rhs due to numerics, in this case take the next divisible number */
6120 if( !SCIPisLE(scip, value2, rhs) )
6121 {
6122 value2 -= gcd;
6123 }
6124
6125 if( SCIPisGE(scip, value2, lhs) )
6126 {
6127 maxvalue = value;
6128 assert(maxvalue > minvalue);
6129 break;
6130 }
6131 value -= gcdinfvars;
6132 }
6133 assert(maxvalue > secondsolval);
6134 }
6135
6136 SCIPdebugMsg(scip, "here nsols %s %d, minsolvalue = %g, maxsolvalue = %g, ninfcheckvars = %d, nunfixedvars = %d\n",
6137 nsols > 2 ? ">=" : "=", nsols, minvalue, maxvalue, ninfcheckvars, nunfixedvars);
6138
6139 /* no possible solution found */
6140 if( nsols == 0 )
6141 {
6142 SCIPdebugMsg(scip, "gcdinfvars = %lld, gcd = %lld, correctedlhs = %g, correctedrhs = %g\n",
6143 gcdinfvars, gcd, lhs, rhs);
6144 SCIPdebugMsg(scip, "no solution found; constraint <%s> lead to infeasibility\n", SCIPconsGetName(cons));
6146
6147 /* start conflict analysis */
6148 /* @todo improve conflict analysis by adding relaxed bounds */
6149 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6150
6151 *cutoff = TRUE;
6152 }
6153 /* if only one solution exist we can extract a new constraint or fix variables */
6154 else if( nsols == 1 )
6155 {
6156 assert(minvalue == maxvalue); /*lint !e777*/
6157
6158 /* we can fix the only variable in our second set of variables */
6159 if( ninfcheckvars == 1 )
6160 {
6161 SCIP_Bool fixed;
6162
6163 assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6164
6165 SCIPdebugMsg(scip, "fixing single variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6166 SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]),
6167 SCIPvarGetUbLocal(infcheckvars[0]), maxvalue/infcheckvals[0]);
6168
6169 /* fix variable to only possible value */
6170 SCIP_CALL( SCIPinferVarFixCons(scip, infcheckvars[0], maxvalue/infcheckvals[0], cons,
6171 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &fixed) );
6172
6173 if( *cutoff )
6174 {
6175 /* start conflict analysis */
6176 /* @todo improve conflict analysis by adding relaxed bounds */
6177 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6178 }
6179
6180 if( fixed )
6181 ++(*nfixedvars);
6182 }
6183 else
6184 {
6185 /* check for exactly one unfixed variable which is not part of the infcheckvars */
6186 if( ninfcheckvars == nunfixedvars - 1 )
6187 {
6189 SCIP_Bool foundvar = FALSE;
6190 SCIP_Bool fixed;
6191 int w = 0;
6192
6193 assert(ninfcheckvars > 0);
6194
6195 /* find variable which is not an infcheckvar and fix it */
6196 for( v = 0; v < consdata->nvars - 1; ++v )
6197 {
6198 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6199 {
6200 if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6201 {
6202#ifndef NDEBUG
6203 int v2 = v + 1;
6204 int w2 = w;
6205
6206 assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6207
6208 for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6209 {
6210 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6211 continue;
6212
6213 assert(consdata->vars[v2] == infcheckvars[w2]);
6214 ++w2;
6215 }
6216 assert(w2 == ninfcheckvars);
6217#endif
6218 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6219
6220 foundvar = TRUE;
6221
6222 if( consdata->vals[v] < 0 )
6223 {
6224 bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6225 }
6226 else
6227 {
6228 bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6229 }
6230
6231 SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6232 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6233 SCIPvarGetUbLocal(consdata->vars[v]), bound);
6234
6235 /* fix variable to only possible value */
6236 SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6238
6239 if( *cutoff )
6240 {
6241 /* start conflict analysis */
6242 /* @todo improve conflict analysis by adding relaxed bounds */
6243 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6244 consdata->vars[v], bound) );
6245 }
6246
6247 if( fixed )
6248 ++(*nfixedvars);
6249
6250 break;
6251 }
6252
6253 ++w;
6254 }
6255 }
6256
6257 /* maybe last variable was the not infcheckvar */
6258 if( !foundvar )
6259 {
6260 assert(v == consdata->nvars - 1);
6261 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6262
6263 if( consdata->vals[v] < 0 )
6264 {
6265 bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6266 }
6267 else
6268 {
6269 bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6270 }
6271
6272 SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6273 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6274 SCIPvarGetUbLocal(consdata->vars[v]), bound);
6275
6276 /* fix variable to only possible value */
6277 SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6279
6280 if( *cutoff )
6281 {
6282 /* start conflict analysis */
6283 /* @todo improve conflict analysis by adding relaxed bounds */
6284 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6285 consdata->vars[v], bound) );
6286 }
6287
6288 if( fixed )
6289 ++(*nfixedvars);
6290 }
6291 }
6292 else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6293 {
6294 /* aggregation possible if we have two variables, but this will be done later on */
6295 SCIP_CONS* newcons;
6296 char name[SCIP_MAXSTRLEN];
6297
6298 /* create, add, and release new artificial constraint */
6299 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6300 ++conshdlrdata->naddconss;
6301
6302 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6303
6304 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals,
6305 maxvalue, maxvalue, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6306 SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6307
6308 SCIPdebugPrintCons(scip, newcons, NULL);
6309
6310 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6311
6312 ++(*naddconss);
6313 }
6314 }
6315 }
6316 /* at least two solutions */
6317 else
6318 {
6319 /* @todo if we found more then one solution, we may reduced domains due to dualpresolving? */
6320
6321 /* only one variable in the second set, so we can bound this variables */
6322 if( ninfcheckvars == 1 )
6323 {
6324 SCIP_Bool tightened;
6325 SCIP_Real newlb;
6326 SCIP_Real newub;
6327
6328 assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6329
6330 if( infcheckvals[0] < 0 )
6331 {
6332 newlb = maxvalue/infcheckvals[0];
6333 newub = minvalue/infcheckvals[0];
6334 }
6335 else
6336 {
6337 newlb = minvalue/infcheckvals[0];
6338 newub = maxvalue/infcheckvals[0];
6339 }
6340 assert(newlb < newub);
6341
6342 if( newlb > SCIPvarGetLbLocal(infcheckvars[0]) )
6343 {
6344 /* update lower bound of variable */
6345 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6346 SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]), newlb);
6347
6348 /* tighten variable lower bound to minimal possible value */
6349 SCIP_CALL( SCIPinferVarLbCons(scip, infcheckvars[0], newlb, cons,
6350 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6351
6352 if( *cutoff )
6353 {
6354 /* start conflict analysis */
6355 /* @todo improve conflict analysis by adding relaxed bounds */
6356 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6357 }
6358
6359 if( tightened )
6360 ++(*nchgbds);
6361 }
6362
6363 if( newub < SCIPvarGetUbLocal(infcheckvars[0]) )
6364 {
6365 /* update upper bound of variable */
6366 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6367 SCIPvarGetName(infcheckvars[0]), SCIPvarGetUbLocal(infcheckvars[0]), newub);
6368
6369 /* tighten variable upper bound to maximal possible value */
6370 SCIP_CALL( SCIPinferVarUbCons(scip, infcheckvars[0], newub, cons,
6371 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6372
6373 if( *cutoff )
6374 {
6375 /* start conflict analysis */
6376 /* @todo improve conflict analysis by adding relaxed bounds */
6377 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6378 }
6379
6380 if( tightened )
6381 ++(*nchgbds);
6382 }
6383 }
6384 /* check if we have only one not infcheckvars, if so we can tighten this variable */
6385 else if( ninfcheckvars == nunfixedvars - 1 )
6386 {
6387 SCIP_Bool foundvar = FALSE;
6388 SCIP_Bool tightened;
6389 SCIP_Real newlb;
6390 SCIP_Real newub;
6391 int w = 0;
6392
6393 assert(ninfcheckvars > 0);
6394 assert(minvalue < maxvalue);
6395
6396 /* find variable which is not an infcheckvar and fix it */
6397 for( v = 0; v < consdata->nvars - 1; ++v )
6398 {
6399 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6400 {
6401 if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6402 {
6403#ifndef NDEBUG
6404 int v2 = v + 1;
6405 int w2 = w;
6406
6407 assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6408
6409 for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6410 {
6411 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6412 continue;
6413
6414 assert(consdata->vars[v2] == infcheckvars[w2]);
6415 ++w2;
6416 }
6417 assert(w2 == ninfcheckvars);
6418#endif
6419
6420 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6421 foundvar = TRUE;
6422
6423 if( consdata->vals[v] < 0 )
6424 {
6425 newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6426 newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6427 }
6428 else
6429 {
6430 newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6431 newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6432 }
6433 assert(SCIPisLE(scip, newlb, newub));
6434
6435 if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6436 {
6437 /* update lower bound of variable */
6438 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6439 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6440
6441 /* tighten variable lower bound to minimal possible value */
6442 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6443 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6444
6445 if( *cutoff )
6446 {
6447 /* start conflict analysis */
6448 /* @todo improve conflict analysis by adding relaxed bounds */
6449 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6450 consdata->vars[v], newlb) );
6451 }
6452
6453 if( tightened )
6454 ++(*nchgbds);
6455 }
6456
6457 if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6458 {
6459 /* update upper bound of variable */
6460 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6461 SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6462
6463 /* tighten variable upper bound to maximal possible value */
6464 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6465 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6466
6467 if( *cutoff )
6468 {
6469 /* start conflict analysis */
6470 /* @todo improve conflict analysis by adding relaxed bounds */
6471 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6472 consdata->vars[v], newub) );
6473 }
6474
6475 if( tightened )
6476 ++(*nchgbds);
6477 }
6478
6479 break;
6480 }
6481
6482 ++w;
6483 }
6484 }
6485
6486 /* maybe last variable was the not infcheckvar */
6487 if( !foundvar )
6488 {
6489 assert(v == consdata->nvars - 1);
6490 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6491
6492 if( consdata->vals[v] < 0 )
6493 {
6494 newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6495 newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6496 }
6497 else
6498 {
6499 newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6500 newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6501 }
6502 assert(SCIPisLE(scip, newlb, newub));
6503
6504 if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6505 {
6506 /* update lower bound of variable */
6507 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6508 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6509
6510 /* tighten variable lower bound to minimal possible value */
6511 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6512 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6513
6514 if( *cutoff )
6515 {
6516 /* start conflict analysis */
6517 /* @todo improve conflict analysis by adding relaxed bounds */
6518 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newlb) );
6519 }
6520
6521 if( tightened )
6522 ++(*nchgbds);
6523 }
6524
6525 if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6526 {
6527 /* update upper bound of variable */
6528 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6529 SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6530
6531 /* tighten variable upper bound to maximal possible value */
6532 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6533 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6534
6535 if( *cutoff )
6536 {
6537 /* start conflict analysis */
6538 /* @todo improve conflict analysis by adding relaxed bounds */
6539 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newub) );
6540 }
6541
6542 if( tightened )
6543 ++(*nchgbds);
6544 }
6545 }
6546 }
6547 /* at least two solutions and more than one variable, so we add a new constraint which bounds the feasible
6548 * region for our infcheckvars, if possible
6549 */
6550 else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6551 {
6552 SCIP_CONS* newcons;
6553 char name[SCIP_MAXSTRLEN];
6554 SCIP_Real newlhs;
6555 SCIP_Real newrhs;
6556
6557 assert(maxvalue > minvalue);
6558
6559 if( SCIPisGT(scip, minvalue, minactinfvars) )
6560 newlhs = minvalue;
6561 else
6562 newlhs = -SCIPinfinity(scip);
6563
6564 if( SCIPisLT(scip, maxvalue, maxactinfvars) )
6565 newrhs = maxvalue;
6566 else
6567 newrhs = SCIPinfinity(scip);
6568
6569 if( !SCIPisInfinity(scip, -newlhs) || !SCIPisInfinity(scip, newrhs) )
6570 {
6571 /* create, add, and release new artificial constraint */
6572 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons1_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6573 ++conshdlrdata->naddconss;
6574
6575 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6576
6577 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6579 SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6580
6581 SCIPdebugPrintCons(scip, newcons, NULL);
6582 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6583
6584 ++(*naddconss);
6585 }
6586 /* @todo maybe add constraint for all variables which are not infcheckvars, lhs should be minvalue, rhs
6587 * should be maxvalue */
6588 }
6589 }
6590 }
6591 }
6592 else if( addartconss && ncontvars < ninfcheckvars )
6593 {
6594 SCIP_Real maxact = 0.0;
6595 SCIP_Real minact = 0.0;
6596 int w = 0;
6597
6598 /* compute activities of non-infcheckvars */
6599 for( v = 0; v < consdata->nvars; ++v )
6600 {
6601 if( w < ninfcheckvars && consdata->vars[v] == infcheckvars[w] )
6602 {
6603 ++w;
6604 continue;
6605 }
6606
6607 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6608 {
6609 if( SCIPvarIsBinary(consdata->vars[v]) )
6610 {
6611 if( consdata->vals[v] > 0.0 )
6612 maxact += consdata->vals[v];
6613 else
6614 minact += consdata->vals[v];
6615 }
6616 else
6617 {
6618 SCIP_Real tmpval;
6619
6620 assert(SCIPvarIsIntegral(consdata->vars[v]));
6621
6622 if( consdata->vals[v] > 0.0 )
6623 {
6624 tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6625
6626 if( SCIPisHugeValue(scip, -tmpval) )
6627 break;
6628
6629 minact += tmpval;
6630
6631 tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6632
6633 if( SCIPisHugeValue(scip, tmpval) )
6634 break;
6635
6636 maxact += tmpval;
6637 }
6638 else
6639 {
6640 tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6641
6642 if( SCIPisHugeValue(scip, -tmpval) )
6643 break;
6644
6645 minact += tmpval;
6646
6647 tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6648
6649 if( SCIPisHugeValue(scip, tmpval) )
6650 break;
6651
6652 maxact += tmpval;
6653 }
6654 }
6655 }
6656 }
6657 if( v == consdata->nvars && !SCIPisHugeValue(scip, -minact) && !SCIPisHugeValue(scip, maxact) )
6658 {
6659 SCIP_CONS* newcons;
6660 char name[SCIP_MAXSTRLEN];
6661 SCIP_Real newlhs;
6662 SCIP_Real newrhs;
6663
6664 assert(maxact > minact);
6665 assert(w == ninfcheckvars);
6666
6667 newlhs = lhs - maxact;
6668 newrhs = rhs - minact;
6669 assert(newlhs < newrhs);
6670
6671 /* create, add, and release new artificial constraint */
6672 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons2_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6673 ++conshdlrdata->naddconss;
6674
6675 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6676
6677 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6679 SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6680
6681 SCIPdebugPrintCons(scip, newcons, NULL);
6682 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6683
6684 ++(*naddconss);
6685 }
6686 }
6687
6688 TERMINATE:
6689 SCIPfreeBufferArray(scip, &infcheckvals);
6690 SCIPfreeBufferArray(scip, &infcheckvars);
6691
6692 return SCIP_OKAY;
6693}
6694
6695/** tightens bounds of a single variable due to activity bounds */
6696static
6698 SCIP* scip, /**< SCIP data structure */
6699 SCIP_CONS* cons, /**< linear constraint */
6700 int pos, /**< position of the variable in the vars array */
6701 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6702 int* nchgbds, /**< pointer to count the total number of tightened bounds */
6703 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
6704 )
6705{
6706 SCIP_CONSDATA* consdata;
6707 SCIP_VAR* var;
6708 SCIP_Real val;
6709 SCIP_Real lb;
6710 SCIP_Real ub;
6711 SCIP_Real minresactivity;
6712 SCIP_Real maxresactivity;
6713 SCIP_Real lhs;
6714 SCIP_Real rhs;
6715 SCIP_Bool infeasible;
6716 SCIP_Bool tightened;
6717 SCIP_Bool ismintight;
6718 SCIP_Bool ismaxtight;
6719 SCIP_Bool isminsettoinfinity;
6720 SCIP_Bool ismaxsettoinfinity;
6721
6722 assert(scip != NULL);
6723 assert(cons != NULL);
6724 assert(cutoff != NULL);
6725 assert(nchgbds != NULL);
6726
6727 /* we cannot tighten variables' bounds, if the constraint may be not complete */
6728 if( SCIPconsIsModifiable(cons) )
6729 return SCIP_OKAY;
6730
6731 consdata = SCIPconsGetData(cons);
6732 assert(consdata != NULL);
6733 assert(0 <= pos && pos < consdata->nvars);
6734
6735 *cutoff = FALSE;
6736
6737 var = consdata->vars[pos];
6738
6739 /* we cannot tighten bounds of multi-aggregated variables */
6741 return SCIP_OKAY;
6742
6743 val = consdata->vals[pos];
6744 lhs = consdata->lhs;
6745 rhs = consdata->rhs;
6746 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
6747 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
6748 assert(var != NULL);
6749 assert(!SCIPisZero(scip, val));
6750 assert(!SCIPisInfinity(scip, lhs));
6751 assert(!SCIPisInfinity(scip, -rhs));
6752
6753 lb = SCIPvarGetLbLocal(var);
6754 ub = SCIPvarGetUbLocal(var);
6755 assert(SCIPisLE(scip, lb, ub));
6756
6757 if( val > 0.0 )
6758 {
6759 /* check, if we can tighten the variable's bounds reliably, therefore only consider sides which are small or
6760 * relatively different to the residual activity bound to avoid cancellation leading to numerical difficulties
6761 */
6762 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && ismintight
6763 && ( SCIPisLT(scip, ABS(rhs), 1.0) || !SCIPisEQ(scip, minresactivity / rhs, 1.0) ) )
6764 {
6765 SCIP_Real newub;
6766
6767 newub = (rhs - minresactivity)/val;
6768
6769 if( !SCIPisInfinity(scip, newub) &&
6770 ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6771 {
6772 SCIP_Bool activityunreliable;
6773 activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6774
6775 /* check minresactivities for reliability */
6776 if( activityunreliable )
6777 {
6778 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6779 newub = (rhs - minresactivity)/val;
6780 activityunreliable = SCIPisInfinity(scip, -minresactivity) ||
6781 (!SCIPisUbBetter(scip, newub, lb, ub) && (!SCIPisFeasLT(scip, newub, ub) || !SCIPvarIsIntegral(var))
6782 && (!force || !SCIPisLT(scip, newub, ub)));
6783 }
6784
6785 if( !activityunreliable )
6786 {
6787 /* tighten upper bound */
6788 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
6789 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6790 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6791 &infeasible, &tightened) );
6792 if( infeasible )
6793 {
6794 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6795 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6796
6797 /* analyze conflict */
6799
6800 *cutoff = TRUE;
6801 return SCIP_OKAY;
6802 }
6803 if( tightened )
6804 {
6805 ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6806 assert(SCIPisFeasLE(scip, ub, newub));
6807 (*nchgbds)++;
6808
6809 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6810 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6811 }
6812 }
6813 }
6814 }
6815
6816 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && ismaxtight
6817 && ( SCIPisLT(scip, ABS(lhs), 1.0) || !SCIPisEQ(scip, maxresactivity / lhs, 1.0) ) )
6818 {
6819 SCIP_Real newlb;
6820
6821 newlb = (lhs - maxresactivity)/val;
6822 if( !SCIPisInfinity(scip, -newlb) &&
6823 ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6824 {
6825 /* check maxresactivities for reliability */
6826 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6827 {
6828 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6829 newlb = (lhs - maxresactivity)/val;
6830
6831 if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisLbBetter(scip, newlb, lb, ub)
6832 && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6833 && (!force || !SCIPisGT(scip, newlb, lb))) )
6834 return SCIP_OKAY;
6835 }
6836
6837 /* tighten lower bound */
6838 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6839 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6840 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6841 &infeasible, &tightened) );
6842 if( infeasible )
6843 {
6844 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6845 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6846
6847 /* analyze conflict */
6849
6850 *cutoff = TRUE;
6851 return SCIP_OKAY;
6852 }
6853 if( tightened )
6854 {
6855 lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6856 assert(SCIPisFeasGE(scip, lb, newlb));
6857 (*nchgbds)++;
6858 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6859 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6860 }
6861 }
6862 }
6863 }
6864 else
6865 {
6866 /* check, if we can tighten the variable's bounds reliably, therefore only consider sides which are small or
6867 * relatively different to the residual activity bound to avoid cancellation leading to numerical difficulties
6868 */
6869 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && ismintight
6870 && ( SCIPisLT(scip, ABS(rhs), 1.0) || !SCIPisEQ(scip, minresactivity / rhs, 1.0) ) )
6871 {
6872 SCIP_Real newlb;
6873
6874 newlb = (rhs - minresactivity)/val;
6875 if( !SCIPisInfinity(scip, -newlb) &&
6876 ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6877 {
6878 SCIP_Bool activityunreliable;
6879 activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6880 /* check minresactivities for reliability */
6881 if( activityunreliable )
6882 {
6883 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6884 newlb = (rhs - minresactivity)/val;
6885
6886 activityunreliable = SCIPisInfinity(scip, -minresactivity)
6887 || (!SCIPisLbBetter(scip, newlb, lb, ub) && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6888 && (!force || !SCIPisGT(scip, newlb, lb)));
6889 }
6890
6891 if( !activityunreliable )
6892 {
6893 /* tighten lower bound */
6894 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6895 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6896 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6897 &infeasible, &tightened) );
6898 if( infeasible )
6899 {
6900 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6901 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6902
6903 /* analyze conflict */
6905
6906 *cutoff = TRUE;
6907 return SCIP_OKAY;
6908 }
6909 if( tightened )
6910 {
6911 lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6912 assert(SCIPisFeasGE(scip, lb, newlb));
6913 (*nchgbds)++;
6914 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6915 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6916 }
6917 }
6918 }
6919 }
6920
6921 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && ismaxtight
6922 && ( SCIPisLT(scip, ABS(lhs), 1.0) || !SCIPisEQ(scip, maxresactivity / lhs, 1.0) ) )
6923 {
6924 SCIP_Real newub;
6925
6926 newub = (lhs - maxresactivity)/val;
6927 if( !SCIPisInfinity(scip, newub) &&
6928 ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6929 {
6930 /* check maxresactivities for reliability */
6931 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6932 {
6933 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6934 newub = (lhs - maxresactivity)/val;
6935
6936 if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisUbBetter(scip, newub, lb, ub)
6937 && (!SCIPisFeasLT(scip, newub, ub) && !SCIPvarIsIntegral(var))
6938 && (!force || !SCIPisLT(scip, newub, ub))) )
6939 return SCIP_OKAY;
6940 }
6941
6942 /* tighten upper bound */
6943 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g], newub=%.15g\n",
6944 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6945 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6946 &infeasible, &tightened) );
6947 if( infeasible )
6948 {
6949 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6950 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6951
6952 /* analyze conflict */
6954
6955 *cutoff = TRUE;
6956 return SCIP_OKAY;
6957 }
6958 if( tightened )
6959 {
6960 ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6961 assert(SCIPisFeasLE(scip, ub, newub));
6962 (*nchgbds)++;
6963 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6964 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6965 }
6966 }
6967 }
6968 }
6969
6970 return SCIP_OKAY;
6971}
6972
6973#define MAXTIGHTENROUNDS 10
6974
6975/** tightens bounds of variables in constraint due to activity bounds */
6976static
6978 SCIP* scip, /**< SCIP data structure */
6979 SCIP_CONS* cons, /**< linear constraint */
6980 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
6981 SCIP_Bool sortvars, /**< should variables be used in sorted order? */
6982 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6983 int* nchgbds /**< pointer to count the total number of tightened bounds */
6984 )
6985{
6986 SCIP_CONSDATA* consdata;
6987 unsigned int tightenmode;
6988 int nvars;
6989 int nrounds;
6990 int lastchange;
6991 int oldnchgbds;
6992#ifndef SCIP_DEBUG
6993 int oldnchgbdstotal;
6994#endif
6995 int v;
6996 SCIP_Bool force;
6997 SCIP_Bool easycase;
6998
6999 assert(scip != NULL);
7000 assert(cons != NULL);
7001 assert(nchgbds != NULL);
7002 assert(cutoff != NULL);
7003
7004 *cutoff = FALSE;
7005
7006 /* we cannot tighten variables' bounds, if the constraint may be not complete */
7007 if( SCIPconsIsModifiable(cons) )
7008 return SCIP_OKAY;
7009
7010 /* if a constraint was created after presolve, then it may hold fixed variables
7011 * if there are even multi-aggregated variables, then we cannot do bound tightening on these
7012 * thus, ensure here again that variable fixings have been applied
7013 */
7014 SCIP_CALL( applyFixings(scip, cons, cutoff) );
7015 if( *cutoff )
7016 return SCIP_OKAY;
7017
7018 /* check if constraint has any chances of tightening bounds */
7019 if( !canTightenBounds(cons) )
7020 return SCIP_OKAY;
7021
7022 consdata = SCIPconsGetData(cons);
7023 assert(consdata != NULL);
7024
7025 nvars = consdata->nvars;
7026 force = (nvars == 1) && !SCIPconsIsModifiable(cons);
7027
7028 /* we are at the root node or during presolving */
7029 if( SCIPgetDepth(scip) < 1 )
7030 tightenmode = 2;
7031 else
7032 tightenmode = 1;
7033
7034 /* stop if we already tightened the constraint and the tightening is not forced */
7035 if( !force && (consdata->boundstightened >= tightenmode) ) /*lint !e574*/
7036 return SCIP_OKAY;
7037
7038 /* ensure that the variables are properly sorted */
7039 if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7040 {
7041 SCIP_CALL( consdataSort(scip, consdata) );
7042 assert(consdata->coefsorted);
7043 }
7044
7045 /* update maximal activity delta if necessary */
7046 if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
7048
7049 assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
7050 assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
7051 checkMaxActivityDelta(scip, consdata);
7052
7053 /* this may happen if all variables are fixed */
7054 if( SCIPisFeasZero(scip, consdata->maxactdelta) )
7055 return SCIP_OKAY;
7056
7057 if( !SCIPisInfinity(scip, consdata->maxactdelta) )
7058 {
7059 SCIP_Real slack;
7060 SCIP_Real surplus;
7061 SCIP_Real minactivity;
7062 SCIP_Real maxactivity;
7063 SCIP_Bool ismintight;
7064 SCIP_Bool ismaxtight;
7065 SCIP_Bool isminsettoinfinity;
7066 SCIP_Bool ismaxsettoinfinity;
7067
7068 /* use maximal activity delta to skip propagation (cannot deduce anything) */
7069 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &ismintight, &ismaxtight,
7070 &isminsettoinfinity, &ismaxsettoinfinity);
7071 assert(!SCIPisInfinity(scip, minactivity));
7072 assert(!SCIPisInfinity(scip, -maxactivity));
7073
7074 slack = (SCIPisInfinity(scip, consdata->rhs) || isminsettoinfinity) ? SCIPinfinity(scip) : (consdata->rhs - minactivity);
7075 surplus = (SCIPisInfinity(scip, -consdata->lhs) || ismaxsettoinfinity) ? SCIPinfinity(scip) : (maxactivity - consdata->lhs);
7076
7077 /* check if the constraint will propagate */
7078 if( SCIPisLE(scip, consdata->maxactdelta, MIN(slack, surplus)) )
7079 return SCIP_OKAY;
7080 }
7081
7082 /* check if we can use fast implementation for easy and numerically well behaved cases */
7083 easycase = SCIPisLT(scip, consdata->maxactdelta, maxeasyactivitydelta);
7084
7085 /* as long as the bounds might be tightened again, try to tighten them; abort after a maximal number of rounds */
7086 lastchange = -1;
7087
7088#ifndef SCIP_DEBUG
7089 oldnchgbds = 0;
7090 oldnchgbdstotal = *nchgbds;
7091#endif
7092
7093 for( nrounds = 0; (force || consdata->boundstightened < tightenmode) && nrounds < MAXTIGHTENROUNDS; ++nrounds ) /*lint !e574*/
7094 {
7095 /* ensure that the variables are properly sorted
7096 *
7097 * note: it might happen that integer variables become binary during bound tightening at the root node
7098 */
7099 if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7100 {
7101 SCIP_CALL( consdataSort(scip, consdata) );
7102 assert(consdata->coefsorted);
7103 }
7104
7105 /* mark the constraint to have the variables' bounds tightened */
7106 consdata->boundstightened = (unsigned int)tightenmode;
7107
7108 /* try to tighten the bounds of each variable in the constraint. During solving process, the binary variable
7109 * sorting enables skipping variables
7110 */
7111 v = 0;
7112 while( v < nvars && v != lastchange && !(*cutoff) )
7113 {
7114 oldnchgbds = *nchgbds;
7115
7116 if( easycase )
7117 {
7118 SCIP_CALL( tightenVarBoundsEasy(scip, cons, v, cutoff, nchgbds, force) );
7119 }
7120 else
7121 {
7122 SCIP_CALL( tightenVarBounds(scip, cons, v, cutoff, nchgbds, force) );
7123 }
7124
7125 /* if there was no progress, skip the rest of the binary variables */
7126 if( *nchgbds > oldnchgbds )
7127 {
7128 lastchange = v;
7129 ++v;
7130 }
7131 else if( consdata->coefsorted && v < consdata->nbinvars - 1
7132 && !SCIPisFeasEQ(scip, SCIPvarGetUbLocal(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v])) )
7133 v = consdata->nbinvars;
7134 else
7135 ++v;
7136 }
7137
7138#ifndef SCIP_DEBUG
7139 SCIPdebugMessage("linear constraint <%s> found %d bound changes in round %d\n", SCIPconsGetName(cons),
7140 *nchgbds - oldnchgbdstotal, nrounds);
7141 oldnchgbdstotal += oldnchgbds;
7142#endif
7143 }
7144
7145#ifndef NDEBUG
7146 if( force && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
7147 assert(*cutoff || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->vars[0]), SCIPvarGetUbLocal(consdata->vars[0])));
7148#endif
7149
7150 return SCIP_OKAY;
7151}
7152
7153/** checks linear constraint for feasibility of given solution or current solution */
7154static
7156 SCIP* scip, /**< SCIP data structure */
7157 SCIP_CONS* cons, /**< linear constraint */
7158 SCIP_SOL* sol, /**< solution to be checked, or NULL for current solution */
7159 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
7160 SCIP_Bool checkrelmaxabs, /**< Should the violation for a constraint with side 0.0 be checked relative
7161 * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
7162 SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
7163 )
7164{
7165 SCIP_CONSDATA* consdata;
7166 SCIP_Real activity;
7167 SCIP_Real absviol;
7168 SCIP_Real relviol;
7169 SCIP_Real lhsviol;
7170 SCIP_Real rhsviol;
7171
7172 assert(scip != NULL);
7173 assert(cons != NULL);
7174 assert(violated != NULL);
7175
7176 SCIPdebugMsg(scip, "checking linear constraint <%s>\n", SCIPconsGetName(cons));
7178
7179 consdata = SCIPconsGetData(cons);
7180 assert(consdata != NULL);
7181
7182 *violated = FALSE;
7183
7184 if( consdata->row != NULL )
7185 {
7186 if( !checklprows && SCIProwIsInLP(consdata->row) )
7187 return SCIP_OKAY;
7188 else if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
7189 activity = consdataComputePseudoActivity(scip, consdata);
7190 else
7191 activity = SCIPgetRowSolActivity(scip, consdata->row, sol);
7192 }
7193 else
7194 activity = consdataGetActivity(scip, consdata, sol);
7195
7196 SCIPdebugMsg(scip, " consdata activity=%.15g (lhs=%.15g, rhs=%.15g, row=%p, checklprows=%u, rowinlp=%u, sol=%p, hascurrentnodelp=%u)\n",
7197 activity, consdata->lhs, consdata->rhs, (void*)consdata->row, checklprows,
7198 consdata->row == NULL ? 0 : SCIProwIsInLP(consdata->row), (void*)sol,
7199 consdata->row == NULL ? FALSE : SCIPhasCurrentNodeLP(scip));
7200
7201 /* calculate absolute and relative bound violations */
7202 lhsviol = consdata->lhs - activity;
7203 rhsviol = activity - consdata->rhs;
7204
7205 absviol = 0.0;
7206 relviol = 0.0;
7207 if( (lhsviol > 0) && (lhsviol > rhsviol) )
7208 {
7209 absviol = lhsviol;
7210 relviol = SCIPrelDiff(consdata->lhs, activity);
7211 }
7212 else if( rhsviol > 0 )
7213 {
7214 absviol = rhsviol;
7215 relviol = SCIPrelDiff(activity, consdata->rhs);
7216 }
7217
7218 /* the activity of pseudo solutions may be invalid if it comprises positive and negative infinity contributions; we
7219 * return infeasible for safety
7220 */
7221 if( activity == SCIP_INVALID ) /*lint !e777*/
7222 {
7223 assert(sol == NULL);
7224 *violated = TRUE;
7225
7226 /* set violation of invalid pseudo solutions */
7227 absviol = SCIP_INVALID;
7228 relviol = SCIP_INVALID;
7229
7230 /* reset constraint age since we are in enforcement */
7232 }
7233 /* check with relative tolerances (the default) */
7234 else if( !consdata->checkabsolute && (SCIPisFeasLT(scip, activity, consdata->lhs) || SCIPisFeasGT(scip, activity, consdata->rhs)) )
7235 {
7236 /* the "normal" check: one of the two sides is violated */
7237 if( !checkrelmaxabs )
7238 {
7239 *violated = TRUE;
7240
7241 /* only reset constraint age if we are in enforcement */
7242 if( sol == NULL )
7243 {
7245 }
7246 }
7247 /* the (much) more complicated check: we try to disregard random noise and violations of a 0.0 side which are
7248 * small compared to the absolute values occurring in the activity
7249 */
7250 else
7251 {
7252 SCIP_Real maxabs;
7253 SCIP_Real coef;
7254 SCIP_Real absval;
7255 SCIP_Real solval;
7256 int v;
7257
7258 maxabs = 1.0;
7259
7260 /* compute maximum absolute value */
7261 for( v = 0; v < consdata->nvars; ++v )
7262 {
7263 if( consdata->vals != NULL )
7264 {
7265 coef = consdata->vals[v];
7266 }
7267 else
7268 coef = 1.0;
7269
7270 solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
7271 absval = REALABS( coef * solval );
7272 maxabs = MAX( maxabs, absval );
7273 }
7274
7275 /* regard left hand side, first */
7276 if( SCIPisFeasLT(scip, activity, consdata->lhs) )
7277 {
7278 /* check whether violation is random noise */
7279 if( (consdata->lhs - activity) <= (1e-15 * maxabs) )
7280 {
7281 SCIPdebugMsg(scip, " lhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7282 consdata->lhs - activity, maxabs);
7284
7285 /* only increase constraint age if we are in enforcement */
7286 if( sol == NULL )
7287 {
7288 SCIP_CALL( SCIPincConsAge(scip, cons) );
7289 }
7290 }
7291 /* lhs is violated and lhs is 0.0: use relative tolerance w.r.t. largest absolute value */
7292 else if( SCIPisZero(scip, consdata->lhs) )
7293 {
7294 if( (consdata->lhs - activity) <= (SCIPfeastol(scip) * maxabs) )
7295 {
7296 SCIPdebugMsg(scip, " lhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7297 consdata->lhs - activity, maxabs);
7299
7300 /* only increase constraint age if we are in enforcement */
7301 if( sol == NULL )
7302 {
7303 SCIP_CALL( SCIPincConsAge(scip, cons) );
7304 }
7305 }
7306 else
7307 {
7308 *violated = TRUE;
7309
7310 /* only reset constraint age if we are in enforcement */
7311 if( sol == NULL )
7312 {
7314 }
7315 }
7316 }
7317 else
7318 {
7319 *violated = TRUE;
7320
7321 /* only reset constraint age if we are in enforcement */
7322 if( sol == NULL )
7323 {
7325 }
7326 }
7327 }
7328
7329 /* now regard right hand side */
7330 if( SCIPisFeasGT(scip, activity, consdata->rhs) )
7331 {
7332 /* check whether violation is random noise */
7333 if( (activity - consdata->rhs) <= (1e-15 * maxabs) )
7334 {
7335 SCIPdebugMsg(scip, " rhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7336 activity - consdata->rhs, maxabs);
7338
7339 /* only increase constraint age if we are in enforcement */
7340 if( sol == NULL )
7341 {
7342 SCIP_CALL( SCIPincConsAge(scip, cons) );
7343 }
7344 }
7345 /* rhs is violated and rhs is 0.0, use relative tolerance w.r.t. largest absolute value */
7346 else if( SCIPisZero(scip, consdata->rhs) )
7347 {
7348 if( (activity - consdata->rhs) <= (SCIPfeastol(scip) * maxabs) )
7349 {
7350 SCIPdebugMsg(scip, " rhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7351 activity - consdata->rhs, maxabs);
7353
7354 /* only increase constraint age if we are in enforcement */
7355 if( sol == NULL )
7356 {
7357 SCIP_CALL( SCIPincConsAge(scip, cons) );
7358 }
7359 }
7360 else
7361 {
7362 *violated = TRUE;
7363
7364 /* only reset constraint age if we are in enforcement */
7365 if( sol == NULL )
7366 {
7368 }
7369 }
7370 }
7371 else
7372 {
7373 *violated = TRUE;
7374
7375 /* only reset constraint age if we are in enforcement */
7376 if( sol == NULL )
7377 {
7379 }
7380 }
7381 }
7382 }
7383 }
7384 /* check with absolute tolerances */
7385 else if( consdata->checkabsolute &&
7386 ((!SCIPisInfinity(scip, -consdata->lhs) && SCIPisGT(scip, consdata->lhs-activity, SCIPfeastol(scip))) ||
7387 (!SCIPisInfinity(scip, consdata->rhs) && SCIPisGT(scip, activity-consdata->rhs, SCIPfeastol(scip)))) )
7388 {
7389 *violated = TRUE;
7390
7391 /* only reset constraint age if we are in enforcement */
7392 if( sol == NULL )
7393 {
7395 }
7396 }
7397 else
7398 {
7399 /* only increase constraint age if we are in enforcement */
7400 if( sol == NULL )
7401 {
7402 SCIP_CALL( SCIPincConsAge(scip, cons) );
7403 }
7404 }
7405
7406 /* update absolute and relative violation of the solution */
7407 if( sol != NULL )
7408 SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
7409
7410 return SCIP_OKAY;
7411}
7412
7413/** creates an LP row in a linear constraint data */
7414static
7416 SCIP* scip, /**< SCIP data structure */
7417 SCIP_CONS* cons /**< linear constraint */
7418 )
7419{
7420 SCIP_CONSDATA* consdata;
7421
7422 assert(scip != NULL);
7423 assert(cons != NULL);
7424
7425 consdata = SCIPconsGetData(cons);
7426 assert(consdata != NULL);
7427 assert(consdata->row == NULL);
7428
7429 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
7431
7432 SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) );
7433
7434 return SCIP_OKAY;
7435}
7436
7437/** adds linear constraint as cut to the LP */
7438static
7440 SCIP* scip, /**< SCIP data structure */
7441 SCIP_CONS* cons, /**< linear constraint */
7442 SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7443 )
7444{
7445 SCIP_CONSDATA* consdata;
7446
7447 assert(scip != NULL);
7448 assert(cons != NULL);
7449
7450 consdata = SCIPconsGetData(cons);
7451 assert(consdata != NULL);
7452
7453 if( consdata->row == NULL )
7454 {
7455 if( !SCIPconsIsModifiable(cons) )
7456 {
7457 /* 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
7458 * removing this here will make test cons/linear/fixedvar.c fail (as of 2018-12-03)
7459 */
7460 SCIP_CALL( applyFixings(scip, cons, cutoff) );
7461 if( *cutoff )
7462 return SCIP_OKAY;
7463 }
7464
7465 /* convert consdata object into LP row */
7466 SCIP_CALL( createRow(scip, cons) );
7467 }
7468 assert(consdata->row != NULL);
7469
7470 if( consdata->nvars == 0 )
7471 {
7472 SCIPdebugMsg(scip, "Empty linear constraint enters LP: <%s>\n", SCIPconsGetName(cons));
7473 }
7474
7475 /* insert LP row as cut */
7476 if( !SCIProwIsInLP(consdata->row) )
7477 {
7478 SCIPdebugMsg(scip, "adding relaxation of linear constraint <%s>: ", SCIPconsGetName(cons));
7479 SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL)) );
7480 /* if presolving is turned off, the row might be trivial */
7481 if ( ! SCIPisInfinity(scip, -consdata->lhs) || ! SCIPisInfinity(scip, consdata->rhs) )
7482 {
7483 SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, cutoff) );
7484 }
7485#ifndef NDEBUG
7486 else
7487 {
7488 int pr;
7489 int cr;
7490 SCIP_CALL( SCIPgetIntParam(scip, "presolving/maxrounds", &pr) );
7491 SCIP_CALL( SCIPgetIntParam(scip, "constraints/linear/maxprerounds", &cr) );
7492 assert( pr == 0 || cr == 0 );
7493 }
7494#endif
7495 }
7496
7497 return SCIP_OKAY;
7498}
7499
7500/** adds linear constraint as row to the NLP, if not added yet */
7501static
7503 SCIP* scip, /**< SCIP data structure */
7504 SCIP_CONS* cons /**< linear constraint */
7505 )
7506{
7507 SCIP_CONSDATA* consdata;
7508
7510
7511 /* skip deactivated, redundant, or local linear constraints (the NLP does not allow for local rows at the moment) */
7512 if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsLocal(cons) )
7513 return SCIP_OKAY;
7514
7515 consdata = SCIPconsGetData(cons);
7516 assert(consdata != NULL);
7517
7518 if( consdata->nlrow == NULL )
7519 {
7520 assert(consdata->lhs <= consdata->rhs);
7521
7522 SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons),
7523 0.0, consdata->nvars, consdata->vars, consdata->vals, NULL, consdata->lhs, consdata->rhs, SCIP_EXPRCURV_LINEAR) );
7524
7525 assert(consdata->nlrow != NULL);
7526 }
7527
7528 if( !SCIPnlrowIsInNLP(consdata->nlrow) )
7529 {
7530 SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow) );
7531 }
7532
7533 return SCIP_OKAY;
7534}
7535
7536/** separates linear constraint: adds linear constraint as cut, if violated by given solution */
7537static
7539 SCIP* scip, /**< SCIP data structure */
7540 SCIP_CONS* cons, /**< linear constraint */
7541 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
7542 SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
7543 SCIP_Bool separatecards, /**< should knapsack cardinality cuts be generated? */
7544 SCIP_Bool separateall, /**< should all constraints be subject to cardinality cut generation instead of only
7545 * the ones with non-zero dual value? */
7546 int* ncuts, /**< pointer to add up the number of found cuts */
7547 SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7548 )
7549{
7550 SCIP_CONSDATA* consdata;
7551 SCIP_Bool violated;
7552 int oldncuts;
7553
7554 assert(scip != NULL);
7555 assert(conshdlrdata != NULL);
7556 assert(cons != NULL);
7557 assert(cutoff != NULL);
7558
7559 consdata = SCIPconsGetData(cons);
7560 assert(ncuts != NULL);
7561 assert(consdata != NULL);
7562
7563 oldncuts = *ncuts;
7564 *cutoff = FALSE;
7565
7566 SCIP_CALL( checkCons(scip, cons, sol, (sol != NULL), conshdlrdata->checkrelmaxabs, &violated) );
7567
7568 if( violated )
7569 {
7570 /* insert LP row as cut */
7572 (*ncuts)++;
7573 }
7574 else if( !SCIPconsIsModifiable(cons) && separatecards && consdata->nvars > 0 )
7575 {
7576 /* relax linear constraint into knapsack constraint and separate lifted cardinality cuts */
7577 if( !separateall && sol == NULL )
7578 {
7579 /* we only want to call the knapsack cardinality cut separator for rows that have a non-zero dual solution */
7580 if( consdata->row != NULL && SCIProwIsInLP(consdata->row) )
7581 {
7582 SCIP_Real dualsol;
7583
7584 dualsol = SCIProwGetDualsol(consdata->row);
7585 if( SCIPisFeasNegative(scip, dualsol) )
7586 {
7587 if( !SCIPisInfinity(scip, consdata->rhs) )
7588 {
7589 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7590 consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7591 }
7592 }
7593 else if( SCIPisFeasPositive(scip, dualsol) )
7594 {
7595 if( !SCIPisInfinity(scip, -consdata->lhs) )
7596 {
7597 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7598 consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7599 }
7600 }
7601 }
7602 }
7603 else
7604 {
7605 if( !SCIPisInfinity(scip, consdata->rhs) )
7606 {
7607 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7608 consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7609 }
7610 if( !SCIPisInfinity(scip, -consdata->lhs) )
7611 {
7612 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7613 consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7614 }
7615 }
7616 }
7617
7618 if( *ncuts > oldncuts )
7619 {
7621 }
7622
7623 return SCIP_OKAY;
7624}
7625
7626/** propagation method for linear constraints */
7627static
7629 SCIP* scip, /**< SCIP data structure */
7630 SCIP_CONS* cons, /**< linear constraint */
7631 SCIP_Bool tightenbounds, /**< should the variable's bounds be tightened? */
7632 SCIP_Bool rangedrowpropagation,/**< should ranged row propagation be performed? */
7633 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7634 SCIP_Bool sortvars, /**< should variable sorting for faster propagation be used? */
7635 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7636 int* nchgbds /**< pointer to count the total number of tightened bounds */
7637 )
7638{
7639 SCIP_CONSDATA* consdata;
7640 SCIP_Real minactivity;
7641 SCIP_Real maxactivity;
7642 SCIP_Bool isminacttight;
7643 SCIP_Bool ismaxacttight;
7644 SCIP_Bool isminsettoinfinity;
7645 SCIP_Bool ismaxsettoinfinity;
7646
7647 assert(scip != NULL);
7648 assert(cons != NULL);
7649 assert(cutoff != NULL);
7650 assert(nchgbds != NULL);
7651
7652 /*SCIPdebugMsg(scip, "propagating linear constraint <%s>\n", SCIPconsGetName(cons));*/
7653
7654 consdata = SCIPconsGetData(cons);
7655 assert(consdata != NULL);
7656
7657 if( consdata->eventdata == NULL )
7658 {
7659 SCIP_CONSHDLR* conshdlr;
7660 SCIP_CONSHDLRDATA* conshdlrdata;
7661
7662 conshdlr = SCIPconsGetHdlr(cons);
7663 assert(conshdlr != NULL);
7664
7665 conshdlrdata = SCIPconshdlrGetData(conshdlr);
7666 assert(conshdlrdata != NULL);
7667
7668 /* catch bound change events of variables */
7669 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
7670 assert(consdata->eventdata != NULL);
7671 }
7672
7673 *cutoff = FALSE;
7674
7675 /* we can only infer activity bounds of the linear constraint, if it is not modifiable */
7676 if( !SCIPconsIsModifiable(cons) )
7677 {
7678 /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
7680 {
7681 SCIP_CALL( SCIPincConsAge(scip, cons) );
7682 }
7683
7684 /* tighten the variable's bounds */
7685 if( tightenbounds )
7686 {
7687 int oldnchgbds;
7688
7689 oldnchgbds = *nchgbds;
7690
7691 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
7692
7693 if( *nchgbds > oldnchgbds )
7694 {
7696 }
7697 }
7698
7699 /* propagate ranged rows */
7700 if( rangedrowpropagation && tightenbounds && !(*cutoff) )
7701 {
7702 int nfixedvars;
7703 int naddconss;
7704 SCIPdebug( int oldnchgbds = *nchgbds; )
7705
7706 nfixedvars = 0;
7707 naddconss = 0;
7708
7709 SCIP_CALL( rangedRowPropagation(scip, cons, cutoff, &nfixedvars, nchgbds, &naddconss) );
7710
7711 if( *cutoff )
7712 {
7713 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible\n", SCIPconsGetName(cons));
7714 }
7715 else
7716 {
7717 SCIPdebug( SCIPdebugMsg(scip, "linear constraint <%s> found %d bound changes and %d fixings\n", SCIPconsGetName(cons), *nchgbds - oldnchgbds, nfixedvars); )
7718 }
7719
7720 if( nfixedvars > 0 )
7721 *nchgbds += 2*nfixedvars;
7722 } /*lint !e438*/
7723
7724 /* check constraint for infeasibility and redundancy */
7725 if( !(*cutoff) )
7726 {
7727 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
7728 &isminsettoinfinity, &ismaxsettoinfinity);
7729
7730 if( SCIPisFeasGT(scip, minactivity, consdata->rhs) )
7731 {
7732 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (rhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7733 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7734
7735 /* analyze conflict */
7737
7739 *cutoff = TRUE;
7740 }
7741 else if( SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
7742 {
7743 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (lhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7744 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7745
7746 /* analyze conflict */
7748
7750 *cutoff = TRUE;
7751 }
7752 else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
7753 {
7754 SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7755 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7756
7757 /* remove the constraint locally unless it has become empty, in which case it is removed globally */
7758 if( consdata->nvars > 0 )
7760 else
7761 SCIP_CALL( SCIPdelCons(scip, cons) );
7762 }
7763 }
7764 }
7765
7766 return SCIP_OKAY;
7767}
7768
7769
7770/*
7771 * Presolving methods
7772 */
7773
7774/** converts all variables with fixed domain into FIXED variables */
7775static
7777 SCIP* scip, /**< SCIP data structure */
7778 SCIP_CONS* cons, /**< linear constraint */
7779 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
7780 int* nfixedvars /**< pointer to count the total number of fixed variables */
7781 )
7782{
7783 SCIP_CONSDATA* consdata;
7784 SCIP_VAR* var;
7785 SCIP_VARSTATUS varstatus;
7786 SCIP_Real lb;
7787 SCIP_Real ub;
7788 SCIP_Bool fixed;
7789 SCIP_Bool infeasible;
7790 int v;
7791
7792 assert(scip != NULL);
7793 assert(cons != NULL);
7794 assert(cutoff != NULL);
7795 assert(nfixedvars != NULL);
7796
7797 consdata = SCIPconsGetData(cons);
7798 assert(consdata != NULL);
7799
7800 for( v = 0; v < consdata->nvars; ++v )
7801 {
7802 assert(consdata->vars != NULL);
7803 var = consdata->vars[v];
7804 varstatus = SCIPvarGetStatus(var);
7805
7806 if( varstatus != SCIP_VARSTATUS_FIXED )
7807 {
7808 lb = SCIPvarGetLbGlobal(var);
7809 ub = SCIPvarGetUbGlobal(var);
7810 if( SCIPisEQ(scip, lb, ub) )
7811 {
7812 SCIP_Real fixval;
7813
7814 fixval = SCIPselectSimpleValue(lb, ub, MAXDNOM);
7815 SCIPdebugMsg(scip, "converting variable <%s> with fixed bounds [%.15g,%.15g] into fixed variable fixed at %.15g\n",
7816 SCIPvarGetName(var), lb, ub, fixval);
7817 SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
7818 if( infeasible )
7819 {
7820 SCIPdebugMsg(scip, " -> infeasible fixing\n");
7821 *cutoff = TRUE;
7822 return SCIP_OKAY;
7823 }
7824 if( fixed )
7825 (*nfixedvars)++;
7826 }
7827 }
7828 }
7829
7830 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
7831
7832 if( infeasible )
7833 {
7834 SCIPdebugMsg(scip, " -> infeasible fixing\n");
7835 *cutoff = TRUE;
7836 return SCIP_OKAY;
7837 }
7838
7839 assert(consdata->removedfixings);
7840
7841 return SCIP_OKAY;
7842}
7843
7844#define MAX_CLIQUE_NONZEROS_PER_CONS 1000000
7845
7846/** extracts cliques of the constraint and adds them to SCIP
7847 *
7848 * The following clique extraction mechanism are implemeneted
7849 *
7850 * 1. collect binary variables and sort them in non increasing order, then
7851 *
7852 * a) if the constraint has a finite right hand side and the negative infinity counters for the minactivity are zero
7853 * then add the variables as a clique for which all successive pairs of coefficients fullfill the following
7854 * condition
7855 *
7856 * minactivity + vals[i] + vals[i+1] > rhs
7857 *
7858 * and also add the binary to binary implication also for non-successive variables for which the same argument
7859 * holds
7860 *
7861 * minactivity + vals[i] + vals[j] > rhs
7862 *
7863 * 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
7864 * binary to binary implications x1 = 1 => x4 = 0 and x2 = 1 => x4 = 0
7865 *
7866 * b) if the constraint has a finite left hand side and the positive infinity counters for the maxactivity are zero
7867 * then add the variables as a clique for which all successive pairs of coefficients fullfill the follwoing
7868 * condition
7869 *
7870 * maxactivity + vals[i] + vals[i-1] < lhs
7871 *
7872 * and also add the binary to binary implication also for non-successive variables for which the same argument
7873 * holds
7874 *
7875 * maxactivity + vals[i] + vals[j] < lhs
7876 *
7877 * e.g. you could multiply the above example by -1
7878 *
7879 * c) the constraint has a finite right hand side and a finite minactivity then add the variables as a negated
7880 * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7881 * condition
7882 *
7883 * minactivity - vals[i] - vals[i-1] > rhs
7884 *
7885 * and also add the binary to binary implication also for non-successive variables for which the
7886 * same argument holds
7887 *
7888 * minactivity - vals[i] - vals[j] > rhs
7889 *
7890 * e.g. -4 x1 -3 x2 - 2 x3 + 2 x4 <= -4 would lead to the (negated) clique (~x1, ~x2) and the binary to binary
7891 * implication x1 = 0 => x3 = 1
7892 *
7893 * d) the constraint has a finite left hand side and a finite maxactivity then add the variables as a negated
7894 * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7895 * condition
7896 *
7897 * maxactivity - vals[i] - vals[i+1] < lhs
7898 *
7899 * and also add the binary to binary implication also for non-successive variables for which the same argument
7900 * holds
7901 *
7902 * maxactivity - vals[i] - vals[j] < lhs
7903 *
7904 * e.g. you could multiply the above example by -1
7905 *
7906 * 2. if the linear constraint represents a set-packing or set-partitioning constraint, the whole constraint is added
7907 * as clique, (this part is done at the end of the method)
7908 *
7909 */
7910static
7912 SCIP* scip, /**< SCIP data structure */
7913 SCIP_CONS* cons, /**< linear constraint */
7914 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7915 SCIP_Bool sortvars, /**< should variables be used in sorted order? */
7916 int* nfixedvars, /**< pointer to count number of fixed variables */
7917 int* nchgbds, /**< pointer to count the total number of tightened bounds */
7918 SCIP_Bool* cutoff /**< pointer to store TRUE, if a cutoff was found */
7919 )
7920{
7921 SCIP_VAR** vars;
7922 SCIP_Real* vals;
7923 SCIP_CONSDATA* consdata;
7924 SCIP_Bool lhsclique;
7925 SCIP_Bool rhsclique;
7926 SCIP_Bool finitelhs;
7927 SCIP_Bool finiterhs;
7928 SCIP_Bool finiteminact;
7929 SCIP_Bool finitemaxact;
7930 SCIP_Bool finitenegminact;
7931 SCIP_Bool finitenegmaxact;
7932 SCIP_Bool finiteposminact;
7933 SCIP_Bool finiteposmaxact;
7934 SCIP_Bool infeasible;
7935 SCIP_Bool stopped;
7936 int cliquenonzerosadded;
7937 int v;
7938 int i;
7939 int nposcoefs;
7940 int nnegcoefs;
7941 int nvars;
7942
7943 assert(scip != NULL);
7944 assert(cons != NULL);
7945 assert(nfixedvars != NULL);
7946 assert(nchgbds != NULL);
7947 assert(cutoff != NULL);
7948 assert(!SCIPconsIsDeleted(cons));
7949
7950 consdata = SCIPconsGetData(cons);
7951 assert(consdata != NULL);
7952
7953 if( consdata->nvars < 2 )
7954 return SCIP_OKAY;
7955
7956 /* add implications if possible
7957 *
7958 * for now we only add binary to non-binary implications, and this is only done for the binary variable with the
7959 * maximal absolute contribution and also only if this variable would force all other variables to their bound
7960 * corresponding to the global minimal activity of the constraint
7961 */
7962 if( !consdata->implsadded )
7963 {
7964 /* sort variables by variable type */
7965 SCIP_CALL( consdataSort(scip, consdata) );
7966
7967 /* @todo we might extract implications/cliques if SCIPvarIsBinary() variables exist and we have integer variables
7968 * up front, might change sorting correspondingly
7969 */
7970 /* fast abort if no binaries seem to exist
7971 * "seem to", because there are rare situations in which variables may actually not be sorted by type, even though consdataSort has been called
7972 * this situation can occur if, e.g., the type of consdata->vars[1] has been changed to binary, but the corresponding variable event has
7973 * not been executed yet, because it is the eventExecLinear() which marks the variables array as unsorted (set consdata->indexsorted to FALSE),
7974 * which is the requirement for consdataSort() to actually resort the variables
7975 * we assume that in this situation the below code may be executed in a future presolve round, after the variable events have been executed
7976 */
7977 if( !SCIPvarIsBinary(consdata->vars[0]) )
7978 return SCIP_OKAY;
7979
7980 nvars = consdata->nvars;
7981 vars = consdata->vars;
7982 vals = consdata->vals;
7983
7984 /* recompute activities if needed */
7985 if( !consdata->validactivities )
7986 consdataCalcActivities(scip, consdata);
7987 assert(consdata->validactivities);
7988
7989 finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
7990 finiterhs = !SCIPisInfinity(scip, consdata->rhs);
7991 finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
7992 finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
7993 finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
7994 finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
7995 finiteminact = (finitenegminact && finiteposminact);
7996 finitemaxact = (finitenegmaxact && finiteposmaxact);
7997
7998 if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
7999 {
8000 SCIP_Real maxabscontrib = -1.0;
8001 SCIP_Bool posval = FALSE;
8002 SCIP_Bool allbinary = TRUE;
8003 int oldnchgbds = *nchgbds;
8004 int nbdchgs = 0;
8005 int nimpls = 0;
8006 int position = -1;
8007
8008 /* we need a valid minimal/maximal activity to add cliques */
8009 if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8010 {
8012 assert(consdata->validglbminact);
8013 }
8014
8015 if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8016 {
8018 assert(consdata->validglbmaxact);
8019 }
8020 assert(consdata->validglbminact || consdata->validglbmaxact);
8021
8022 /* @todo extend this to local/constraint probing */
8023
8024 /* determine maximal contribution to the activity */
8025 for( v = nvars - 1; v >= 0; --v )
8026 {
8027 if( SCIPvarIsBinary(vars[v]) )
8028 {
8029 if( vals[v] > 0 )
8030 {
8031 SCIP_Real value = vals[v] * SCIPvarGetUbGlobal(vars[v]);
8032
8033 if( value > maxabscontrib )
8034 {
8035 maxabscontrib = value;
8036 position = v;
8037 posval = TRUE;
8038 }
8039 }
8040 else
8041 {
8042 SCIP_Real value = vals[v] * SCIPvarGetLbGlobal(vars[v]);
8043
8044 value = REALABS(value);
8045
8046 if( value > maxabscontrib )
8047 {
8048 maxabscontrib = value;
8049 position = v;
8050 posval = FALSE;
8051 }
8052 }
8053 }
8054 else
8055 allbinary = FALSE;
8056 }
8057 assert(0 <= position && position < nvars);
8058
8059 if( !SCIPisEQ(scip, maxabscontrib, 1.0) && !allbinary )
8060 {
8061 /* if the right hand side and the minimal activity are finite and changing the variable with the biggest
8062 * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8063 * implications
8064 */
8065 if( finiterhs && finiteminact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbminactivity), consdata->rhs - maxabscontrib) )
8066 {
8067 for( v = nvars - 1; v >= 0; --v )
8068 {
8069 /* binary to binary implications will be collected when extrating cliques */
8070 if( !SCIPvarIsBinary(vars[v]) )
8071 {
8072 if( v != position )
8073 {
8074 if( vals[v] > 0 )
8075 {
8076 /* add implications */
8077 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8078 ++nimpls;
8079 *nchgbds += nbdchgs;
8080 }
8081 else
8082 {
8083 /* add implications */
8084 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8085 ++nimpls;
8086 *nchgbds += nbdchgs;
8087 }
8088
8089 if( infeasible )
8090 {
8091 *cutoff = TRUE;
8092 break;
8093 }
8094 }
8095 }
8096 /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8098 break;
8099 }
8100 }
8101
8102 /* if the left hand side and the maximal activity are finite and changing the variable with the biggest
8103 * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8104 * implications
8105 */
8106 if( finitelhs && finitemaxact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbmaxactivity), consdata->lhs - maxabscontrib) )
8107 {
8108 for( v = nvars - 1; v >= 0; --v )
8109 {
8110 /* binary to binary implications will be collected when extrating cliques */
8111 if( !SCIPvarIsBinary(vars[v]) )
8112 {
8113 if( v != position )
8114 {
8115 if( vals[v] > 0 )
8116 {
8117 /* add implications */
8118 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8119 ++nimpls;
8120 *nchgbds += nbdchgs;
8121 }
8122 else
8123 {
8124 /* add implications */
8125 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8126 ++nimpls;
8127 *nchgbds += nbdchgs;
8128 }
8129
8130 if( infeasible )
8131 {
8132 *cutoff = TRUE;
8133 break;
8134 }
8135 }
8136 }
8137 /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8138 else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8139 break;
8140 }
8141 }
8142
8143 /* did we find some implications */
8144 if( nimpls > 0 )
8145 {
8146 SCIPdebugMsg(scip, "extracted %d implications from constraint %s which led to %d bound changes, %scutoff detetcted\n", nimpls, SCIPconsGetName(cons), *nchgbds - oldnchgbds, *cutoff ? "" : "no ");
8147
8148 if( *cutoff )
8149 return SCIP_OKAY;
8150
8151 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8152 if( *nchgbds - oldnchgbds > 0 )
8153 {
8154 /* check for fixed variables */
8155 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8156 if( *cutoff )
8157 return SCIP_OKAY;
8158
8159 /* tighten variable's bounds */
8160 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8161 if( *cutoff )
8162 return SCIP_OKAY;
8163
8164 /* check for fixed variables */
8165 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8166 if( *cutoff )
8167 return SCIP_OKAY;
8168 }
8169 }
8170 }
8171 }
8172
8173 consdata->implsadded = TRUE;
8174 }
8175
8176 /* check if we already added the cliques of this constraint */
8177 if( consdata->cliquesadded )
8178 return SCIP_OKAY;
8179
8180 consdata->cliquesadded = TRUE;
8181 cliquenonzerosadded = 0;
8182 stopped = FALSE;
8183
8184 /* sort variables by variable type */
8185 SCIP_CALL( consdataSort(scip, consdata) );
8186
8187 nvars = consdata->nvars;
8188 vars = consdata->vars;
8189 vals = consdata->vals;
8190
8191 /**@todo extract more cliques, implications and variable bounds from linear constraints */
8192
8193 /* recompute activities if needed */
8194 if( !consdata->validactivities )
8195 consdataCalcActivities(scip, consdata);
8196 assert(consdata->validactivities);
8197
8198 finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8199 finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8200 finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8201 finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8202 finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8203 finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8204 finiteminact = (finitenegminact && finiteposminact);
8205 finitemaxact = (finitenegmaxact && finiteposmaxact);
8206
8207 /* 1. we wheck whether some variables do not fit together into this constraint and add the corresponding clique
8208 * information
8209 */
8210 if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
8211 {
8212 SCIP_VAR** binvars;
8213 SCIP_Real* binvarvals;
8214 int nposbinvars = 0;
8215 int nnegbinvars = 0;
8216 int allonebinary = 0;
8217
8219 SCIP_CALL( SCIPallocBufferArray(scip, &binvarvals, nvars) );
8220
8221 /* collect binary variables */
8222 for( i = 0; i < nvars; ++i )
8223 {
8224 if( SCIPvarIsBinary(vars[i]) )
8225 {
8226 assert(!SCIPisZero(scip, vals[i]));
8227
8228 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8229 ++allonebinary;
8230
8231 binvars[nposbinvars + nnegbinvars] = vars[i];
8232 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8233
8234 if( SCIPisPositive(scip, vals[i]) )
8235 ++nposbinvars;
8236 else
8237 ++nnegbinvars;
8238
8239 assert(nposbinvars + nnegbinvars <= nvars);
8240 }
8241 /* stop searching for binary variables, because the constraint data is sorted */
8242 else if( !SCIPvarIsIntegral(vars[i]) )
8243 break;
8244 }
8245 assert(nposbinvars + nnegbinvars <= nvars);
8246
8247 /* setppc constraints will be handled later; we need at least two binary variables with same sign to extract
8248 * cliques
8249 */
8250 if( allonebinary < nvars && (nposbinvars >= 2 || nnegbinvars >= 2) )
8251 {
8252 SCIP_Real threshold;
8253 int oldnchgbds = *nchgbds;
8254 int nbdchgs;
8255 int jstart;
8256 int j;
8257
8258 /* we need a valid minimal/maximal activity to add cliques */
8259 if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8260 {
8262 assert(consdata->validglbminact);
8263 }
8264
8265 if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8266 {
8268 assert(consdata->validglbmaxact);
8269 }
8270 assert(consdata->validglbminact || consdata->validglbmaxact);
8271
8272 /* sort coefficients non-increasing to be faster in the clique search */
8273 SCIPsortDownRealPtr(binvarvals, (void**) binvars, nposbinvars + nnegbinvars);
8274
8275 /* case a) */
8276 if( finiterhs && finitenegminact && nposbinvars >= 2 )
8277 {
8278 /* compute value that needs to be exceeded */
8279 threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
8280
8281 j = 1;
8282#ifdef SCIP_DISABLED_CODE /* assertion should only hold when constraints were fully propagated and boundstightened */
8283 /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8284 assert(SCIPisFeasLE(scip, binvarvals[0], threshold));
8285#endif
8286 /* check if at least two variables are in a clique */
8287 if( SCIPisFeasGT(scip, binvarvals[0] + binvarvals[j], threshold) )
8288 {
8289 ++j;
8290 /* check for extending the clique */
8291 while( j < nposbinvars )
8292 {
8293 if( !SCIPisFeasGT(scip, binvarvals[j-1] + binvarvals[j], threshold) )
8294 break;
8295 ++j;
8296 }
8297 assert(j >= 2);
8298
8299 /* add clique with at least two variables */
8300 SCIP_CALL( SCIPaddClique(scip, binvars, NULL, j, FALSE, &infeasible, &nbdchgs) );
8301
8302 if( infeasible )
8303 *cutoff = TRUE;
8304
8305 *nchgbds += nbdchgs;
8306
8307 cliquenonzerosadded += j;
8308 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8309 stopped = TRUE;
8310
8311 /* exchange the last variable in the clique if possible and add all new ones */
8312 if( !stopped && !(*cutoff) && j < nposbinvars )
8313 {
8314 SCIP_VAR** clqvars;
8315 int lastfit = j - 2;
8316 assert(lastfit >= 0);
8317
8318 /* copy all 'main'-clique variables */
8319 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
8320
8321 /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8322 while( lastfit >= 0 && j < nposbinvars )
8323 {
8324 /* check if two variables are in a clique */
8325 if( SCIPisFeasGT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8326 {
8327 clqvars[lastfit + 1] = binvars[j];
8328
8329 /* add clique with at least two variables */
8330 SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8331
8332 if( infeasible )
8333 {
8334 *cutoff = TRUE;
8335 break;
8336 }
8337
8338 *nchgbds += nbdchgs;
8339
8340 cliquenonzerosadded += (lastfit + 2);
8341 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8342 {
8343 stopped = TRUE;
8344 break;
8345 }
8346
8347 ++j;
8348 }
8349 else
8350 --lastfit;
8351 }
8352
8353 SCIPfreeBufferArray(scip, &clqvars);
8354 }
8355 }
8356 }
8357
8358 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8359 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8360 {
8361 /* check for fixed variables */
8362 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8363
8364 if( !*cutoff )
8365 {
8366 /* tighten variable's bounds */
8367 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8368
8369 if( !*cutoff )
8370 {
8371 /* check for fixed variables */
8372 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8373
8374 if( !*cutoff )
8375 {
8376 /* sort variables by variable type */
8377 SCIP_CALL( consdataSort(scip, consdata) );
8378
8379 /* recompute activities if needed */
8380 if( !consdata->validactivities )
8381 consdataCalcActivities(scip, consdata);
8382 assert(consdata->validactivities);
8383
8384 nvars = consdata->nvars;
8385 vars = consdata->vars;
8386 vals = consdata->vals;
8387 nposbinvars = 0;
8388 nnegbinvars = 0;
8389 allonebinary = 0;
8390
8391 /* update binary variables */
8392 for( i = 0; i < nvars; ++i )
8393 {
8394 if( SCIPvarIsBinary(vars[i]) )
8395 {
8396 assert(!SCIPisZero(scip, vals[i]));
8397
8398 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8399 ++allonebinary;
8400
8401 binvars[nposbinvars + nnegbinvars] = vars[i];
8402 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8403
8404 if( SCIPisPositive(scip, vals[i]) )
8405 ++nposbinvars;
8406 else
8407 ++nnegbinvars;
8408
8409 assert(nposbinvars + nnegbinvars <= nvars);
8410 }
8411 /* stop searching for binary variables, because the constraint data is sorted */
8412 else if( !SCIPvarIsIntegral(vars[i]) )
8413 break;
8414 }
8415 assert(nposbinvars + nnegbinvars <= nvars);
8416 }
8417 }
8418 }
8419
8420 oldnchgbds = *nchgbds;
8421 }
8422
8423 /* case b) */
8424 if( !stopped && !(*cutoff) && finitelhs && finiteposmaxact && nnegbinvars >= 2 )
8425 {
8426 /* compute value that needs to be deceeded */
8427 threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
8428
8429 i = nposbinvars + nnegbinvars - 1;
8430 j = i - 1;
8431#ifdef SCIP_DISABLED_CODE
8432 /* assertion should only hold when constraints were fully propagated and boundstightened */
8433 /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8434 assert(SCIPisFeasGE(scip, binvarvals[i], threshold));
8435#endif
8436 /* check if two variables are in a clique */
8437 if( SCIPisFeasLT(scip, binvarvals[i] + binvarvals[j], threshold) )
8438 {
8439 --j;
8440 /* check for extending the clique */
8441 while( j >= nposbinvars )
8442 {
8443 if( !SCIPisFeasLT(scip, binvarvals[j+1] + binvarvals[j], threshold) )
8444 break;
8445 --j;
8446 }
8447 jstart = j;
8448
8449 assert(i - j >= 2);
8450 /* add clique with at least two variables */
8451 SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), NULL, i - j, FALSE, &infeasible, &nbdchgs) );
8452
8453 if( infeasible )
8454 *cutoff = TRUE;
8455
8456 *nchgbds += nbdchgs;
8457
8458 cliquenonzerosadded += (i - j);
8459 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8460 stopped = TRUE;
8461
8462 /* exchange the last variable in the clique if possible and add all new ones */
8463 if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8464 {
8465 SCIP_VAR** clqvars;
8466 int lastfit = jstart + 1;
8467 assert(lastfit < i);
8468
8469 /* copy all 'main'-clique variables */
8470 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8471 ++lastfit;
8472
8473 /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8474 while( lastfit <= i && j >= nposbinvars )
8475 {
8476 /* check if two variables are in a clique */
8477 if( SCIPisFeasLT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8478 {
8479 assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8480 clqvars[lastfit - jstart - 2] = binvars[j];
8481
8482 assert(i - lastfit + 2 >= 2);
8483 /* add clique with at least two variables */
8484 SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), NULL, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8485
8486 if( infeasible )
8487 {
8488 *cutoff = TRUE;
8489 break;
8490 }
8491
8492 *nchgbds += nbdchgs;
8493
8494 cliquenonzerosadded += (i - lastfit + 2);
8495 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8496 {
8497 stopped = TRUE;
8498 break;
8499 }
8500
8501 --j;
8502 }
8503 else
8504 ++lastfit;
8505 }
8506
8507 SCIPfreeBufferArray(scip, &clqvars);
8508 }
8509 }
8510 }
8511
8512 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8513 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8514 {
8515 /* check for fixed variables */
8516 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8517
8518 if( !*cutoff )
8519 {
8520 /* tighten variable's bounds */
8521 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8522
8523 if( !*cutoff )
8524 {
8525 /* check for fixed variables */
8526 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8527
8528 if( !*cutoff )
8529 {
8530 /* sort variables by variable type */
8531 SCIP_CALL( consdataSort(scip, consdata) );
8532
8533 /* recompute activities if needed */
8534 if( !consdata->validactivities )
8535 consdataCalcActivities(scip, consdata);
8536 assert(consdata->validactivities);
8537
8538 nvars = consdata->nvars;
8539 vars = consdata->vars;
8540 vals = consdata->vals;
8541 nposbinvars = 0;
8542 nnegbinvars = 0;
8543 allonebinary = 0;
8544
8545 /* update binary variables */
8546 for( i = 0; i < nvars; ++i )
8547 {
8548 if( SCIPvarIsBinary(vars[i]) )
8549 {
8550 assert(!SCIPisZero(scip, vals[i]));
8551
8552 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8553 ++allonebinary;
8554
8555 binvars[nposbinvars + nnegbinvars] = vars[i];
8556 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8557
8558 if( SCIPisPositive(scip, vals[i]) )
8559 ++nposbinvars;
8560 else
8561 ++nnegbinvars;
8562
8563 assert(nposbinvars + nnegbinvars <= nvars);
8564 }
8565 /* stop searching for binary variables, because the constraint data is sorted */
8566 else if( !SCIPvarIsIntegral(vars[i]) )
8567 break;
8568 }
8569 assert(nposbinvars + nnegbinvars <= nvars);
8570 }
8571 }
8572 }
8573
8574 oldnchgbds = *nchgbds;
8575 }
8576
8577 /* case c) */
8578 if( !(*cutoff) && finiterhs && finiteminact && nnegbinvars >= 2 )
8579 {
8580 SCIP_Bool* values;
8581
8582 /* initialize clique values array for adding a negated clique */
8583 SCIP_CALL( SCIPallocBufferArray(scip, &values, nnegbinvars) );
8584 BMSclearMemoryArray(values, nnegbinvars);
8585
8586 /* compute value that needs to be exceeded */
8587 threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
8588
8589 i = nposbinvars + nnegbinvars - 1;
8590 j = i - 1;
8591
8592#ifdef SCIP_DISABLED_CODE
8593 /* assertion should only hold when constraints were fully propagated and boundstightened */
8594 /* check if the variable should not have already been fixed to one */
8595 assert(!SCIPisFeasGT(scip, binvarvals[i], threshold));
8596#endif
8597
8598 if( SCIPisFeasGT(scip, -binvarvals[i] - binvarvals[j], threshold) )
8599 {
8600 --j;
8601 /* check for extending the clique */
8602 while( j >= nposbinvars )
8603 {
8604 if( !SCIPisFeasGT(scip, -binvarvals[j+1] - binvarvals[j], threshold) )
8605 break;
8606 --j;
8607 }
8608 jstart = j;
8609
8610 assert(i - j >= 2);
8611 /* add negated clique with at least two variables */
8612 SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), values, i - j, FALSE, &infeasible, &nbdchgs) );
8613
8614 if( infeasible )
8615 *cutoff = TRUE;
8616
8617 *nchgbds += nbdchgs;
8618
8619 cliquenonzerosadded += (i - j);
8620 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8621 stopped = TRUE;
8622
8623 /* exchange the last variable in the clique if possible and add all new ones */
8624 if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8625 {
8626 SCIP_VAR** clqvars;
8627 int lastfit = j + 1;
8628 assert(lastfit < i);
8629
8630 /* copy all 'main'-clique variables */
8631 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8632 ++lastfit;
8633
8634 /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8635 while( lastfit <= i && j >= nposbinvars )
8636 {
8637 /* check if two variables are in a negated clique */
8638 if( SCIPisFeasGT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8639 {
8640 assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8641 clqvars[lastfit - jstart - 2] = binvars[j];
8642
8643 assert(i - lastfit + 2 >= 2);
8644 /* add clique with at least two variables */
8645 SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), values, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8646
8647 if( infeasible )
8648 {
8649 *cutoff = TRUE;
8650 break;
8651 }
8652
8653 *nchgbds += nbdchgs;
8654
8655 cliquenonzerosadded += (i - lastfit + 2);
8656 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8657 {
8658 stopped = TRUE;
8659 break;
8660 }
8661
8662 --j;
8663 }
8664 else
8665 ++lastfit;
8666 }
8667
8668 SCIPfreeBufferArray(scip, &clqvars);
8669 }
8670 }
8671
8672 SCIPfreeBufferArray(scip, &values);
8673 }
8674
8675 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8676 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8677 {
8678 /* check for fixed variables */
8679 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8680
8681 if( !*cutoff )
8682 {
8683 /* tighten variable's bounds */
8684 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8685
8686 if( !*cutoff )
8687 {
8688 /* check for fixed variables */
8689 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8690
8691 if( !*cutoff )
8692 {
8693 /* sort variables by variable type */
8694 SCIP_CALL( consdataSort(scip, consdata) );
8695
8696 /* recompute activities if needed */
8697 if( !consdata->validactivities )
8698 consdataCalcActivities(scip, consdata);
8699 assert(consdata->validactivities);
8700
8701 nvars = consdata->nvars;
8702 vars = consdata->vars;
8703 vals = consdata->vals;
8704 nposbinvars = 0;
8705 nnegbinvars = 0;
8706 allonebinary = 0;
8707
8708 /* update binary variables */
8709 for( i = 0; i < nvars; ++i )
8710 {
8711 if( SCIPvarIsBinary(vars[i]) )
8712 {
8713 assert(!SCIPisZero(scip, vals[i]));
8714
8715 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8716 ++allonebinary;
8717
8718 binvars[nposbinvars + nnegbinvars] = vars[i];
8719 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8720
8721 if( SCIPisPositive(scip, vals[i]) )
8722 ++nposbinvars;
8723 else
8724 ++nnegbinvars;
8725
8726 assert(nposbinvars + nnegbinvars <= nvars);
8727 }
8728 /* stop searching for binary variables, because the constraint data is sorted */
8729 else if( !SCIPvarIsIntegral(vars[i]) )
8730 break;
8731 }
8732 assert(nposbinvars + nnegbinvars <= nvars);
8733 }
8734 }
8735 }
8736 }
8737
8738 /* case d) */
8739 if( !stopped && !(*cutoff) && finitelhs && finitemaxact && nposbinvars >= 2 )
8740 {
8741 SCIP_Bool* values;
8742
8743 /* initialize clique values array for adding a negated clique */
8744 SCIP_CALL( SCIPallocBufferArray(scip, &values, nposbinvars) );
8745 BMSclearMemoryArray(values, nposbinvars);
8746
8747 /* compute value that needs to be exceeded */
8748 threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
8749
8750 j = 1;
8751
8752#ifdef SCIP_DISABLED_CODE
8753 /* assertion should only hold when constraints were fully propagated and boundstightened */
8754 /* check if the variable should not have already been fixed to one */
8755 assert(!SCIPisFeasLT(scip, -binvarvals[0], threshold));
8756#endif
8757
8758 if( SCIPisFeasLT(scip, -binvarvals[0] - binvarvals[j], threshold) )
8759 {
8760 ++j;
8761 /* check for extending the clique */
8762 while( j < nposbinvars )
8763 {
8764 if( !SCIPisFeasLT(scip, -binvarvals[j-1] - binvarvals[j], threshold) )
8765 break;
8766 ++j;
8767 }
8768 assert(j >= 2);
8769
8770 /* add negated clique with at least two variables */
8771 SCIP_CALL( SCIPaddClique(scip, binvars, values, j, FALSE, &infeasible, &nbdchgs) );
8772
8773 if( infeasible )
8774 *cutoff = TRUE;
8775
8776 *nchgbds += nbdchgs;
8777
8778 cliquenonzerosadded += j;
8779 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8780 stopped = TRUE;
8781
8782 /* exchange the last variable in the clique if possible and add all new ones */
8783 if( !stopped && !(*cutoff) && j < nposbinvars )
8784 {
8785 SCIP_VAR** clqvars;
8786 int lastfit = j - 2;
8787 assert(lastfit >= 0);
8788
8789 /* copy all 'main'-clique variables */
8790 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
8791
8792 /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8793 while( lastfit >= 0 && j < nposbinvars )
8794 {
8795 /* check if two variables are in a negated clique */
8796 if( SCIPisFeasLT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8797 {
8798 clqvars[lastfit + 1] = binvars[j];
8799
8800 /* add clique with at least two variables */
8801 SCIP_CALL( SCIPaddClique(scip, clqvars, values, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8802
8803 if( infeasible )
8804 {
8805 *cutoff = TRUE;
8806 break;
8807 }
8808
8809 *nchgbds += nbdchgs;
8810
8811 cliquenonzerosadded += lastfit + 2;
8812 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8813 break;
8814
8815 ++j;
8816 }
8817 else
8818 --lastfit;
8819 }
8820
8821 SCIPfreeBufferArray(scip, &clqvars);
8822 }
8823 }
8824
8825 SCIPfreeBufferArray(scip, &values);
8826 }
8827 }
8828
8829 SCIPfreeBufferArray(scip, &binvarvals);
8830 SCIPfreeBufferArray(scip, &binvars);
8831
8832 if( *cutoff )
8833 return SCIP_OKAY;
8834 }
8835
8836 /* 2. we only check if the constraint is a set packing / partitioning constraint */
8837
8838 /* check if all variables are binary, if the coefficients are +1 or -1, and if the right hand side is equal
8839 * to 1 - number of negative coefficients, or if the left hand side is equal to number of positive coefficients - 1
8840 */
8841 nposcoefs = 0;
8842 nnegcoefs = 0;
8843 for( i = 0; i < nvars; ++i )
8844 {
8845 if( !SCIPvarIsBinary(vars[i]) )
8846 return SCIP_OKAY;
8847 else if( SCIPisEQ(scip, vals[i], +1.0) )
8848 nposcoefs++;
8849 else if( SCIPisEQ(scip, vals[i], -1.0) )
8850 nnegcoefs++;
8851 else
8852 return SCIP_OKAY;
8853 }
8854
8855 lhsclique = SCIPisEQ(scip, consdata->lhs, (SCIP_Real)nposcoefs - 1.0);
8856 rhsclique = SCIPisEQ(scip, consdata->rhs, 1.0 - (SCIP_Real)nnegcoefs);
8857
8858 if( lhsclique || rhsclique )
8859 {
8860 SCIP_Bool* values;
8861 int nbdchgs;
8862
8863 SCIPdebugMsg(scip, "linear constraint <%s>: adding clique with %d vars (%d pos, %d neg)\n",
8864 SCIPconsGetName(cons), nvars, nposcoefs, nnegcoefs);
8866
8867 for( i = 0; i < nvars; ++i )
8868 values[i] = (rhsclique == (vals[i] > 0.0));
8869
8870 SCIP_CALL( SCIPaddClique(scip, vars, values, nvars, SCIPisEQ(scip, consdata->lhs, consdata->rhs), &infeasible, &nbdchgs) );
8871
8872 if( infeasible )
8873 *cutoff = TRUE;
8874
8875 *nchgbds += nbdchgs;
8876 SCIPfreeBufferArray(scip, &values);
8877 }
8878
8879 return SCIP_OKAY;
8880}
8881
8882/** tightens left and right hand side of constraint due to integrality */
8883static
8885 SCIP* scip, /**< SCIP data structure */
8886 SCIP_CONS* cons, /**< linear constraint */
8887 int* nchgsides, /**< pointer to count number of side changes */
8888 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
8889 )
8890{
8891 SCIP_CONSDATA* consdata;
8892 SCIP_Real newlhs;
8893 SCIP_Real newrhs;
8894 SCIP_Bool chglhs;
8895 SCIP_Bool chgrhs;
8896 SCIP_Bool integral;
8897 int i;
8898
8899 assert(scip != NULL);
8900 assert(cons != NULL);
8901 assert(nchgsides != NULL);
8902 assert(infeasible != NULL);
8903
8904 consdata = SCIPconsGetData(cons);
8905 assert(consdata != NULL);
8906
8907 *infeasible = FALSE;
8908
8909 chglhs = FALSE;
8910 chgrhs = FALSE;
8911 newlhs = -SCIPinfinity(scip);
8912 newrhs = SCIPinfinity(scip);
8913
8914 if( !SCIPisIntegral(scip, consdata->lhs) || !SCIPisIntegral(scip, consdata->rhs) )
8915 {
8916 integral = TRUE;
8917 for( i = 0; i < consdata->nvars && integral; ++i )
8918 integral = SCIPvarIsIntegral(consdata->vars[i]) && SCIPisIntegral(scip, consdata->vals[i]);
8919 if( integral )
8920 {
8921 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisIntegral(scip, consdata->lhs) )
8922 {
8923 newlhs = SCIPfeasCeil(scip, consdata->lhs);
8924 chglhs = TRUE;
8925 }
8926 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisIntegral(scip, consdata->rhs) )
8927 {
8928 newrhs = SCIPfeasFloor(scip, consdata->rhs);
8929 chgrhs = TRUE;
8930 }
8931
8932 /* check whether rounding would lead to an unsatisfiable constraint */
8933 if( SCIPisGT(scip, newlhs, newrhs) )
8934 {
8935 SCIPdebugMsg(scip, "rounding sides=[%.15g,%.15g] of linear constraint <%s> with integral coefficients and variables only "
8936 "is infeasible\n", consdata->lhs, consdata->rhs, SCIPconsGetName(cons));
8937
8938 *infeasible = TRUE;
8939 return SCIP_OKAY;
8940 }
8941
8942 SCIPdebugMsg(scip, "linear constraint <%s>: make sides integral: sides=[%.15g,%.15g]\n",
8943 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
8944
8945 if( chglhs )
8946 {
8947 assert(!SCIPisInfinity(scip, -newlhs));
8948
8949 SCIP_CALL( chgLhs(scip, cons, newlhs) );
8950 if( !consdata->upgraded )
8951 (*nchgsides)++;
8952 }
8953 if( chgrhs )
8954 {
8955 assert(!SCIPisInfinity(scip, newrhs));
8956
8957 SCIP_CALL( chgRhs(scip, cons, newrhs) );
8958 if( !consdata->upgraded )
8959 (*nchgsides)++;
8960 }
8961 SCIPdebugMsg(scip, "linear constraint <%s>: new integral sides: sides=[%.15g,%.15g]\n",
8962 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
8963 }
8964 }
8965
8966 return SCIP_OKAY;
8967}
8968
8969/** tightens coefficients of binary, integer, and implied integral variables due to activity bounds in presolving:
8970 * given an inequality lhs <= a*x + ai*xi <= rhs, with a non-continuous variable li <= xi <= ui
8971 * let minact := min{a*x + ai*xi}, maxact := max{a*x + ai*xi}
8972 * (i) ai >= 0:
8973 * if minact + ai >= lhs and maxact - ai <= rhs: (**)
8974 * - a deviation from the lower/upper 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' := max(lhs - minact, maxact - rhs, 0)
8979 * lhs' := lhs - (ai - ai')*li
8980 * rhs' := rhs - (ai - ai')*ui
8981 * (ii) ai < 0:
8982 * if minact - ai >= lhs and maxact + ai <= rhs: (***)
8983 * - a deviation from the upper/lower bound of xi would make the left/right hand side redundant
8984 * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
8985 * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
8986 * - change coefficients:
8987 * ai' := min(rhs - maxact, minact - lhs, 0)
8988 * lhs' := lhs - (ai - ai')*ui
8989 * rhs' := rhs - (ai - ai')*li
8990 *
8991 * We further try to remove variables from the constraint;
8992 * Variables which fulfill conditions (**) or (***) are called relevant variables.
8993 * A deviation of only one from their bound makes the lhs/rhs feasible (i.e., redundant), even if all other
8994 * variables are set to their "worst" bound. If all variables which are not relevant cannot make the lhs/rhs
8995 * redundant, even if they are set to their "best" bound, they can be removed from the constraint. E.g., for binary
8996 * 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
8997 * inequality, whereas the x_i do not contribute to feasibility and can be removed.
8998 *
8999 * @todo use also some tightening procedures for (knapsack) constraints with non-integer coefficients, see
9000 * cons_knapsack.c the following methods detectRedundantVars() and tightenWeights()
9001 */
9002static
9004 SCIP* scip, /**< SCIP data structure */
9005 SCIP_CONS* cons, /**< linear constraint */
9006 int* nchgcoefs, /**< pointer to count total number of changed coefficients */
9007 int* nchgsides /**< pointer to count number of side changes */
9008 )
9009{
9010 SCIP_CONSDATA* consdata;
9011 SCIP_VAR* var;
9012 SCIP_Bool* isvarrelevant;
9013 SCIP_Real minactivity; /* minimal value w.r.t. the variable's local bounds for the constraint's
9014 * activity, ignoring the coefficients contributing with infinite value */
9015 SCIP_Real maxactivity; /* maximal value w.r.t. the variable's local bounds for the constraint's
9016 * activity, ignoring the coefficients contributing with infinite value */
9017 SCIP_Bool isminacttight; /* are all contributions to the minactivity non-huge or non-contradicting? */
9018 SCIP_Bool ismaxacttight; /* are all contributions to the maxactivity non-huge or non-contradicting? */
9019 SCIP_Bool isminsettoinfinity;
9020 SCIP_Bool ismaxsettoinfinity;
9021 SCIP_Real minleftactivity; /* minimal activity without relevant variables */
9022 SCIP_Real maxleftactivity; /* maximal activity without relevant variables */
9023 SCIP_Real aggrlhs; /* lhs without minimal activity of relevant variables */
9024 SCIP_Real aggrrhs; /* rhs without maximal activity of relevant variables */
9025 SCIP_Real lval; /* candidate for new value arising from considering the left hand side */
9026 SCIP_Real rval; /* candidate for new value arising from considering the left hand side */
9027 SCIP_Real val;
9028 SCIP_Real newval;
9029 SCIP_Real newlhs;
9030 SCIP_Real newrhs;
9031 SCIP_Real lb;
9032 SCIP_Real ub;
9033 int i;
9034
9035 assert(scip != NULL);
9036 assert(cons != NULL);
9037 assert(nchgcoefs != NULL);
9038 assert(nchgsides != NULL);
9039
9040 consdata = SCIPconsGetData(cons);
9041 assert(consdata != NULL);
9042
9043 /* allocate relevance flags */
9044 SCIP_CALL( SCIPallocBufferArray(scip, &isvarrelevant, consdata->nvars) );
9045
9046 /* get the minimal and maximal activity of the constraint */
9047 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
9048 &isminsettoinfinity, &ismaxsettoinfinity);
9049 assert(( isminsettoinfinity && !SCIPisInfinity(scip, -consdata->lhs) )
9050 || SCIPisLT(scip, minactivity, consdata->lhs)
9051 || ( ismaxsettoinfinity && !SCIPisInfinity(scip, consdata->rhs) )
9052 || SCIPisGT(scip, maxactivity, consdata->rhs));
9053
9054 minleftactivity = 0.0;
9055 maxleftactivity = 0.0;
9056
9057 /* try to tighten each coefficient */
9058 i = 0;
9059 while( i < consdata->nvars )
9060 {
9061 /* get coefficient and variable's bounds */
9062 var = consdata->vars[i];
9063 val = consdata->vals[i];
9064 assert(!SCIPisZero(scip, val));
9065 lb = SCIPvarGetLbLocal(var);
9066 ub = SCIPvarGetUbLocal(var);
9067
9068 /* check sign of coefficient */
9069 if( val >= 0.0 )
9070 {
9071 /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9072 isvarrelevant[i] = SCIPvarIsIntegral(var)
9073 && SCIPisGE(scip, minactivity + val, consdata->lhs) && SCIPisLE(scip, maxactivity - val, consdata->rhs);
9074
9075 if( isvarrelevant[i] )
9076 {
9077 /* change coefficients:
9078 * ai' := max(lhs - minact, maxact - rhs)
9079 * lhs' := lhs - (ai - ai')*li
9080 * rhs' := rhs - (ai - ai')*ui
9081 */
9082
9083 lval = consdata->lhs - minactivity;
9084 rval = maxactivity - consdata->rhs;
9085
9086 /* Try to avoid cancellation, if there are only two variables */
9087 if( consdata->nvars == 2 )
9088 {
9089 SCIP_Real otherval;
9090 otherval = consdata->vals[1-i];
9091
9092 if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9093 {
9094 lval = consdata->lhs - val*lb;
9095 lval -= otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9096 }
9097
9098 if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9099 {
9100 rval = val*ub - consdata->rhs;
9101 rval += otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9102 }
9103 }
9104
9105 newval = MAX3(lval, rval, 0.0);
9106 assert(SCIPisSumRelLE(scip, newval, val));
9107
9108 /* Try to avoid cancellation in computation of lhs/rhs */
9109 newlhs = consdata->lhs - val * lb;
9110 newlhs += newval * lb;
9111 newrhs = consdata->rhs - val * ub;
9112 newrhs += newval * ub;
9113
9114 if( !SCIPisSumRelEQ(scip, newval, val) )
9115 {
9116 SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9117 SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var), minactivity,
9118 maxactivity, consdata->lhs, consdata->rhs);
9119
9120 /* update the coefficient and the activity bounds */
9121 if( SCIPisZero(scip, newval) )
9122 {
9123 SCIP_CALL( delCoefPos(scip, cons, i) );
9124 --i;
9125 }
9126 else
9127 {
9128 SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9129 }
9130 ++(*nchgcoefs);
9131
9132 /* get the new minimal and maximal activity of the constraint */
9133 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight,
9134 &ismaxacttight, &isminsettoinfinity, &ismaxsettoinfinity);
9135
9136 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9137 {
9138 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons),
9139 consdata->lhs, newlhs);
9140
9141 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9142 (*nchgsides)++;
9143 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9144 }
9145
9146 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9147 {
9148 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons),
9149 consdata->rhs, newrhs);
9150
9151 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9152 (*nchgsides)++;
9153 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9154 }
9155 }
9156 }
9157 else
9158 {
9159 if( !SCIPisInfinity(scip, -minleftactivity) )
9160 {
9161 assert(!SCIPisInfinity(scip, val));
9162 assert(!SCIPisInfinity(scip, lb));
9163 if( SCIPisInfinity(scip, -lb) )
9164 minleftactivity = -SCIPinfinity(scip);
9165 else
9166 minleftactivity += val * lb;
9167 }
9168
9169 if( !SCIPisInfinity(scip, maxleftactivity) )
9170 {
9171 assert(!SCIPisInfinity(scip, val));
9172 assert(!SCIPisInfinity(scip, -ub));
9173 if( SCIPisInfinity(scip,ub) )
9174 maxleftactivity = SCIPinfinity(scip);
9175 else
9176 maxleftactivity += val * ub;
9177 }
9178 }
9179 }
9180 else
9181 {
9182 /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9183 isvarrelevant[i] = SCIPvarIsIntegral(var)
9184 && SCIPisGE(scip, minactivity - val, consdata->lhs) && SCIPisLE(scip, maxactivity + val, consdata->rhs);
9185
9186 if( isvarrelevant[i] )
9187 {
9188 /* change coefficients:
9189 * ai' := min(rhs - maxact, minact - lhs)
9190 * lhs' := lhs - (ai - ai')*ui
9191 * rhs' := rhs - (ai - ai')*li
9192 */
9193
9194 lval = minactivity - consdata->lhs;
9195 rval = consdata->rhs - maxactivity;
9196
9197 /* Try to avoid cancellation, if there are only two variables */
9198 if( consdata->nvars == 2 )
9199 {
9200 SCIP_Real otherval;
9201 otherval = consdata->vals[1-i];
9202
9203 if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9204 {
9205 lval = val*ub - consdata->lhs;
9206 lval += otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9207 }
9208
9209 if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9210 {
9211 rval = consdata->rhs - val*lb;
9212 rval -= otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9213 }
9214 }
9215
9216 newval = MIN3(lval, rval, 0.0);
9217 assert(SCIPisSumRelGE(scip, newval, val));
9218
9219 /* Try to avoid cancellation in computation of lhs/rhs */
9220 newlhs = consdata->lhs - val * ub;
9221 newlhs += newval * ub;
9222 newrhs = consdata->rhs - val * lb;
9223 newrhs += newval * lb;
9224
9225 if( !SCIPisSumRelEQ(scip, newval, val) )
9226 {
9227 SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9228 SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var), minactivity,
9229 maxactivity, consdata->lhs, consdata->rhs);
9230
9231 /* update the coefficient and the activity bounds */
9232 if( SCIPisZero(scip, newval) )
9233 {
9234 SCIP_CALL( delCoefPos(scip, cons, i) );
9235 --i;
9236 }
9237 else
9238 {
9239 SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9240 }
9241 ++(*nchgcoefs);
9242
9243 /* get the new minimal and maximal activity of the constraint */
9244 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight,
9245 &ismaxacttight, &isminsettoinfinity, &ismaxsettoinfinity);
9246
9247 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9248 {
9249 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons),
9250 consdata->lhs, newlhs);
9251
9252 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9253 (*nchgsides)++;
9254 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9255 }
9256
9257 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9258 {
9259 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons),
9260 consdata->rhs, newrhs);
9261
9262 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9263 (*nchgsides)++;
9264 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9265 }
9266 }
9267 }
9268 else
9269 {
9270 if( !SCIPisInfinity(scip, -minleftactivity) )
9271 {
9272 assert(!SCIPisInfinity(scip, -val));
9273 assert(!SCIPisInfinity(scip, -ub));
9274 if( SCIPisInfinity(scip, ub) )
9275 minleftactivity = -SCIPinfinity(scip);
9276 else
9277 minleftactivity += val * ub;
9278 }
9279
9280 if( !SCIPisInfinity(scip, maxleftactivity) )
9281 {
9282 assert(!SCIPisInfinity(scip, -val));
9283 assert(!SCIPisInfinity(scip, lb));
9284 if( SCIPisInfinity(scip, -lb) )
9285 maxleftactivity = SCIPinfinity(scip);
9286 else
9287 maxleftactivity += val * lb;
9288 }
9289 }
9290 }
9291
9292 ++i;
9293 }
9294
9295 SCIPdebugMsg(scip, "minleftactivity = %.15g, rhs = %.15g\n",
9296 minleftactivity, consdata->rhs);
9297 SCIPdebugMsg(scip, "maxleftactivity = %.15g, lhs = %.15g\n",
9298 maxleftactivity, consdata->lhs);
9299
9300 /* minleft == \infty ==> minactivity == \infty */
9301 assert(!SCIPisInfinity(scip, -minleftactivity) || SCIPisInfinity(scip, -minactivity));
9302 assert(!SCIPisInfinity(scip, maxleftactivity) || SCIPisInfinity(scip, maxactivity));
9303
9304 /* if the lhs is finite, we will check in the following whether the not relevant variables can make lhs feasible;
9305 * this is not valid, if the minactivity is -\infty (aggrlhs would be minus infinity in the following computation)
9306 * or if huge values contributed to the minactivity, because the minactivity is then just a relaxation
9307 * (<= the exact minactivity), and we might falsely remove coefficients in the following
9308 */
9309 assert(!SCIPisInfinity(scip, minactivity));
9310 if( !SCIPisInfinity(scip, -consdata->lhs) && (SCIPisInfinity(scip, -minactivity) || !isminacttight) )
9311 goto TERMINATE;
9312
9313 /* if the rhs is finite, we will check in the following whether the not relevant variables can make rhs feasible;
9314 * this is not valid, if the maxactivity is \infty (aggrrhs would be infinity in the following computation)
9315 * or if huge values contributed to the maxactivity, because the maxactivity is then just a relaxation
9316 * (>= the exact maxactivity), and we might falsely remove coefficients in the following
9317 */
9318 assert(!SCIPisInfinity(scip, -maxactivity));
9319 if( !SCIPisInfinity(scip, consdata->rhs) && (SCIPisInfinity(scip, maxactivity) || !ismaxacttight) )
9320 goto TERMINATE;
9321
9322 /* correct lhs and rhs by min/max activity of relevant variables
9323 * relevant variables are all those where a deviation from the bound makes the lhs/rhs redundant
9324 */
9325 aggrlhs = consdata->lhs - minactivity + minleftactivity;
9326 aggrrhs = consdata->rhs - maxactivity + maxleftactivity;
9327
9328 /* check if the constraint contains variables whose coefficient can be removed. The reasoning is the following:
9329 * Each relevant variable can make the lhs/rhs feasible with a deviation of only one in the bound. If _all_ not
9330 * relevant variables together cannot make lhs/rhs redundant, they can be removed from the constraint. aggrrhs may
9331 * contain some near-infinity value, but only if rhs is infinity.
9332 */
9333 if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasLT(scip, maxleftactivity, aggrlhs))
9334 && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasGT(scip, minleftactivity, aggrrhs)) )
9335 {
9336 SCIP_Real minleftactivitypart;
9337 SCIP_Real maxleftactivitypart;
9338
9339 assert(!SCIPisInfinity(scip, -consdata->lhs) || !SCIPisInfinity(scip, consdata->rhs));
9340
9341 /* remove redundant variables from constraint */
9342 i = 0;
9343 while( i < consdata->nvars )
9344 {
9345 /* consider redundant variable */
9346 if( !isvarrelevant[i] )
9347 {
9348 /* get coefficient and variable's bounds */
9349 var = consdata->vars[i];
9350 val = consdata->vals[i];
9351 assert(!SCIPisZero(scip, val));
9352 lb = SCIPvarGetLbLocal(var);
9353 ub = SCIPvarGetUbLocal(var);
9354
9355 SCIPdebugMsg(scip, "val = %g\tlhs = %g\trhs = %g\n", val, consdata->lhs, consdata->rhs);
9356 SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> from constraint since it is redundant\n",
9357 SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]));
9358
9359 /* check sign of coefficient */
9360 if( val >= 0.0 )
9361 {
9362 minleftactivitypart = val * lb;
9363 maxleftactivitypart = val * ub;
9364 }
9365 else
9366 {
9367 minleftactivitypart = val * ub;
9368 maxleftactivitypart = val * lb;
9369 }
9370
9371 /* remove redundant variable */
9372 isvarrelevant[i] = isvarrelevant[consdata->nvars - 1];
9373 SCIP_CALL( delCoefPos(scip, cons, i) );
9374 --i;
9375
9376 /* adjust lhs and right hand side */
9377 newlhs = consdata->lhs - minleftactivitypart;
9378 newrhs = consdata->rhs - maxleftactivitypart;
9379
9380 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9381 {
9382 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons),
9383 consdata->lhs, newlhs);
9384
9385 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9386 ++(*nchgsides);
9387 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9388 }
9389
9390 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9391 {
9392 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons),
9393 consdata->rhs, newrhs);
9394
9395 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9396 ++(*nchgsides);
9397 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9398 }
9399 }
9400
9401 ++i;
9402 }
9403 }
9404
9405TERMINATE:
9406 /* free relevance flags */
9407 SCIPfreeBufferArray(scip, &isvarrelevant);
9408
9409 return SCIP_OKAY;
9410}
9411
9412/** processes equality with only one variable by fixing the variable and deleting the constraint */
9413static
9415 SCIP* scip, /**< SCIP data structure */
9416 SCIP_CONS* cons, /**< linear constraint */
9417 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9418 int* nfixedvars, /**< pointer to count number of fixed variables */
9419 int* ndelconss /**< pointer to count number of deleted constraints */
9420 )
9421{
9422 SCIP_CONSDATA* consdata;
9423 SCIP_VAR* var;
9424 SCIP_Real val;
9425 SCIP_Real fixval;
9426 SCIP_Bool infeasible;
9427 SCIP_Bool fixed;
9428
9429 assert(scip != NULL);
9430 assert(cons != NULL);
9431 assert(cutoff != NULL);
9432 assert(nfixedvars != NULL);
9433 assert(ndelconss != NULL);
9434
9435 consdata = SCIPconsGetData(cons);
9436 assert(consdata != NULL);
9437 assert(consdata->nvars == 1);
9438 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9439
9440 /* calculate the value to fix the variable to */
9441 var = consdata->vars[0];
9442 val = consdata->vals[0];
9443 assert(!SCIPisZero(scip, val));
9444 fixval = SCIPselectSimpleValue(consdata->lhs/val - 0.9 * SCIPepsilon(scip),
9445 consdata->rhs/val + 0.9 * SCIPepsilon(scip), MAXDNOM);
9446 SCIPdebugMsg(scip, "linear equality <%s>: fix <%s> == %.15g\n",
9447 SCIPconsGetName(cons), SCIPvarGetName(var), fixval);
9448
9449 /* fix variable */
9450 SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
9451 if( infeasible )
9452 {
9453 SCIPdebugMsg(scip, " -> infeasible fixing\n");
9454 *cutoff = TRUE;
9455 return SCIP_OKAY;
9456 }
9457 if( fixed )
9458 (*nfixedvars)++;
9459
9460 /* disable constraint */
9461 SCIP_CALL( SCIPdelCons(scip, cons) );
9462 if( !consdata->upgraded )
9463 (*ndelconss)++;
9464
9465 return SCIP_OKAY;
9466}
9467
9468/** processes equality with exactly two variables by aggregating one of the variables and deleting the constraint */
9469static
9471 SCIP* scip, /**< SCIP data structure */
9472 SCIP_CONS* cons, /**< linear constraint */
9473 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9474 int* naggrvars, /**< pointer to count number of aggregated variables */
9475 int* ndelconss /**< pointer to count number of deleted constraints */
9476 )
9477{
9478 SCIP_CONSDATA* consdata;
9479 SCIP_Bool infeasible;
9480 SCIP_Bool redundant;
9481 SCIP_Bool aggregated;
9482
9483 assert(scip != NULL);
9484 assert(cons != NULL);
9485 assert(cutoff != NULL);
9486 assert(naggrvars != NULL);
9487 assert(ndelconss != NULL);
9488
9489 consdata = SCIPconsGetData(cons);
9490 assert(consdata != NULL);
9491 assert(consdata->nvars == 2);
9492 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9493
9494 SCIPdebugMsg(scip, "linear constraint <%s>: aggregate %.15g<%s> + %.15g<%s> == %.15g\n",
9495 SCIPconsGetName(cons), consdata->vals[0], SCIPvarGetName(consdata->vars[0]),
9496 consdata->vals[1], SCIPvarGetName(consdata->vars[1]), consdata->rhs);
9497
9498 /* aggregate the equality */
9499 SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], consdata->vals[0], consdata->vals[1],
9500 consdata->rhs, &infeasible, &redundant, &aggregated) );
9501
9502 /* check for infeasibility of aggregation */
9503 if( infeasible )
9504 {
9505 SCIPdebugMsg(scip, " -> infeasible aggregation\n");
9506 *cutoff = TRUE;
9507 return SCIP_OKAY;
9508 }
9509
9510 /* count the aggregation */
9511 if( aggregated )
9512 (*naggrvars)++;
9513
9514 /* delete the constraint, if it is redundant */
9515 if( redundant )
9516 {
9517 SCIP_CALL( SCIPdelCons(scip, cons) );
9518
9519 if( !consdata->upgraded )
9520 (*ndelconss)++;
9521 }
9522
9523 return SCIP_OKAY;
9524}
9525
9526/** calculates the new lhs and rhs of the constraint after the given variable is aggregated out */
9527static
9529 SCIP* scip, /**< SCIP data structure */
9530 SCIP_CONSDATA* consdata, /**< linear constraint data */
9531 SCIP_VAR* slackvar, /**< variable to be aggregated out */
9532 SCIP_Real slackcoef, /**< coefficient of variable in constraint */
9533 SCIP_Real* newlhs, /**< pointer to store new lhs of constraint */
9534 SCIP_Real* newrhs /**< pointer to store new rhs of constraint */
9535 )
9536{
9537 SCIP_Real slackvarlb;
9538 SCIP_Real slackvarub;
9539
9540 assert(scip != NULL);
9541 assert(consdata != NULL);
9542 assert(newlhs != NULL);
9543 assert(newrhs != NULL);
9544 assert(!SCIPisInfinity(scip, -consdata->lhs));
9545 assert(!SCIPisInfinity(scip, consdata->rhs));
9546
9547 slackvarlb = SCIPvarGetLbGlobal(slackvar);
9548 slackvarub = SCIPvarGetUbGlobal(slackvar);
9549 if( slackcoef > 0.0 )
9550 {
9551 if( SCIPisInfinity(scip, -slackvarlb) )
9552 *newrhs = SCIPinfinity(scip);
9553 else
9554 *newrhs = consdata->rhs - slackcoef * slackvarlb;
9555 if( SCIPisInfinity(scip, slackvarub) )
9556 *newlhs = -SCIPinfinity(scip);
9557 else
9558 *newlhs = consdata->lhs - slackcoef * slackvarub;
9559 }
9560 else
9561 {
9562 if( SCIPisInfinity(scip, -slackvarlb) )
9563 *newlhs = -SCIPinfinity(scip);
9564 else
9565 *newlhs = consdata->rhs - slackcoef * slackvarlb;
9566 if( SCIPisInfinity(scip, slackvarub) )
9567 *newrhs = SCIPinfinity(scip);
9568 else
9569 *newrhs = consdata->lhs - slackcoef * slackvarub;
9570 }
9571 assert(SCIPisLE(scip, *newlhs, *newrhs));
9572}
9573
9574/** processes equality with more than two variables by multi-aggregating one of the variables and converting the equality
9575 * into an inequality; if multi-aggregation is not possible, tries to identify one continuous or integer variable that
9576 * is implied integral by this constraint
9577 *
9578 * @todo Check whether a more clever way of avoiding aggregation of variables containing implied integral variables
9579 * can help.
9580 */
9581static
9583 SCIP* scip, /**< SCIP data structure */
9584 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
9585 SCIP_CONS* cons, /**< linear constraint */
9586 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9587 int* naggrvars, /**< pointer to count number of aggregated variables */
9588 int* ndelconss, /**< pointer to count number of deleted constraints */
9589 int* nchgvartypes /**< pointer to count number of changed variable types */
9590 )
9591{
9592 SCIP_CONSDATA* consdata;
9593 SCIP_VAR** vars;
9594 SCIP_Real* vals;
9595 SCIP_VARTYPE bestslacktype;
9596 SCIP_VARTYPE slacktype;
9597 SCIP_IMPLINTTYPE impltype;
9598 SCIP_Real lhs;
9599 SCIP_Real rhs;
9600 SCIP_Real bestslackdomrng;
9601 SCIP_Real minabsval;
9602 SCIP_Real maxabsval;
9603 SCIP_Bool bestremovescons;
9604 SCIP_Bool coefszeroone;
9605 SCIP_Bool coefsintegral;
9606 SCIP_Bool varsintegral;
9607 SCIP_Bool infeasible;
9608 int maxnlocksstay;
9609 int maxnlocksremove;
9610 int bestslackpos;
9611 int bestnlocks;
9612 int ncontvars;
9613 int contvarpos;
9614 int nintvars;
9615 int nweakimplvars;
9616 int nimplvars;
9617 int intvarpos;
9618 int v;
9619
9620 assert(scip != NULL);
9621 assert(cons != NULL);
9622 assert(cutoff != NULL);
9623 assert(naggrvars != NULL);
9624
9625 consdata = SCIPconsGetData(cons);
9626 assert(consdata != NULL);
9627 assert(consdata->nvars > 2);
9628 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9629
9630 SCIPdebugMsg(scip, "linear constraint <%s>: try to multi-aggregate equality\n", SCIPconsGetName(cons));
9631
9632 /* We do not want to increase the total number of non-zeros due to the multi-aggregation.
9633 * Therefore, we have to restrict the number of locks of a variable that is aggregated out.
9634 * maxnlocksstay: maximal sum of lock numbers if the constraint does not become redundant after the aggregation
9635 * maxnlocksremove: maximal sum of lock numbers if the constraint can be deleted after the aggregation
9636 */
9637 lhs = consdata->lhs;
9638 rhs = consdata->rhs;
9639 maxnlocksstay = 0;
9640 if( consdata->nvars == 3 )
9641 {
9642 /* If the constraint becomes redundant, 3 non-zeros are removed, and we get 1 additional non-zero for each
9643 * constraint the variable appears in. Thus, the variable must appear in at most 3 other constraints.
9644 */
9645 maxnlocksremove = 3;
9646 }
9647 else if( consdata->nvars == 4 )
9648 {
9649 /* If the constraint becomes redundant, 4 non-zeros are removed, and we get 2 additional non-zeros for each
9650 * constraint the variable appears in. Thus, the variable must appear in at most 2 other constraints.
9651 */
9652 maxnlocksremove = 2;
9653 }
9654 else
9655 {
9656 /* If the constraint is redundant but has more than 4 variables, we can only accept one other constraint. */
9657 maxnlocksremove = 1;
9658 }
9659
9660 /* the locks on this constraint can be ignored */
9661 if( SCIPconsIsChecked(cons) )
9662 {
9663 if( !SCIPisInfinity(scip, -lhs) )
9664 {
9665 maxnlocksstay++;
9666 maxnlocksremove++;
9667 }
9668 if( !SCIPisInfinity(scip, rhs) )
9669 {
9670 maxnlocksstay++;
9671 maxnlocksremove++;
9672 }
9673 }
9674
9675 /* look for a slack variable s to convert a*x + s == b into lhs <= a*x <= rhs */
9676 vars = consdata->vars;
9677 vals = consdata->vals;
9678 bestslackpos = -1;
9679 bestslacktype = SCIP_VARTYPE_BINARY;
9680 bestnlocks = INT_MAX;
9681 bestremovescons = FALSE;
9682 bestslackdomrng = 0.0;
9683 coefszeroone = TRUE;
9684 coefsintegral = TRUE;
9685 varsintegral = TRUE;
9686 ncontvars = 0;
9687 contvarpos = -1;
9688 nintvars = 0;
9689 nweakimplvars = 0;
9690 nimplvars = 0;
9691 intvarpos = -1;
9692 minabsval = SCIPinfinity(scip);
9693 maxabsval = -1.0;
9694 for( v = 0; v < consdata->nvars; ++v )
9695 {
9696 SCIP_VAR* var;
9697 SCIP_Real val;
9698 SCIP_Real absval;
9699 SCIP_Real varlb;
9700 SCIP_Real varub;
9701 SCIP_Bool iscont;
9702 int nlocks;
9703
9704 assert(vars != NULL);
9705 assert(vals != NULL);
9706
9707 var = vars[v];
9708 assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= 1); /* because variable is locked in this equality */
9710 varlb = SCIPvarGetLbGlobal(var);
9711 varub = SCIPvarGetUbGlobal(var);
9712
9713 val = vals[v];
9714 absval = REALABS(val);
9715 assert(SCIPisPositive(scip, absval));
9716
9717 /* calculate minimal and maximal absolute value */
9718 if( absval < minabsval )
9719 minabsval = absval;
9720 if( absval > maxabsval )
9721 maxabsval = absval;
9722
9723 /** @todo Do not exit here, but continue if we may still detect implied integrality. */
9724 /* do not try to multi aggregate, when numerical bad */
9725 if( maxabsval / minabsval > conshdlrdata->maxmultaggrquot )
9726 return SCIP_OKAY;
9727
9728 impltype = SCIPvarGetImplType(var);
9730 coefszeroone = coefszeroone && SCIPisEQ(scip, absval, 1.0);
9731 coefsintegral = coefsintegral && SCIPisIntegral(scip, val);
9732 varsintegral = varsintegral && (slacktype != SCIP_VARTYPE_CONTINUOUS);
9733 iscont = (slacktype == SCIP_VARTYPE_CONTINUOUS || slacktype == SCIP_DEPRECATED_VARTYPE_IMPLINT);
9734
9735 /* update candidates for continuous -> implint and integer -> implint conversion */
9736 if( slacktype == SCIP_VARTYPE_CONTINUOUS )
9737 {
9738 ncontvars++;
9739 contvarpos = v;
9740 }
9741 else if( slacktype == SCIP_DEPRECATED_VARTYPE_IMPLINT )
9742 {
9743 ++nimplvars;
9744 assert(impltype != SCIP_IMPLINTTYPE_NONE);
9745 if( impltype == SCIP_IMPLINTTYPE_WEAK )
9746 ++nweakimplvars;
9747 }
9748 else if( slacktype == SCIP_VARTYPE_INTEGER )
9749 {
9750 nintvars++;
9751 intvarpos = v;
9752 }
9753
9754 /* check, if variable is already fixed or aggregated */
9755 if( !SCIPvarIsActive(var) )
9756 continue;
9757
9758 /* check, if variable is used in too many other constraints, even if this constraint could be deleted */
9760
9761 if( nlocks > maxnlocksremove )
9762 continue;
9763
9764 /* check, if variable can be used as a slack variable */
9765 if( (iscont || (coefsintegral && varsintegral && SCIPisEQ(scip, absval, 1.0))) &&
9767 {
9768 SCIP_Bool better;
9769 SCIP_Bool equal;
9770 SCIP_Real slackdomrng;
9771
9772 if( SCIPisInfinity(scip, varub) || SCIPisInfinity(scip, -varlb) )
9773 slackdomrng = SCIPinfinity(scip);
9774 /* we do not want to perform multi-aggregation due to numerics, if the bounds are huge */
9775 else if( SCIPisHugeValue(scip, varub) || SCIPisHugeValue(scip, -varlb) )
9776 return SCIP_OKAY;
9777 else
9778 {
9779 slackdomrng = (varub - varlb)*absval;
9780 assert(!SCIPisInfinity(scip, slackdomrng));
9781 }
9782 equal = FALSE;
9783
9784 /* continuous > implied > integer > binary */
9785 better = (slacktype > bestslacktype) || (bestslackpos == -1);
9786 if( !better && slacktype == bestslacktype )
9787 {
9788 better = (nlocks < bestnlocks);
9789 if( nlocks == bestnlocks && !bestremovescons )
9790 {
9791 better = SCIPisGT(scip, slackdomrng, bestslackdomrng);
9792 equal = !better && SCIPisGE(scip, slackdomrng, bestslackdomrng);
9793 }
9794 }
9795
9796 if( better || equal )
9797 {
9798 SCIP_Real minresactivity;
9799 SCIP_Real maxresactivity;
9800 SCIP_Real newlhs;
9801 SCIP_Real newrhs;
9802 SCIP_Bool removescons;
9803 SCIP_Bool ismintight;
9804 SCIP_Bool ismaxtight;
9805 SCIP_Bool isminsettoinfinity;
9806 SCIP_Bool ismaxsettoinfinity;
9807
9808 /* check if the constraint becomes redundant after multi-aggregation */
9809 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
9810 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
9811
9812 /* do not perform the multi-aggregation due to numerics, if we have huge contributions in the residual
9813 * activity
9814 */
9815 if( !ismintight || !ismaxtight )
9816 continue;
9817
9818 getNewSidesAfterAggregation(scip, consdata, var, val, &newlhs, &newrhs);
9819 removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9820
9821 /* check resactivities for reliability */
9822 if( removescons )
9823 {
9824 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
9825 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
9826
9827 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity)
9828 && SCIPisFeasLE(scip, newlhs, minresactivity))
9829 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
9830
9831 removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9832 }
9833
9834 /* if parameter multaggrremove is set to TRUE, only aggregate when this removes constraint */
9835 if( conshdlrdata->multaggrremove && !removescons )
9836 continue;
9837
9838 /* if the constraint does not become redundant, only accept the variable if it does not appear in
9839 * other constraints
9840 */
9841 if( !removescons && nlocks > maxnlocksstay )
9842 continue;
9843
9844 /* prefer variables that make the constraints redundant
9845 * unless there is a continuous better slack
9846 */
9847 if( !bestremovescons && removescons )
9848 better = TRUE;
9849 else if( bestremovescons && !removescons && (bestslacktype > SCIP_VARTYPE_INTEGER || slacktype <= SCIP_VARTYPE_INTEGER) )
9850 better = FALSE;
9851 if( better )
9852 {
9853 bestslackpos = v;
9854 bestslacktype = slacktype;
9855 bestnlocks = nlocks;
9856 bestslackdomrng = slackdomrng;
9857 bestremovescons = removescons;
9858 }
9859 }
9860 }
9861 }
9862
9863 /* if all coefficients and variables are integral, the right hand side must also be integral */
9864 if( coefsintegral && varsintegral && !SCIPisFeasIntegral(scip, consdata->rhs) )
9865 {
9866 SCIPdebugMsg(scip, "linear equality <%s> is integer infeasible\n", SCIPconsGetName(cons));
9868 *cutoff = TRUE;
9869 return SCIP_OKAY;
9870 }
9871
9872 /* if the slack variable is of integer type, and the constraint itself may take fractional values,
9873 * we cannot aggregate the variable, because the integrality condition would get lost
9874 * Similarly, if there are implied integral variables, we cannot aggregate since we might
9875 * loose the integrality condition for this variable.
9876 */
9877 if( bestslackpos >= 0
9878 && (bestslacktype == SCIP_VARTYPE_CONTINUOUS || bestslacktype == SCIP_DEPRECATED_VARTYPE_IMPLINT
9879 || (coefsintegral && varsintegral && nimplvars == 0)) )
9880 {
9881 SCIP_VAR** aggrvars;
9882 SCIP_VAR* slackvar;
9884 SCIP_Real slackcoef;
9885 SCIP_Real aggrconst;
9886 SCIP_Real newlhs;
9887 SCIP_Real newrhs;
9888 SCIP_Bool aggregated;
9889
9890 /* we found a slack variable that only occurs in at most one other constraint:
9891 * a_1*x_1 + ... + a_k*x_k + a'*s == rhs -> s == rhs - a_1/a'*x_1 - ... - a_k/a'*x_k
9892 */
9893 assert(bestslackpos < consdata->nvars);
9894
9895 /* do not multi aggregate binary variables */
9896 if( SCIPvarIsBinary(vars[bestslackpos]) )
9897 return SCIP_OKAY;
9898
9899 /* convert equality into inequality by deleting the slack variable:
9900 * x + a*s == b, l <= s <= u -> b - a*u <= x <= b - a*l
9901 */
9902 slackvar = vars[bestslackpos];
9903 slackcoef = vals[bestslackpos];
9904 assert(!SCIPisZero(scip, slackcoef));
9905 aggrconst = consdata->rhs/slackcoef;
9906
9907 /* allocate temporary memory */
9908 SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars - 1) );
9909 SCIP_CALL( SCIPallocBufferArray(scip, &scalars, consdata->nvars - 1) );
9910
9911 /* set up the multi-aggregation */
9912 SCIPdebugMsg(scip, "linear constraint <%s>: multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(slackvar));
9913 for( v = 0; v < consdata->nvars - 1; ++v )
9914 {
9915 if( v == bestslackpos )
9916 {
9917 aggrvars[v] = vars[consdata->nvars - 1];
9918 scalars[v] = -consdata->vals[consdata->nvars - 1] / slackcoef;
9919 }
9920 else
9921 {
9922 aggrvars[v] = vars[v];
9923 scalars[v] = -consdata->vals[v] / slackcoef;
9924 }
9925 SCIPdebugMsgPrint(scip, " %+.15g<%s>", scalars[v], SCIPvarGetName(aggrvars[v]));
9926 }
9927 SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g], nlocks=%d, maxnlocks=%d, removescons=%u\n",
9928 aggrconst, SCIPvarGetName(slackvar), SCIPvarGetLbGlobal(slackvar), SCIPvarGetUbGlobal(slackvar),
9929 bestnlocks, bestremovescons ? maxnlocksremove : maxnlocksstay, bestremovescons);
9930
9931 /* perform the multi-aggregation */
9932 SCIP_CALL( SCIPmultiaggregateVar(scip, slackvar, consdata->nvars - 1, aggrvars, scalars, aggrconst,
9933 &infeasible, &aggregated) );
9934
9935 /* free temporary memory */
9937 SCIPfreeBufferArray(scip, &aggrvars);
9938
9939 /* check for infeasible aggregation */
9940 if( infeasible )
9941 {
9942 SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
9943 *cutoff = TRUE;
9944 return SCIP_OKAY;
9945 }
9946
9947 /* check for applied aggregation */
9948 if( !aggregated )
9949 {
9950 SCIPdebugMsg(scip, "linear constraint <%s>: multi-aggregation not applicable\n", SCIPconsGetName(cons));
9951 return SCIP_OKAY;
9952 }
9953
9954 ++(*naggrvars);
9955
9956 getNewSidesAfterAggregation(scip, consdata, slackvar, slackcoef, &newlhs, &newrhs);
9957 assert(SCIPisLE(scip, newlhs, newrhs));
9958 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9959 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9960 SCIP_CALL( delCoefPos(scip, cons, bestslackpos) );
9961
9962 /* delete the constraint if it became redundant */
9963 if( bestremovescons )
9964 {
9965 SCIPdebugMsg(scip, "linear constraint <%s>: redundant after multi-aggregation\n", SCIPconsGetName(cons));
9966 SCIP_CALL( SCIPdelCons(scip, cons) );
9967
9968 if( !consdata->upgraded )
9969 (*ndelconss)++;
9970 }
9971 }
9972 else if( ncontvars == 1 )
9973 {
9974 SCIP_VAR* var;
9975
9976 assert(0 <= contvarpos && contvarpos < consdata->nvars);
9977 var = vars[contvarpos];
9979
9980 if( coefsintegral && SCIPisFeasIntegral(scip, consdata->rhs) )
9981 {
9982 /* upgrade continuous variable to an implied integral one, if the absolute value of the coefficient is one */
9983 if( SCIPisEQ(scip, REALABS(vals[contvarpos]), 1.0) )
9984 {
9985 /* convert the continuous variable with coefficient 1.0 into an implied integral variable */
9986 SCIPdebugMsg(scip, "linear constraint <%s>: converting continuous variable <%s> to implied integral variable\n",
9988 /* if the integrality does not depend on weak implied integrality, the variable becomes strongly implied integral */
9989 impltype = nweakimplvars == 0 ? SCIP_IMPLINTTYPE_STRONG : SCIP_IMPLINTTYPE_WEAK;
9990 SCIP_CALL( SCIPchgVarImplType(scip, var, impltype, &infeasible) );
9991 (*nchgvartypes)++;
9992 if( infeasible )
9993 {
9994 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
9995 *cutoff = TRUE;
9996
9997 return SCIP_OKAY;
9998 }
9999 }
10000 /* aggregate continuous variable to an implied integral one if the absolute coefficient is unequal to one */
10001 /* @todo check if the aggregation coefficient should be in some range(, which is not too big) */
10002 else if( !SCIPdoNotAggr(scip) )
10003 {
10004 SCIP_VAR* newvar;
10005 SCIP_Real absval;
10006 char newvarname[SCIP_MAXSTRLEN];
10007 SCIP_Bool redundant;
10008 SCIP_Bool aggregated;
10009
10010 absval = REALABS(vals[contvarpos]);
10011
10012 (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_impl", SCIPvarGetName(var));
10013
10014 /* create new implied integral variable for aggregation */
10015 SCIP_CALL( SCIPcreateVarImpl(scip, &newvar, newvarname, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0,
10018
10019 /* add new variable to problem */
10020 SCIP_CALL( SCIPaddVar(scip, newvar) );
10021
10022#ifdef WITH_DEBUG_SOLUTION
10023 if( SCIPdebugIsMainscip(scip) )
10024 {
10025 SCIP_Real varval;
10026 SCIP_CALL( SCIPdebugGetSolVal(scip, var, &varval) );
10027 SCIP_CALL( SCIPdebugAddSolVal(scip, newvar, absval * varval) );
10028 }
10029#endif
10030
10031 /* convert the continuous variable with coefficient 1.0 into an implied integral variable */
10032 SCIPdebugMsg(scip, "linear constraint <%s>: aggregating continuous variable <%s> to newly created implied integral variable <%s>, aggregation factor = %g\n",
10033 SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(newvar), absval);
10034
10035 /* aggregate continuous and implied integral variable */
10036 SCIP_CALL( SCIPaggregateVars(scip, var, newvar, absval, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
10037
10038 if( infeasible )
10039 {
10040 SCIPdebugMsg(scip, "infeasible aggregation of variable <%s> to implied integral variable <%s>, domain is empty\n",
10042 *cutoff = TRUE;
10043
10044 /* release implied integral variable */
10045 SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10046
10047 return SCIP_OKAY;
10048 }
10049
10050 /* release implied integral variable */
10051 SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10052
10053 if( aggregated )
10054 (*naggrvars)++;
10055 else
10056 return SCIP_OKAY;
10057 }
10058
10059 /* we do not have any event on vartype changes, so we need to manually force this constraint to be presolved
10060 * again
10061 */
10062 consdata->boundstightened = 0;
10063 consdata->rangedrowpropagated = 0;
10064 consdata->presolved = FALSE;
10065 }
10066 }
10067 else if( ncontvars == 0 && nimplvars == 0 && nintvars == 1 && !coefszeroone )
10068 {
10069 SCIP_VAR* var;
10070
10071 /* this seems to help for rococo instances, but does not for rout (where all coefficients are +/- 1.0)
10072 * -> we don't convert integers into implints if the row is a 0/1-row
10073 */
10074 assert(varsintegral);
10075 assert(0 <= intvarpos && intvarpos < consdata->nvars);
10076 var = vars[intvarpos];
10078
10079 if( coefsintegral
10080 && SCIPisEQ(scip, REALABS(vals[intvarpos]), 1.0)
10081 && SCIPisFeasIntegral(scip, consdata->rhs) )
10082 {
10083 /* convert the integer variable with coefficient 1.0 into an implied integral variable */
10084 SCIPdebugMsg(scip, "linear constraint <%s>: converting integer variable <%s> to implied integral variable\n",
10087 (*nchgvartypes)++;
10088 if( infeasible )
10089 {
10090 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10091 *cutoff = TRUE;
10092
10093 return SCIP_OKAY;
10094 }
10095 }
10096 }
10097
10098 return SCIP_OKAY;
10099}
10100
10101/** checks if the given variables and their coefficient are equal (w.r.t. scaling factor) to the objective function */
10102static
10104 SCIP* scip, /**< SCIP data structure */
10105 SCIP_CONSDATA* consdata, /**< linear constraint data */
10106 SCIP_Real* scale, /**< pointer to store the scaling factor between the constraint and the
10107 * objective function */
10108 SCIP_Real* offset /**< pointer to store the offset of the objective function resulting by
10109 * this constraint */
10110 )
10111{
10112 SCIP_VAR** vars;
10113 SCIP_VAR* var;
10115 SCIP_Bool negated;
10116 int nvars;
10117 int v;
10118
10119 vars = consdata->vars;
10120 nvars = consdata->nvars;
10121
10122 assert(vars != NULL);
10123
10124 for( v = 0; v < nvars; ++v )
10125 {
10126 negated = FALSE;
10127 var = vars[v];
10128 assert(var != NULL);
10129
10130 if( SCIPvarIsNegated(var) )
10131 {
10132 negated = TRUE;
10134 assert(var != NULL);
10135 }
10136
10138
10139 /* if a variable has a zero objective coefficient the linear constraint is not a subset of the objective
10140 * function
10141 */
10142 if( SCIPisZero(scip, objval) )
10143 return FALSE;
10144 else
10145 {
10146 SCIP_Real val;
10147
10148 val = consdata->vals[v];
10149
10150 if( negated )
10151 {
10152 if( v == 0 )
10153 {
10154 /* the first variable defines the scale */
10155 (*scale) = val / -objval;
10156
10157 (*offset) += val;
10158 }
10159 else if( SCIPisEQ(scip, -objval * (*scale), val) )
10160 (*offset) += val;
10161 else
10162 return FALSE;
10163 }
10164 else if( v == 0 )
10165 {
10166 /* the first variable defines the scale */
10167 (*scale) = val / objval;
10168 }
10169 else if( !SCIPisEQ(scip, objval * (*scale), val) )
10170 return FALSE;
10171 }
10172 }
10173
10174 return TRUE;
10175}
10176
10177/** check if the linear equality constraint is equal to a subset of the objective function; if so we can remove the
10178 * objective coefficients and add an objective offset
10179 */
10180static
10182 SCIP* scip, /**< SCIP data structure */
10183 SCIP_CONS* cons, /**< linear equation constraint */
10184 SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10185 )
10186{
10187 SCIP_CONSDATA* consdata;
10188 SCIP_Real offset;
10189 SCIP_Real scale;
10190 SCIP_Bool applicable;
10191 int nobjvars;
10192 int nvars;
10193 int v;
10194
10195 assert(scip != NULL);
10196 assert(cons != NULL);
10197 assert(conshdlrdata != NULL);
10198
10199 consdata = SCIPconsGetData(cons);
10200 assert(consdata != NULL);
10201 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
10202
10203 nvars = consdata->nvars;
10204 nobjvars = SCIPgetNObjVars(scip);
10205
10206 /* check if the linear equality constraints does not have more variables than the objective function */
10207 if( nvars > nobjvars || nvars == 0 )
10208 return SCIP_OKAY;
10209
10210 /* check for allowance of algorithm */
10211 if( (nvars < nobjvars && !conshdlrdata->detectpartialobjective) ||
10212 (nvars == nobjvars && (!conshdlrdata->detectcutoffbound || !conshdlrdata->detectlowerbound)) )
10213 return SCIP_OKAY;
10214
10215 offset = consdata->rhs;
10216 scale = 1.0;
10217
10218 /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10219 applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10220
10221 if( applicable )
10222 {
10223 SCIP_VAR** vars;
10224
10225 vars = consdata->vars;
10226 assert(vars != NULL);
10227
10228 offset /= scale;
10229
10230 SCIPdebugMsg(scip, "linear equality constraint <%s> == %g (offset %g) is a subset of the objective function\n",
10231 SCIPconsGetName(cons), consdata->rhs, offset);
10232
10233 /* make equality a model constraint to ensure optimality in this direction */
10236
10237 /* set all objective coefficient to zero */
10238 for( v = 0; v < nvars; ++v )
10239 {
10240 SCIP_CALL( SCIPchgVarObj(scip, vars[v], 0.0) );
10241 }
10242
10243 /* add an objective offset */
10244 SCIP_CALL( SCIPaddObjoffset(scip, offset) );
10245 }
10246
10247 return SCIP_OKAY;
10248}
10249
10250/** updates the cutoff if the given primal bound (which is implied by the given constraint) is better */
10251static
10253 SCIP* scip, /**< SCIP data structure */
10254 SCIP_CONS* cons, /**< constraint */
10255 SCIP_Real primalbound /**< feasible primal bound */
10256 )
10257{
10258 SCIP_Real cutoffbound;
10259
10260 /* increase the cutoff bound value by an epsilon to ensue that solution with the value of the cutoff bound are still
10261 * accepted
10262 */
10263 cutoffbound = primalbound + SCIPcutoffbounddelta(scip);
10264
10265 if( cutoffbound < SCIPgetCutoffbound(scip) )
10266 {
10267 SCIPdebugMsg(scip, "update cutoff bound <%g>\n", cutoffbound);
10268
10269 SCIP_CALL( SCIPupdateCutoffbound(scip, cutoffbound) );
10270 }
10271 else
10272 {
10273 SCIP_CONSDATA* consdata;
10274
10275 consdata = SCIPconsGetData(cons);
10276 assert(consdata != NULL);
10277
10278 /* we cannot disable the enforcement and propagation on ranged rows, because the cutoffbound could only have
10279 * resulted from one side
10280 */
10281 if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
10282 {
10283 /* in case the cutoff bound is worse then the currently known one, we additionally avoid enforcement and
10284 * propagation
10285 */
10288 }
10289 }
10290
10291 return SCIP_OKAY;
10292}
10293
10294/** check if the linear constraint is parallel to objective function; if so update the cutoff bound and avoid that the
10295 * constraint enters the LP by setting the initial and separated flag to FALSE
10296 */
10297static
10299 SCIP* scip, /**< SCIP data structure */
10300 SCIP_CONS* cons, /**< linear constraint */
10301 SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10302 )
10303{
10304 SCIP_CONSDATA* consdata;
10305 SCIP_Real offset;
10306 SCIP_Real scale;
10307 SCIP_Bool applicable;
10308 int nobjvars;
10309 int nvars;
10310
10311 assert(scip != NULL);
10312 assert(cons != NULL);
10313 assert(conshdlrdata != NULL);
10314
10315 consdata = SCIPconsGetData(cons);
10316 assert(consdata != NULL);
10317
10318 /* ignore equalities since these are covered by the method checkPartialObjective() */
10319 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10320 return SCIP_OKAY;
10321
10322 nvars = consdata->nvars;
10323 nobjvars = SCIPgetNObjVars(scip);
10324
10325 /* check if the linear inequality constraints has the same number of variables as the objective function and if the
10326 * initial and/or separated flag is set to FALSE
10327 */
10328 if( nvars != nobjvars || (!SCIPconsIsInitial(cons) && !SCIPconsIsSeparated(cons)) )
10329 return SCIP_OKAY;
10330
10331 offset = 0.0;
10332 scale = 1.0;
10333
10334 /* There are no variables in the objective function and in the constraint. Thus, the constraint is redundant or proves
10335 * infeasibility. Since we have a pure feasibility problem, we do not want to set a cutoff or lower bound.
10336 */
10337 if( nobjvars == 0 )
10338 return SCIP_OKAY;
10339
10340 /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10341 applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10342
10343 if( applicable )
10344 {
10345 SCIP_Bool rhsfinite = !SCIPisInfinity(scip, consdata->rhs);
10346 SCIP_Bool lhsfinite = !SCIPisInfinity(scip, -consdata->lhs);
10347
10348 assert(scale != 0.0);
10349
10350 if( scale > 0.0 )
10351 {
10352 if( conshdlrdata->detectcutoffbound && rhsfinite )
10353 {
10354 SCIP_Real primalbound;
10355
10356 primalbound = (consdata->rhs - offset) / scale;
10357
10358 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10359 SCIPconsGetName(cons), primalbound);
10360
10361 SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10362 }
10363
10364 if( conshdlrdata->detectlowerbound && lhsfinite )
10365 {
10366 SCIP_Real lowerbound;
10367
10368 lowerbound = (consdata->lhs - offset) / scale;
10369
10370 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10371 SCIPconsGetName(cons), lowerbound);
10372
10374 }
10375
10376 if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !lhsfinite)) ||
10377 (conshdlrdata->detectlowerbound && !rhsfinite) )
10378 {
10379 /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10382 }
10383 }
10384 else
10385 {
10386 if( conshdlrdata->detectlowerbound && rhsfinite )
10387 {
10388 SCIP_Real lowerbound;
10389
10390 lowerbound = (consdata->rhs - offset) / scale;
10391
10392 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10393 SCIPconsGetName(cons), lowerbound);
10394
10396 }
10397
10398 if( conshdlrdata->detectcutoffbound && lhsfinite )
10399 {
10400 SCIP_Real primalbound;
10401
10402 primalbound = (consdata->lhs - offset) / scale;
10403
10404 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10405 SCIPconsGetName(cons), primalbound);
10406
10407 SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10408 }
10409
10410 if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !rhsfinite)) ||
10411 (conshdlrdata->detectlowerbound && !lhsfinite) )
10412 {
10413 /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10416 }
10417 }
10418 }
10419
10420 return SCIP_OKAY;
10421}
10422
10423/** converts special equalities */
10424static
10426 SCIP* scip, /**< SCIP data structure */
10427 SCIP_CONS* cons, /**< linear constraint */
10428 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10429 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10430 int* nfixedvars, /**< pointer to count number of fixed variables */
10431 int* naggrvars, /**< pointer to count number of aggregated variables */
10432 int* ndelconss, /**< pointer to count number of deleted constraints */
10433 int* nchgvartypes /**< pointer to count number of changed variable types */
10434 )
10435{
10436 SCIP_CONSDATA* consdata;
10437
10438 assert(scip != NULL);
10439 assert(cons != NULL);
10440 assert(conshdlrdata != NULL);
10441 assert(cutoff != NULL);
10442 assert(nfixedvars != NULL);
10443 assert(naggrvars != NULL);
10444 assert(ndelconss != NULL);
10445
10446 consdata = SCIPconsGetData(cons);
10447 assert(consdata != NULL);
10448 assert(consdata->removedfixings);
10449
10450 /* do nothing on inequalities */
10451 if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10452 return SCIP_OKAY;
10453
10454 /* depending on the number of variables, call a special conversion method */
10455 if( consdata->nvars == 1 )
10456 {
10457 /* fix variable */
10458 SCIP_CALL( convertUnaryEquality(scip, cons, cutoff, nfixedvars, ndelconss) );
10459 }
10460 else if( consdata->nvars == 2 )
10461 {
10462 /* aggregate one of the variables */
10463 SCIP_CALL( convertBinaryEquality(scip, cons, cutoff, naggrvars, ndelconss) );
10464 }
10465 else
10466 {
10467 /* check if the equality is part of the objective function */
10468 SCIP_CALL( checkPartialObjective(scip, cons, conshdlrdata) );
10469
10470 /* try to multi-aggregate one of the variables */
10471 SCIP_CALL( convertLongEquality(scip, conshdlrdata, cons, cutoff, naggrvars, ndelconss, nchgvartypes) );
10472 }
10473
10474 return SCIP_OKAY;
10475}
10476
10477/** returns whether the linear sum of all variables/coefficients except the given one divided by the given value is always
10478 * integral
10479 */
10480static
10482 SCIP* scip, /**< SCIP data structure */
10483 SCIP_CONSDATA* consdata, /**< linear constraint */
10484 int pos, /**< position of variable to be left out */
10485 SCIP_Real val /**< value to divide the coefficients by */
10486 )
10487{
10488 int v;
10489
10490 assert(scip != NULL);
10491 assert(consdata != NULL);
10492 assert(0 <= pos && pos < consdata->nvars);
10493
10494 for( v = 0; v < consdata->nvars; ++v )
10495 {
10496 if( v != pos && (!SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v]/val)) )
10497 return FALSE;
10498 }
10499
10500 return TRUE;
10501}
10502
10503/** 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$,
10504 * 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$
10505 */
10506static
10508 SCIP* scip, /**< SCIP data structure */
10509 SCIP_Real side, /**< lhs or rhs */
10510 SCIP_Real val, /**< coefficient */
10511 SCIP_Real minresactivity, /**< minimal residual activity */
10512 SCIP_Real maxresactivity, /**< maximal residual activity */
10513 SCIP_Real* minval, /**< pointer to store calculated minval */
10514 SCIP_Real* maxval /**< pointer to store calculated maxval */
10515 )
10516{
10517 assert(scip != NULL);
10518 assert(minval != NULL);
10519 assert(maxval != NULL);
10520
10521 if( val > 0.0 )
10522 {
10523 if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10524 *minval = -maxresactivity;
10525 else
10526 *minval = (side - maxresactivity)/val;
10527
10528 if( SCIPisInfinity(scip, ABS(minresactivity)) )
10529 *maxval = -minresactivity;
10530 else
10531 *maxval = (side - minresactivity)/val;
10532 }
10533 else
10534 {
10535 if( SCIPisInfinity(scip, ABS(minresactivity)) )
10536 *minval = minresactivity;
10537 else
10538 *minval = (side - minresactivity)/val;
10539
10540 if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10541 *maxval = maxresactivity;
10542 else
10543 *maxval = (side - maxresactivity)/val;
10544 }
10545}
10546
10547
10548/** applies dual presolving for variables that are locked only once in a direction, and this locking is due to a
10549 * linear inequality
10550 */
10551static
10553 SCIP* scip, /**< SCIP data structure */
10554 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10555 SCIP_CONS* cons, /**< linear constraint */
10556 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10557 int* nfixedvars, /**< pointer to count number of fixed variables */
10558 int* naggrvars, /**< pointer to count number of aggregated variables */
10559 int* ndelconss, /**< pointer to count number of deleted constraints */
10560 int* nchgvartypes /**< pointer to count number of changed variable types */
10561 )
10562{
10563 SCIP_CONSDATA* consdata;
10564 SCIP_Bool lhsexists;
10565 SCIP_Bool rhsexists;
10566 SCIP_Bool bestisint;
10567 SCIP_Bool bestislhs;
10568 SCIP_Real minabsval;
10569 SCIP_Real maxabsval;
10570 int bestpos;
10571 int i;
10572 int maxotherlocks;
10573
10574 assert(scip != NULL);
10575 assert(cons != NULL);
10576 assert(cutoff != NULL);
10577 assert(nfixedvars != NULL);
10578 assert(naggrvars != NULL);
10579 assert(ndelconss != NULL);
10580
10581 /* only process checked constraints (for which the locks are increased);
10582 * otherwise we would have to check for variables with nlocks == 0, and these are already processed by the
10583 * dualfix presolver
10584 */
10585 if( !SCIPconsIsChecked(cons) )
10586 return SCIP_OKAY;
10587
10588 consdata = SCIPconsGetData(cons);
10589 assert(consdata != NULL);
10590
10591 lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
10592 rhsexists = !SCIPisInfinity(scip, consdata->rhs);
10593
10594 /* search for a single-locked variable which can be multi-aggregated; if a valid continuous variable was found, we
10595 * can use it safely for aggregation and break the search loop
10596 */
10597 bestpos = -1;
10598 bestisint = TRUE;
10599 bestislhs = FALSE;
10600
10601 /* We only want to multi-aggregate variables, if they appear in maximal one additional constraint,
10602 * everything else would produce fill-in. Exceptions:
10603 * - If there are only two variables in the constraint from which the multi-aggregation arises, no fill-in will be
10604 * produced.
10605 * - If there are three variables in the constraint, multi-aggregation in three additional constraints will remove
10606 * six nonzeros (three from the constraint and the three entries of the multi-aggregated variable) and add
10607 * six nonzeros (two variables per substitution).
10608 * - If there at most four variables in the constraint, multi-aggregation in two additional constraints will remove
10609 * six nonzeros (four from the constraint and the two entries of the multi-aggregated variable) and add
10610 * six nonzeros (three variables per substitution). God exists!
10611 */
10612 if( consdata->nvars <= 2 )
10613 maxotherlocks = INT_MAX;
10614 else if( consdata->nvars == 3 )
10615 maxotherlocks = 3;
10616 else if( consdata->nvars == 4 )
10617 maxotherlocks = 2;
10618 else
10619 maxotherlocks = 1;
10620
10621 /* if this constraint has both sides, it also provides a lock for the other side and thus we can allow one more lock */
10622 if( lhsexists && rhsexists && maxotherlocks < INT_MAX )
10623 maxotherlocks++;
10624
10625 minabsval = SCIPinfinity(scip);
10626 maxabsval = -1.0;
10627 for( i = 0; i < consdata->nvars && bestisint; ++i )
10628 {
10629 SCIP_VAR* var;
10630 SCIP_Bool isint;
10631 SCIP_Real val;
10632 SCIP_Real absval;
10633 SCIP_Real obj;
10634 SCIP_Real lb;
10635 SCIP_Real ub;
10636 SCIP_Bool agglhs;
10637 SCIP_Bool aggrhs;
10638
10639 val = consdata->vals[i];
10640 absval = REALABS(val);
10641
10642 /* calculate minimal and maximal absolute value */
10643 if( absval < minabsval )
10644 minabsval = absval;
10645 if( absval > maxabsval )
10646 maxabsval = absval;
10647
10648 /* do not try to multi aggregate, when numerical bad */
10649 if( maxabsval / minabsval > conshdlrdata->maxdualmultaggrquot )
10650 return SCIP_OKAY;
10651
10652 var = consdata->vars[i];
10654
10655 /* if we already found a candidate, skip integers */
10656 if( bestpos >= 0 && isint )
10657 continue;
10658
10659 /* better do not multi-aggregate binary variables, since most plugins rely on their binary variables to be either
10660 * active, fixed, or single-aggregated with another binary variable
10661 */
10662 if( SCIPvarIsBinary(var) && consdata->nvars > 2 )
10663 continue;
10664
10666 continue;
10667
10668 val = consdata->vals[i];
10670 lb = SCIPvarGetLbGlobal(var);
10671 ub = SCIPvarGetUbGlobal(var);
10672
10673 /* lhs <= a_0 * x_0 + a_1 * x_1 + ... + a_{n-1} * x_{n-1} <= rhs
10674 *
10675 * a_i >= 0, c_i >= 0, lhs exists, nlocksdown(x_i) == 1:
10676 * - constraint is the only one that forbids fixing the variable to its lower bound
10677 * - 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
10678 *
10679 * a_i <= 0, c_i <= 0, lhs exists, nlocksup(x_i) == 1:
10680 * - constraint is the only one that forbids fixing the variable to its upper bound
10681 * - 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
10682 *
10683 * a_i >= 0, c_i <= 0, rhs exists, nlocksup(x_i) == 1:
10684 * - constraint is the only one that forbids fixing the variable to its upper bound
10685 * - 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
10686 *
10687 * a_i <= 0, c_i >= 0, rhs exists, nlocksdown(x_i) == 1:
10688 * - constraint is the only one that forbids fixing the variable to its lower bound
10689 * - 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
10690 *
10691 * but: all this is only applicable, if the aggregated value is inside x_i's bounds for all possible values
10692 * of all x_j
10693 * furthermore: we only want to apply this, if no fill-in will be produced
10694 */
10695 agglhs = lhsexists
10697 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10699 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10700 aggrhs = rhsexists
10702 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10704 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10705 if( agglhs || aggrhs )
10706 {
10707 SCIP_Real minresactivity;
10708 SCIP_Real maxresactivity;
10709 SCIP_Real minval;
10710 SCIP_Real maxval;
10711 SCIP_Bool ismintight;
10712 SCIP_Bool ismaxtight;
10713 SCIP_Bool isminsettoinfinity;
10714 SCIP_Bool ismaxsettoinfinity;
10715
10716 /* calculate bounds for \sum_{j \neq i} a_j * x_j */
10717 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
10718 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
10719 assert(SCIPisLE(scip, minresactivity, maxresactivity));
10720
10721 /* We called consdataGetActivityResiduals() saying that we do not need a good relaxation,
10722 * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
10723 * This is needed, because we do not want to rely on relaxed finite resactivities.
10724 */
10725 assert((ismintight || isminsettoinfinity) && (ismaxtight || ismaxsettoinfinity));
10726
10727 if( agglhs )
10728 {
10729 /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10730 calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10731
10732 assert(SCIPisLE(scip, minval, maxval));
10733 if( !SCIPisInfinity(scip, -minval) && SCIPisGE(scip, minval, lb)
10734 && !SCIPisInfinity(scip, maxval) && SCIPisLE(scip, maxval, ub) )
10735 {
10736 SCIP_Real oldmaxresactivity;
10737 SCIP_Real oldminresactivity;
10738 SCIP_Bool recalculated;
10739
10740 recalculated = FALSE;
10741 oldmaxresactivity = maxresactivity;
10742 oldminresactivity = minresactivity;
10743
10744 /* check minresactivity for reliability */
10745 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10746 {
10747 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10748 recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10749 isminsettoinfinity = TRUE; /* here it means only that it was even calculated */
10750 }
10751
10752 /* check maxresactivity for reliability */
10753 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10754 {
10755 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10756 recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10757 ismaxsettoinfinity = TRUE; /* here it means only that it was even calculated */
10758 }
10759
10760 /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10761 if( recalculated )
10762 {
10763 assert(SCIPisLE(scip, minresactivity, maxresactivity));
10764
10765 /* check again if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10766 calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10767
10768 assert(SCIPisLE(scip, minval, maxval));
10769 }
10770
10771 if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10772 {
10773 /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10774 * in the multi-aggregation
10775 */
10776 if( !isint || (SCIPisIntegral(scip, consdata->lhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10777 {
10778 bestpos = i;
10779 bestisint = isint;
10780 bestislhs = TRUE;
10781 continue; /* no need to also look at the right hand side */
10782 }
10783 }
10784 }
10785 }
10786
10787 if( aggrhs )
10788 {
10789 /* check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10790 calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10791
10792 assert(SCIPisLE(scip,minval,maxval));
10793 if( !SCIPisInfinity(scip, -minval) && SCIPisGE(scip, minval, lb)
10794 && !SCIPisInfinity(scip, maxval) && SCIPisLE(scip, maxval, ub) )
10795 {
10796 SCIP_Real oldmaxresactivity;
10797 SCIP_Real oldminresactivity;
10798 SCIP_Bool recalculated;
10799
10800 recalculated = FALSE;
10801 oldmaxresactivity = maxresactivity;
10802 oldminresactivity = minresactivity;
10803
10804 /* check minresactivity for reliability */
10805 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10806 {
10807 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10808 recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10809 }
10810
10811 /* check maxresactivity for reliability */
10812 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10813 {
10814 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10815 recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10816 }
10817
10818 /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10819 if( recalculated )
10820 {
10821 /* check again if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10822 calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10823 assert(SCIPisLE(scip,minval,maxval));
10824 }
10825
10826 if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10827 {
10828 /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10829 * in the multi-aggregation
10830 */
10831 if( !isint || (SCIPisIntegral(scip, consdata->rhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10832 {
10833 bestpos = i;
10834 bestisint = isint;
10835 bestislhs = FALSE;
10836 }
10837 }
10838 }
10839 }
10840 }
10841 }
10842
10843 if( bestpos >= 0 )
10844 {
10845 SCIP_VAR** aggrvars;
10846 SCIP_Real* aggrcoefs;
10847 SCIP_Real aggrconst;
10848 SCIP_VAR* bestvar;
10849 SCIP_Real bestval;
10850 int naggrs;
10851 int j;
10852 SCIP_Bool infeasible;
10853 SCIP_Bool aggregated;
10854
10855 assert(!bestislhs || lhsexists);
10856 assert(bestislhs || rhsexists);
10857
10858 bestvar = consdata->vars[bestpos];
10859 bestval = consdata->vals[bestpos];
10860 assert(bestisint == SCIPvarIsNonimpliedIntegral(bestvar));
10861
10862 /* allocate temporary memory */
10863 SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars-1) );
10864 SCIP_CALL( SCIPallocBufferArray(scip, &aggrcoefs, consdata->nvars-1) );
10865
10866 /* set up the multi-aggregation */
10868 SCIPdebugMsg(scip, "linear constraint <%s> (dual): multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(bestvar));
10869 naggrs = 0;
10870
10871 for( j = 0; j < consdata->nvars; ++j )
10872 {
10873 if( j != bestpos )
10874 {
10875 aggrvars[naggrs] = consdata->vars[j];
10876 aggrcoefs[naggrs] = -consdata->vals[j]/consdata->vals[bestpos];
10877
10878 SCIPdebugMsgPrint(scip, " %+.15g<%s>", aggrcoefs[naggrs], SCIPvarGetName(aggrvars[naggrs]));
10879
10880 /* do not try to multi aggregate, when numerical bad */
10881 if( SCIPisZero(scip, aggrcoefs[naggrs]) )
10882 {
10883 SCIPdebugMsg(scip, "do not perform multi-aggregation: too large aggregation coefficients\n");
10884
10885 /* free temporary memory */
10886 SCIPfreeBufferArray(scip, &aggrcoefs);
10887 SCIPfreeBufferArray(scip, &aggrvars);
10888
10889 return SCIP_OKAY;
10890 }
10891
10892 if( bestisint )
10893 {
10894 /* coefficient must be integral: round it to exact integral value */
10895 assert(SCIPisIntegral(scip, aggrcoefs[naggrs]));
10896 aggrcoefs[naggrs] = SCIPfloor(scip, aggrcoefs[naggrs]+0.5);
10897 }
10898
10899 naggrs++;
10900 }
10901 }
10902
10903 aggrconst = (bestislhs ? consdata->lhs/bestval : consdata->rhs/bestval);
10904 SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g]\n", aggrconst, SCIPvarGetName(bestvar),
10905 SCIPvarGetLbGlobal(bestvar), SCIPvarGetUbGlobal(bestvar));
10906 assert(naggrs == consdata->nvars-1);
10907
10908 /* right hand side must be integral: round it to exact integral value */
10909 if( bestisint )
10910 {
10911 assert(SCIPisIntegral(scip, aggrconst));
10912 aggrconst = SCIPfloor(scip, aggrconst+0.5);
10913 }
10914
10915 aggregated = FALSE;
10916 infeasible = FALSE;
10917
10918 /* perform the multi-aggregation */
10919 SCIP_CALL( SCIPmultiaggregateVar(scip, bestvar, naggrs, aggrvars, aggrcoefs, aggrconst, &infeasible, &aggregated) );
10920
10921 /** @todo handle this case properly with weak and strong implied integrality */
10922 /* if the multi-aggregated bestvar is enforced but not strongly implied integral, we need to convert implied
10923 * integral to integer variables because integrality of the multi-aggregated variable must hold
10924 */
10925 if( !infeasible && aggregated && SCIPvarGetType(bestvar) != SCIP_VARTYPE_CONTINUOUS && SCIPvarGetImplType(bestvar) != SCIP_IMPLINTTYPE_STRONG )
10926 {
10927 SCIP_Bool infeasiblevartypechg = FALSE;
10928
10929 for( j = 0; j < naggrs; ++j )
10930 {
10931 /* if the multi-aggregation was not infeasible, then setting implied integral to integer should not
10932 * lead to infeasibility
10933 */
10935 {
10936 if( SCIPvarGetType(aggrvars[j]) == SCIP_VARTYPE_CONTINUOUS )
10937 {
10938 SCIP_CALL( SCIPchgVarType(scip, aggrvars[j], SCIP_VARTYPE_INTEGER, &infeasiblevartypechg) );
10939 assert(!infeasiblevartypechg);
10940 }
10941 SCIP_CALL( SCIPchgVarImplType(scip, aggrvars[j], SCIP_IMPLINTTYPE_NONE, &infeasiblevartypechg) );
10942 assert(!infeasiblevartypechg);
10943 (*nchgvartypes)++;
10944 }
10945 }
10946 }
10947
10948 /* free temporary memory */
10949 SCIPfreeBufferArray(scip, &aggrcoefs);
10950 SCIPfreeBufferArray(scip, &aggrvars);
10951
10952 /* check for infeasible aggregation */
10953 if( infeasible )
10954 {
10955 SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
10956 *cutoff = TRUE;
10957 return SCIP_OKAY;
10958 }
10959
10960 /* delete the constraint, if the aggregation was successful */
10961 if( aggregated )
10962 {
10963 SCIP_CALL( SCIPdelCons(scip, cons) );
10964
10965 if( !consdata->upgraded )
10966 (*ndelconss)++;
10967 (*naggrvars)++;
10968 }
10969 else
10970 {
10971 SCIPdebugMsg(scip, "aggregation non successful!\n");
10972 }
10973 }
10974
10975 return SCIP_OKAY;
10976}
10977
10978#define BINWEIGHT 1
10979#define INTWEIGHT 4
10980#define CONTWEIGHT 8
10981
10982/** gets weight for variable in a "weighted number of variables" sum */
10983static
10985 SCIP_VAR* var /**< variable to get weight for */
10986 )
10987{
10989 return INTWEIGHT;
10990
10991 switch( SCIPvarGetType(var) )
10992 {
10994 return BINWEIGHT;
10996 return INTWEIGHT;
10998 return CONTWEIGHT;
10999 default:
11000 SCIPerrorMessage("unknown variable type\n");
11001 SCIPABORT();
11002 return 0; /*lint !e527*/
11003 } /*lint !e788*/
11004}
11005
11006/** tries to aggregate variables in equations a^Tx = lhs
11007 * in case there are at most two binary variables with an odd coefficient and all other
11008 * variables are not continuous and have an even coefficient then:
11009 * - exactly one odd binary variables
11010 * this binary variables y can be fixed to 0 if the lhs is even and to 1 if the lhs is odd
11011 * - lhs is odd -> y = 1
11012 * - lhs is even -> y = 0
11013 * - exactly two odd binary variables
11014 * aggregate the two binary variables with odd coefficient
11015 * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11016 * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11017 */
11018static
11020 SCIP* scip, /**< SCIP data structure */
11021 SCIP_CONS* cons, /**< linear constraint */
11022 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
11023 int* nfixedvars, /**< pointer to count number of fixed variables */
11024 int* naggrvars /**< pointer to count number of aggregated variables */
11025 )
11026{ /*lint --e{715}*/
11027 SCIP_CONSDATA* consdata;
11028 SCIP_Bool success;
11029
11030 assert( scip != NULL );
11031 assert( cons != NULL );
11032
11033 consdata = SCIPconsGetData(cons);
11034 assert( consdata != NULL );
11035
11036 /* check if the linear constraint is an equation with integral right hand side */
11037 if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) || !SCIPisIntegral(scip, consdata->lhs) )
11038 return SCIP_OKAY;
11039
11040 /* try to fix and aggregated variables until nothing is possible anymore */
11041 do
11042 {
11043 int v;
11044 int nvars;
11045 SCIP_VAR** vars;
11046 SCIP_Real* vals;
11047 SCIP_Real lhs;
11048 SCIP_Bool lhsodd;
11049
11050 SCIP_Bool infeasible;
11051 SCIP_Bool fixed;
11052 SCIP_Bool aggregated;
11053 SCIP_Bool redundant;
11054
11055 SCIP_VAR* var1;
11056 SCIP_VAR* var2;
11057 int noddvars;
11058
11059 success = FALSE;
11060
11061 lhs = consdata->lhs;
11062 vars = consdata->vars;
11063 vals = consdata->vals;
11064 nvars = consdata->nvars;
11065
11066 assert( !SCIPisInfinity(scip, ABS(lhs)) );
11067
11068 var1 = NULL;
11069 var2 = NULL;
11070 noddvars = 0;
11071
11072 /* search for binary variables with an odd coefficient */
11073 for( v = 0; v < nvars && noddvars < 3; ++v )
11074 {
11075 SCIP_Longint val;
11076
11077 /* all coefficients and variables have to be integral */
11078 if( !SCIPvarIsIntegral(vars[v]) || !SCIPisIntegral(scip, vals[v]) )
11079 return SCIP_OKAY;
11080
11081 val = (SCIP_Longint)SCIPfeasFloor(scip, vals[v]);
11082 if( val % 2 != 0 )
11083 {
11084 /* the odd values have to belong to binary variables */
11085 if( !SCIPvarIsBinary(vars[v]) )
11086 return SCIP_OKAY;
11087
11088 if( noddvars == 0 )
11089 var1 = vars[v];
11090 else
11091 var2 = vars[v];
11092
11093 noddvars++;
11094 }
11095 }
11096
11097 /* check lhs is odd or even */
11098 lhsodd = (((SCIP_Longint)SCIPfeasFloor(scip, lhs)) % 2 != 0);
11099
11100 if( noddvars == 1 )
11101 {
11102 assert( var1 != NULL );
11103
11104 SCIPdebugMsg(scip, "linear constraint <%s>: try fixing variable <%s> to <%g>\n",
11105 SCIPconsGetName(cons), SCIPvarGetName(var1), lhsodd ? 1.0 : 0.0);
11106
11107 SCIP_CALL( SCIPfixVar(scip, var1, lhsodd? 1.0 : 0.0, &infeasible, &fixed) );
11108
11109 /* check for infeasibility of fixing */
11110 if( infeasible )
11111 {
11112 SCIPdebugMsg(scip, " -> infeasible fixing\n");
11113 *cutoff = TRUE;
11114 return SCIP_OKAY;
11115 }
11116
11117 if( fixed )
11118 {
11119 SCIPdebugMsg(scip, " -> feasible fixing\n");
11120 (*nfixedvars)++;
11121 success = TRUE;
11122 }
11123 }
11124 else if( noddvars == 2 )
11125 {
11126 assert( var1 != NULL );
11127 assert( var2 != NULL );
11128
11129 /* aggregate the two variables with odd coefficient
11130 * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11131 * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11132 */
11133 SCIPdebugMsg(scip, "linear constraint <%s>: try aggregation of variables <%s> and <%s>\n",
11134 SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
11135
11136 SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, lhsodd ? 1.0 : -1.0,
11137 lhsodd ? 1.0 : 0.0, &infeasible, &redundant, &aggregated) );
11138
11139 /* check for infeasibility of aggregation */
11140 if( infeasible )
11141 {
11142 SCIPdebugMsg(scip, " -> infeasible aggregation\n");
11143 *cutoff = TRUE;
11144 return SCIP_OKAY;
11145 }
11146
11147 /* count the aggregation */
11148 if( aggregated )
11149 {
11150 SCIPdebugMsg(scip, " -> feasible aggregation\n");
11151 (*naggrvars)++;
11152 success = TRUE;
11153 }
11154 }
11155
11156 if( success )
11157 {
11158 /* apply fixings and aggregation to successfully rerun this presolving step */
11159 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
11160
11161 if( infeasible )
11162 {
11163 SCIPdebugMsg(scip, " -> infeasible fixing\n");
11164 *cutoff = TRUE;
11165 return SCIP_OKAY;
11166 }
11167
11168 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
11169
11170 if( infeasible )
11171 {
11172 SCIPdebugMsg(scip, " -> infeasible normalization\n");
11173 *cutoff = TRUE;
11174 return SCIP_OKAY;
11175 }
11176 }
11177 }
11178 while( success && consdata->nvars >= 1 );
11179
11180 return SCIP_OKAY;
11181}
11182
11183
11184
11185/** sorting method for constraint data, compares two variables on given indices, continuous variables will be sorted to
11186 * the end and for all other variables the sortation will be in non-increasing order of their absolute value of the
11187 * coefficients
11188 */
11189static
11191{ /*lint --e{715}*/
11192 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
11193 SCIP_Real value;
11194
11195 assert(consdata != NULL);
11196 assert(0 <= ind1 && ind1 < consdata->nvars);
11197 assert(0 <= ind2 && ind2 < consdata->nvars);
11198
11199 SCIP_Bool varcont1 = !SCIPvarIsIntegral(consdata->vars[ind1]);
11200 SCIP_Bool varcont2 = !SCIPvarIsIntegral(consdata->vars[ind2]);
11201
11202 if( varcont1 )
11203 {
11204 /* continuous variables will be sorted to the back */
11205 if( varcont1 != varcont2 )
11206 return +1;
11207 /* both variables are continuous */
11208 else
11209 return 0;
11210 }
11211 /* continuous variables will be sorted to the back */
11212 else if( varcont2 )
11213 return -1;
11214
11215 value = REALABS(consdata->vals[ind2]) - REALABS(consdata->vals[ind1]);
11216
11217 /* for all non-continuous variables, the variables are sorted after decreasing absolute coefficients */
11218 return (value > 0 ? +1 : (value < 0 ? -1 : 0));
11219}
11220
11221/** tries to simplify coefficients in ranged row of the form lhs <= a^Tx <= rhs
11222 *
11223 * 1. lhs <= a^Tx <= rhs, x binary, lhs > 0, forall a_i >= lhs, a_i <= rhs, and forall pairs a_i + a_j > rhs,
11224 * then we can change this constraint to 1^Tx = 1
11225 */
11226static
11228 SCIP* scip, /**< SCIP data structure */
11229 SCIP_CONS* cons, /**< linear constraint */
11230 int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11231 int* nchgsides /**< pointer to store the amount of changed sides */
11232 )
11233{
11234 SCIP_CONSDATA* consdata;
11235 SCIP_VAR** vars;
11236 SCIP_Real* vals;
11237 SCIP_Real minval;
11238 SCIP_Real secondminval;
11239 SCIP_Real maxval;
11240 SCIP_Real lhs;
11241 SCIP_Real rhs;
11242 int nvars;
11243 int v;
11244
11245 /* we must not change a modifiable constraint in any way */
11246 if( SCIPconsIsModifiable(cons) )
11247 return SCIP_OKAY;
11248
11249 if( SCIPconsIsDeleted(cons) )
11250 return SCIP_OKAY;
11251
11252 consdata = SCIPconsGetData(cons);
11253 assert(consdata != NULL);
11254
11255 nvars = consdata->nvars;
11256
11257 /* do not check empty or bound-constraints */
11258 if( nvars < 2 )
11259 return SCIP_OKAY;
11260
11261 lhs = consdata->lhs;
11262 rhs = consdata->rhs;
11263 assert(!SCIPisInfinity(scip, -lhs));
11264 assert(!SCIPisInfinity(scip, rhs));
11265 assert(!SCIPisNegative(scip, rhs));
11266
11267 /* sides must be positive and different to detect set partition */
11268 if( !SCIPisPositive(scip, lhs) || !SCIPisLT(scip, lhs, rhs) )
11269 return SCIP_OKAY;
11270
11271 vals = consdata->vals;
11272 vars = consdata->vars;
11273 assert(vars != NULL);
11274 assert(vals != NULL);
11275
11276 minval = SCIP_INVALID;
11277 secondminval = SCIP_INVALID;
11278 maxval = -SCIP_INVALID;
11279
11280 for( v = nvars - 1; v >= 0; --v )
11281 {
11282 if( SCIPvarIsBinary(vars[v]) )
11283 {
11284 if( minval > vals[v] || minval == SCIP_INVALID ) /*lint !e777*/
11285 {
11286 secondminval = minval;
11287 minval = vals[v];
11288 }
11289 else if( secondminval > vals[v] || secondminval == SCIP_INVALID ) /*lint !e777*/
11290 secondminval = vals[v];
11291
11292 if( maxval < vals[v] || maxval == -SCIP_INVALID ) /*lint !e777*/
11293 maxval = vals[v];
11294 }
11295 else
11296 break;
11297 }
11298
11299 /* check if all variables are binary, we can choose one, and need to choose at most one */
11300 if( v == -1 && SCIPisGE(scip, minval, lhs) && SCIPisLE(scip, maxval, rhs)
11301 && SCIPisGT(scip, minval + secondminval, rhs) )
11302 {
11303 /* change all coefficients to 1.0 */
11304 for( v = nvars - 1; v >= 0; --v )
11305 {
11306 SCIP_CALL( chgCoefPos(scip, cons, v, 1.0) );
11307 }
11308 (*nchgcoefs) += nvars;
11309
11310 /* replace old right and left hand side with 1.0 */
11311 SCIP_CALL( chgRhs(scip, cons, 1.0) );
11312 SCIP_CALL( chgLhs(scip, cons, 1.0) );
11313 (*nchgsides) += 2;
11314 }
11315
11316 return SCIP_OKAY;
11317}
11318
11319/** tries to simplify coefficients and delete variables in constraints of the form lhs <= a^Tx <= rhs
11320 *
11321 * for both-sided constraints only @see rangedRowSimplify() will be called
11322 *
11323 * for one-sided constraints there are several different coefficient reduction steps which will be applied
11324 *
11325 * 1. We try to determine parts of the constraint which will not change anything on (in-)feasibility of the constraint
11326 *
11327 * e.g. 5x1 + 5x2 + 3z1 <= 8 => 3z1 is redundant if all x are binary and -2 < 3z1 <= 3
11328 *
11329 * 2. We try to remove redundant fractional parts in a constraint
11330 *
11331 * e.g. 5.2x1 + 5.1x2 + 3x3 <= 8.3 => will be changed to 5x1 + 5x2 + 3x3 <= 8 if all x are binary
11332 *
11333 * 3. We are using the greatest common divisor for further reductions
11334 *
11335 * e.g. 10x1 + 5y2 + 5x3 + 3x4 <= 15 => will be changed to 2x1 + y2 + x3 + x4 <= 3 if all xi are binary and y2 is
11336 * integral
11337 */
11338static
11340 SCIP* scip, /**< SCIP data structure */
11341 SCIP_CONS* cons, /**< linear constraint */
11342 int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11343 int* nchgsides, /**< pointer to store the amount of changed sides */
11344 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
11345 )
11346{
11347 SCIP_CONSDATA* consdata;
11348 SCIP_VAR** vars;
11349 SCIP_Real* vals;
11350 int* perm;
11351 SCIP_Real minactsub;
11352 SCIP_Real maxactsub;
11353 SCIP_Real siderest;
11354 SCIP_Real feastol;
11355 SCIP_Real newcoef;
11356 SCIP_Real absval;
11357 SCIP_Real minact;
11358 SCIP_Real maxact;
11359 SCIP_Real side;
11360 SCIP_Real lhs;
11361 SCIP_Real rhs;
11362 SCIP_Real lb;
11363 SCIP_Real ub;
11364 SCIP_Longint restcoef;
11365 SCIP_Longint oldgcd;
11366 SCIP_Longint rest;
11367 SCIP_Longint gcd;
11368 SCIP_Bool isminsettoinfinity;
11369 SCIP_Bool ismaxsettoinfinity;
11370 SCIP_Bool ismintight;
11371 SCIP_Bool ismaxtight;
11372 SCIP_Bool allcoefintegral;
11373 SCIP_Bool onlybin;
11374 SCIP_Bool hasrhs;
11375 SCIP_Bool haslhs;
11376 int oldnchgcoefs; /* cppcheck-suppress unassignedVariable */
11377 int oldnchgsides; /* cppcheck-suppress unassignedVariable */
11378 int foundbin;
11379 int candpos;
11380 int candpos2;
11381 int offsetv;
11382 int nvars;
11383 int v;
11384 int w;
11385
11386 assert(scip != NULL);
11387 assert(cons != NULL);
11388 assert(nchgcoefs != NULL);
11389 assert(nchgsides != NULL);
11390
11391 *infeasible = FALSE;
11392
11393 /* we must not change a modifiable constraint in any way */
11394 if( SCIPconsIsModifiable(cons) )
11395 return SCIP_OKAY;
11396
11397 if( SCIPconsIsDeleted(cons) )
11398 return SCIP_OKAY;
11399
11400 consdata = SCIPconsGetData(cons);
11401 assert(consdata != NULL);
11402
11403 nvars = consdata->nvars;
11404
11405 /* do not check empty or bound-constraints */
11406 if( nvars <= 2 )
11407 return SCIP_OKAY;
11408
11409 /* update maximal activity delta if necessary */
11410 if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
11412
11413 assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
11414 assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
11415 checkMaxActivityDelta(scip, consdata);
11416
11417 /* @todo the following might be too hard, check which steps can be applied and what code must be corrected
11418 * accordingly
11419 */
11420 /* can only work with valid non-infinity activities per variable */
11421 if( SCIPisInfinity(scip, consdata->maxactdelta) )
11422 return SCIP_OKAY;
11423
11424 /* @todo: change the following: due to vartype changes, the status of the normalization can be wrong, need an event
11425 * but the eventsystem seems to be full
11426 */
11427 consdata->normalized = FALSE;
11428
11429 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11430 assert(nvars == consdata->nvars);
11431
11432 if( *infeasible )
11433 return SCIP_OKAY;
11434
11435 if( !consdata->normalized )
11436 return SCIP_OKAY;
11437
11438 lhs = consdata->lhs;
11439 rhs = consdata->rhs;
11440 assert(!SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs));
11441 assert(!SCIPisNegative(scip, rhs));
11442
11443 if( !SCIPisInfinity(scip, -lhs) )
11444 haslhs = TRUE;
11445 else
11446 haslhs = FALSE;
11447
11448 if( !SCIPisInfinity(scip, rhs) )
11449 hasrhs = TRUE;
11450 else
11451 hasrhs = FALSE;
11452
11453 /* @todo extend both-sided simplification */
11454 if( haslhs && hasrhs )
11455 {
11456 SCIP_CALL( rangedRowSimplify(scip, cons, nchgcoefs, nchgsides ) );
11457
11458 return SCIP_OKAY;
11459 }
11460 assert(haslhs != hasrhs);
11461
11462 /* if we have a normalized inequality (not ranged) the one side should be positive, @see normalizeCons() */
11463 assert(!hasrhs || !SCIPisNegative(scip, rhs));
11464 assert(!haslhs || !SCIPisNegative(scip, lhs));
11465
11466 /* get temporary memory to store the sorted permutation */
11468
11469 /* call sorting method, order continuous variables to the end and all other variables after non-increasing absolute
11470 * value of their coefficients
11471 */
11472 SCIPsort(perm, consdataCompSim, (void*)consdata, nvars);
11473
11474 /* perform sorting after permutation array */
11475 permSortConsdata(consdata, perm, nvars);
11476 consdata->indexsorted = FALSE;
11477 consdata->coefsorted = FALSE;
11478
11479 vars = consdata->vars;
11480 vals = consdata->vals;
11481 assert(vars != NULL);
11482 assert(vals != NULL);
11483 assert(!consdata->validmaxabsval || SCIPisFeasEQ(scip, consdata->maxabsval, REALABS(vals[0])) || !SCIPvarIsIntegral(vars[nvars - 1]));
11484
11485 /* free temporary memory */
11486 SCIPfreeBufferArray(scip, &perm);
11487
11488 /* only check constraints with at least two non continuous variables */
11489 if( !SCIPvarIsIntegral(vars[1]) )
11490 return SCIP_OKAY;
11491
11492 /* do not process constraints when all coefficients are 1.0 */
11493 if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) && ((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs))) )
11494 return SCIP_OKAY;
11495
11496 feastol = SCIPfeastol(scip);
11497
11498 SCIPdebugMsg(scip, "starting simplification of coefficients\n");
11500
11501 /* get global activities */
11502 consdataGetGlbActivityBounds(scip, consdata, FALSE, &minact, &maxact,
11503 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
11504
11505 /* cannot work with infinite activities */
11506 if( isminsettoinfinity || ismaxsettoinfinity )
11507 return SCIP_OKAY;
11508
11509 assert(ismintight);
11510 assert(ismaxtight);
11511 assert(maxact > minact);
11512 assert(!SCIPisInfinity(scip, -minact));
11513 assert(!SCIPisInfinity(scip, maxact));
11514
11515 v = 0;
11516 offsetv = -1;
11517 side = haslhs ? lhs : rhs;
11518 minactsub = minact;
11519 maxactsub = maxact;
11520
11521 /* we now determine coefficients as large as the side of the constraint to retrieve a better reduction where we
11522 * do not need to look at the large coefficients
11523 *
11524 * e.g. all x are binary, z are positive integer
11525 * c1: +5x1 + 5x2 + 3x3 + 3x4 + x5 >= 5 (x5 is redundant and does not change (in-)feasibility of this constraint)
11526 * c2: +4x1 + 4x2 + 3x3 + 3x4 + x5 >= 4 (gcd (without the coefficient of x5) after the large coefficients is 3
11527 * c3: +30x1 + 29x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 30 (gcd (without the coefficient of x2) after the large coefficients is 7
11528 *
11529 * can be changed to
11530 *
11531 * c1: +6x1 + 6x2 + 3x3 + 3x4 >= 6 (will be changed to c1: +2x1 + 2x2 + x3 + x4 >= 2)
11532 * c2: +6x1 + 6x2 + 3x3 + 3x4 + 3x5 >= 6 (will be changed to c2: +2x1 + 2x2 + x3 + x4 + x5 >= 2)
11533 * c3: +28x1 + 28x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 28 (will be changed to c3: +4x1 + 4x2 + 2x3 + 2z1 + x5 + x6 <= 4)
11534 */
11535
11536 /* if the minimal activity is negative and we found more than one variable with a coefficient bigger than the left
11537 * hand side, we cannot apply the extra reduction step and need to reset v
11538 *
11539 * 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
11540 * coefficients due to the gcd on the "small" coefficients we would get 8x1 + 8x2 - 4x3 - 4x4 >= 8 were xi = 1
11541 * for all i is a solution
11542 *
11543 * also redundancy of variables would not be correctly determined in such a case
11544 */
11545 if( nvars > 2 && SCIPisEQ(scip, vals[0], side) && !SCIPisNegative(scip, minactsub) )
11546 {
11547 v = 1;
11548
11549 while( v < nvars && SCIPisEQ(scip, side, vals[v]) )
11550 {
11551 /* if we have integer variable with "side"-coefficients but also with a lower bound greater than 0 we stop this
11552 * extra step, which might have worked
11553 */
11554 if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
11555 {
11556 v = 0;
11557 break;
11558 }
11559
11560 ++v;
11561 }
11562
11563 /* easy and quick fix: if all coefficients were equal to the side, we cannot apply further simplifications */
11564 /* todo find numerically stable normalization conditions to scale this cons to have coefficients almost equal to 1 */
11565 if( v == nvars )
11566 return SCIP_OKAY;
11567
11568 /* cannot work with continuous variables which have a big coefficient */
11569 if( v > 0 && !SCIPvarIsIntegral(vars[v - 1]) )
11570 return SCIP_OKAY;
11571
11572 /* big negative coefficient, do not try to use the extra coefficient reduction step */
11573 if( SCIPisEQ(scip, side, -vals[v]) )
11574 v = 0;
11575
11576 /* all but one variable are processed or the next variable is continuous we cannot perform the extra coefficient
11577 * reduction
11578 */
11579 if( v == nvars - 1 || !SCIPvarIsIntegral(vars[v]) )
11580 v = 0;
11581
11582 if( v > 0 )
11583 {
11584 assert(v < nvars);
11585
11586 offsetv = v - 1;
11587
11588 for( w = 0; w < v; ++w )
11589 {
11590 lb = SCIPvarGetLbGlobal(vars[w]);
11591 ub = SCIPvarGetUbGlobal(vars[w]);
11592
11593 assert(vals[w] > 0);
11594
11595 /* update residual activities */
11596 maxactsub -= ub * vals[w];
11597 minactsub -= lb * vals[w];
11598 assert(maxactsub > minactsub);
11599 }
11600 }
11601 }
11602
11603 /* find and remove redundant variables which do not interact with the (in-)feasibility of this constraint
11604 *
11605 * e.g. let all x are binary and y1 is continuous with bounds [-3,1] then we can reduce
11606 *
11607 * 15x1 + 15x2 + 7x3 + 3x4 + y1 <= 26
11608 * to
11609 * 15x1 + 15x2 <= 26 <=> x1 + x2 <= 1
11610 */
11611 if( nvars > 2 && SCIPisIntegral(scip, vals[v]) )
11612 {
11613 SCIP_Bool redundant = FALSE;
11614 SCIP_Bool numericsok;
11615 SCIP_Bool rredundant;
11616 SCIP_Bool lredundant;
11617
11618 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11619 assert(gcd >= 1);
11620
11621 if( v == 0 )
11622 {
11623 lb = SCIPvarGetLbGlobal(vars[0]);
11624 ub = SCIPvarGetUbGlobal(vars[0]);
11625
11626 /* update residual activities */
11627 if( vals[0] > 0 )
11628 {
11629 maxactsub -= ub * vals[0];
11630 minactsub -= lb * vals[0];
11631 }
11632 else
11633 {
11634 maxactsub -= lb * vals[0];
11635 minactsub -= ub * vals[0];
11636 }
11637 assert(maxactsub > minactsub);
11638 ++v;
11639 }
11640
11641 siderest = -SCIP_INVALID;
11642 allcoefintegral = TRUE;
11643
11644 /* check if some variables always fit into the given constraint */
11645 for( ; v < nvars - 1; ++v )
11646 {
11647 if( !SCIPvarIsIntegral(vars[v]) )
11648 break;
11649
11650 if( !SCIPisIntegral(scip, vals[v]) )
11651 {
11652 allcoefintegral = FALSE;
11653 break;
11654 }
11655
11656 /* calculate greatest common divisor for all general and binary variables */
11657 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11658
11659 if( gcd == 1 )
11660 break;
11661
11662 lb = SCIPvarGetLbGlobal(vars[v]);
11663 ub = SCIPvarGetUbGlobal(vars[v]);
11664
11665 assert(!SCIPisInfinity(scip, -lb));
11666 assert(!SCIPisInfinity(scip, ub));
11667
11668 /* update residual activities */
11669 if( vals[v] > 0 )
11670 {
11671 maxactsub -= ub * vals[v];
11672 minactsub -= lb * vals[v];
11673 }
11674 else
11675 {
11676 maxactsub -= lb * vals[v];
11677 minactsub -= ub * vals[v];
11678 }
11679 assert(SCIPisGE(scip, maxactsub, minactsub));
11680
11681 if( hasrhs )
11682 {
11683 /* determine the remainder of the right hand side and the gcd */
11684 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11685 }
11686 else
11687 {
11688 /* determine the remainder of the left hand side and the gcd */
11689 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11690 if( SCIPisZero(scip, siderest) )
11691 siderest = gcd;
11692 }
11693
11694 rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
11695 lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11696
11697 /* early termination if the activities deceed the gcd */
11698 if( offsetv == -1 && (rredundant || lredundant) )
11699 {
11700 redundant = TRUE;
11701 break;
11702 }
11703 }
11704 assert(v < nvars || (offsetv >= 0 && gcd > 1));
11705
11706 if( !redundant )
11707 {
11708 if( hasrhs )
11709 {
11710 /* determine the remainder of the right hand side and the gcd */
11711 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11712 }
11713 else
11714 {
11715 /* determine the remainder of the left hand side and the gcd */
11716 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11717 if( SCIPisZero(scip, siderest) )
11718 siderest = gcd;
11719 }
11720 }
11721 else
11722 ++v;
11723
11724 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",
11725 v, nvars, minactsub, maxactsub, redundant, hasrhs, siderest, gcd, offsetv);
11726
11727 /* to avoid inconsistencies due to numerics, check that the full and partial activities have
11728 * reasonable absolute values */
11729 numericsok = REALABS(maxact) < MAXACTVAL && REALABS(maxactsub) < MAXACTVAL && REALABS(minact) < MAXACTVAL &&
11730 REALABS(minactsub) < MAXACTVAL;
11731
11732 rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
11733 lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11734
11735 /* check if we can remove redundant variables */
11736 if( v < nvars && numericsok && (redundant || (offsetv == -1 && (rredundant || lredundant))) )
11737 {
11738 SCIP_Real oldcoef;
11739
11740 /* double check the redundancy */
11741#ifndef NDEBUG
11742 SCIP_Real tmpminactsub = 0.0;
11743 SCIP_Real tmpmaxactsub = 0.0;
11744
11745 /* recompute residual activities */
11746 for( w = v; w < nvars; ++w )
11747 {
11748 lb = SCIPvarGetLbGlobal(vars[w]);
11749 ub = SCIPvarGetUbGlobal(vars[w]);
11750
11751 assert(!SCIPisInfinity(scip, -lb));
11752 assert(!SCIPisInfinity(scip, ub));
11753
11754 /* update residual activities */
11755 if( vals[w] > 0 )
11756 {
11757 tmpmaxactsub += ub * vals[w];
11758 tmpminactsub += lb * vals[w];
11759 }
11760 else
11761 {
11762 tmpmaxactsub += lb * vals[w];
11763 tmpminactsub += ub * vals[w];
11764 }
11765 assert(tmpmaxactsub >= tmpminactsub);
11766 }
11767
11768 if( hasrhs )
11769 {
11770 assert(offsetv == -1);
11771
11772 /* determine the remainder of the right hand side and the gcd */
11773 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11774 }
11775 else
11776 {
11777 /* determine the remainder of the left hand side and the gcd */
11778 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11779 if( SCIPisZero(scip, siderest) )
11780 siderest = gcd;
11781 }
11782
11783 /* is the redundancy really fulfilled */
11784 assert((hasrhs && SCIPisFeasLE(scip, tmpmaxactsub, siderest) && tmpminactsub > siderest - gcd) ||
11785 (haslhs && tmpmaxactsub < siderest && SCIPisFeasGE(scip, tmpminactsub, siderest - gcd)));
11786#endif
11787
11788 SCIPdebugMsg(scip, "removing %d last variables from constraint <%s>, because they never change anything on the feasibility of this constraint\n",
11789 nvars - v, SCIPconsGetName(cons));
11790
11791 /* remove redundant variables */
11792 for( w = nvars - 1; w >= v; --w )
11793 {
11794 SCIP_CALL( delCoefPos(scip, cons, w) );
11795 }
11796 (*nchgcoefs) += (nvars - v);
11797
11798 assert(w >= 0);
11799
11800 oldcoef = vals[w];
11801
11802 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11803 assert(vars == consdata->vars);
11804 assert(vals == consdata->vals);
11806
11807 if( *infeasible )
11808 return SCIP_OKAY;
11809
11810 /* compute new greatest common divisor due to normalization */
11811 gcd = (SCIP_Longint)(gcd / (oldcoef/vals[w]) + feastol);
11812 assert(gcd >= 1);
11813
11814 /* update side */
11815 if( hasrhs )
11816 {
11817 /* replace old with new right hand side */
11818 SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
11819 rhs = consdata->rhs;
11820 }
11821 else
11822 {
11823 if( SCIPisFeasGT(scip, oldcoef/vals[w], 1.0) )
11824 {
11825 SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
11826 lhs = consdata->lhs;
11827 }
11828 else
11829 assert(offsetv == -1 || SCIPisEQ(scip, vals[offsetv], consdata->lhs));
11830 }
11831 ++(*nchgsides);
11832
11833 assert(!hasrhs || !SCIPisNegative(scip, rhs));
11834 assert(!haslhs || !SCIPisNegative(scip, lhs));
11835
11836 /* get new constraint data */
11837 nvars = consdata->nvars;
11838 assert(nvars > 0);
11839
11840 allcoefintegral = TRUE;
11841
11842#ifndef NDEBUG
11843 /* check integrality */
11844 for( w = offsetv + 1; w < nvars; ++w )
11845 {
11846 assert(SCIPisIntegral(scip, vals[w]));
11847 }
11848#endif
11850 }
11851
11852 /* try to find a better gcd, when having large coefficients */
11853 if( offsetv >= 0 && gcd == 1 )
11854 {
11855 /* calculate greatest common divisor for all general variables */
11856 gcd = (SCIP_Longint)(REALABS(vals[nvars - 1]) + feastol);
11857
11858 if( gcd > 1 )
11859 {
11860 gcd = -1;
11861 candpos = -1;
11862
11863 for( v = nvars - 1; v > offsetv; --v )
11864 {
11865 assert(!SCIPisZero(scip, vals[v]));
11866 if( !SCIPvarIsIntegral(vars[v]) )
11867 break;
11868
11869 if( !SCIPisIntegral(scip, vals[v]) )
11870 {
11871 allcoefintegral = FALSE;
11872 break;
11873 }
11874
11875 oldgcd = gcd;
11876
11877 if( gcd == -1 )
11878 {
11879 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11880 assert(gcd >= 1);
11881 }
11882 else
11883 {
11884 /* calculate greatest common divisor for all general and binary variables */
11885 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11886 }
11887
11888 /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
11889 * can stop searching
11890 */
11891 if( gcd == 1 )
11892 {
11893 if( !SCIPvarIsBinary(vars[v]) )
11894 break;
11895
11896 /* found candidate */
11897 if( candpos == -1 )
11898 {
11899 gcd = oldgcd;
11900 candpos = v;
11901 }
11902 /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
11903 else
11904 break;
11905 }
11906 }
11907 assert(v > offsetv || candpos > offsetv);
11908 }
11909 else
11910 candpos = -1;
11911 }
11912 else
11913 candpos = nvars - 1;
11914
11915 /* check last coefficient for integrality */
11916 if( gcd > 1 && allcoefintegral && !redundant )
11917 {
11918 if( !SCIPisIntegral(scip, vals[nvars - 1]) )
11919 allcoefintegral = FALSE;
11920 }
11921
11922 /* check for further necessary coefficient adjustments */
11923 if( offsetv >= 0 && gcd > 1 && allcoefintegral )
11924 {
11925 assert(offsetv + 1 < nvars);
11926 assert(0 <= candpos && candpos < nvars);
11927
11928 if( SCIPvarIsIntegral(vars[candpos]) )
11929 {
11930 SCIP_Bool notchangable = FALSE;
11931
11932#ifndef NDEBUG
11933 /* check integrality */
11934 for( w = offsetv + 1; w < nvars; ++w )
11935 {
11936 assert(SCIPisIntegral(scip, vals[w]));
11937 }
11938#endif
11939
11940 if( vals[candpos] > 0 && SCIPvarIsBinary(vars[candpos]) &&
11941 SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) < gcd )
11942 {
11943 /* determine the remainder of the side and the gcd */
11944 if( hasrhs )
11945 rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
11946 else
11947 rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
11948 assert(rest >= 0);
11949 assert(rest < gcd);
11950
11951 /* determine the remainder of the coefficient candidate and the gcd */
11952 restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
11953 assert(restcoef >= 1);
11954 assert(restcoef < gcd);
11955
11956 if( hasrhs )
11957 {
11958 /* calculate new coefficient */
11959 if( restcoef > rest )
11960 newcoef = vals[candpos] - restcoef + gcd;
11961 else
11962 newcoef = vals[candpos] - restcoef;
11963 }
11964 else
11965 {
11966 /* calculate new coefficient */
11967 if( rest == 0 || restcoef < rest )
11968 newcoef = vals[candpos] - restcoef;
11969 else
11970 newcoef = vals[candpos] - restcoef + gcd;
11971 }
11972
11973 /* done */
11974
11975 /* new coeffcient must not be zero if we would loose the implication that a variable needs to be 0 if
11976 * another with the big coefficient was set to 1
11977 */
11978 if( hasrhs && SCIPisZero(scip, newcoef) )
11979 {
11980 notchangable = TRUE;
11981 }
11982 else if( SCIPisZero(scip, newcoef) )
11983 {
11984 /* delete old redundant coefficient */
11985 SCIP_CALL( delCoefPos(scip, cons, candpos) );
11986 ++(*nchgcoefs);
11987 }
11988 else
11989 {
11990 /* replace old with new coefficient */
11991 SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
11992 ++(*nchgcoefs);
11993 }
11994 }
11995 else if( vals[candpos] < 0 || !SCIPvarIsBinary(vars[candpos]) )
11996 {
11997 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol));
11998 }
11999
12000 /* correct side and big coefficients */
12001 if( (!notchangable && hasrhs && ((!SCIPisFeasIntegral(scip, rhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(rhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd))) ||
12002 ( haslhs && (!SCIPisFeasIntegral(scip, lhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(lhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd)) )
12003 {
12004 if( haslhs )
12005 {
12006 newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasCeil(scip, lhs/gcd) * gcd + feastol));
12007
12008 SCIP_CALL( chgLhs(scip, cons, newcoef) );
12009 ++(*nchgsides);
12010 }
12011 else
12012 {
12013 assert(hasrhs);
12014 newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasFloor(scip, rhs/gcd) * gcd + feastol));
12015
12016 SCIP_CALL( chgRhs(scip, cons, newcoef) );
12017 ++(*nchgsides);
12018 }
12019
12020 /* correct coefficients up front */
12021 for( w = offsetv; w >= 0; --w )
12022 {
12023 assert(vals[w] > 0);
12024
12025 SCIP_CALL( chgCoefPos(scip, cons, w, newcoef) );
12026 }
12027 (*nchgcoefs) += (offsetv + 1);
12028 }
12029
12030 if( !notchangable )
12031 {
12032 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12033 assert(vars == consdata->vars);
12034 assert(vals == consdata->vals);
12035
12036 if( *infeasible )
12037 return SCIP_OKAY;
12038
12039 /* get new constraint data */
12040 nvars = consdata->nvars;
12041 assert(nvars >= 2);
12042
12044
12045 lhs = consdata->lhs;
12046 rhs = consdata->rhs;
12047 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12048 assert(!haslhs || !SCIPisNegative(scip, lhs));
12049 }
12050 }
12051 }
12052 }
12053
12054 /* @todo we still can remove continuous variables if they are redundant due to the non-integrality argument */
12055 /* no continuous variables are left over */
12056 if( !SCIPvarIsIntegral(vars[nvars - 1]) )
12057 return SCIP_OKAY;
12058
12059 onlybin = TRUE;
12060 allcoefintegral = TRUE;
12061 /* check if all variables are of binary type */
12062 for( v = nvars - 1; v >= 0; --v )
12063 {
12064 if( !SCIPvarIsBinary(vars[v]) )
12065 onlybin = FALSE;
12066 if( !SCIPisIntegral(scip, vals[v]) )
12067 allcoefintegral = FALSE;
12068 }
12069
12070 /* check if the non-integrality part of all integral variables is smaller than the non-inegrality part of the right
12071 * hand side or bigger than the left hand side respectively, so we can make all of them integral
12072 *
12073 * @todo there are some steps missing ....
12074 */
12075 if( (hasrhs && !SCIPisFeasIntegral(scip, rhs)) || (haslhs && !SCIPisFeasIntegral(scip, lhs)) )
12076 {
12077 SCIP_Real val;
12078 SCIP_Real newval;
12079 SCIP_Real frac = 0.0;
12080 SCIP_Bool found = FALSE;
12081
12082 if( hasrhs )
12083 {
12084 if( allcoefintegral )
12085 {
12086 /* replace old with new right hand side */
12087 SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12088 ++(*nchgsides);
12089 }
12090 else
12091 {
12092 siderest = rhs - SCIPfloor(scip, rhs);
12093
12094 /* try to round down all non-integral coefficients */
12095 for( v = nvars - 1; v >= 0; --v )
12096 {
12097 val = vals[v];
12098
12099 /* add up all possible fractional parts */
12100 if( !SCIPisIntegral(scip, val) )
12101 {
12102 lb = SCIPvarGetLbGlobal(vars[v]);
12103 ub = SCIPvarGetUbGlobal(vars[v]);
12104
12105 /* at least one bound need to be at zero */
12106 if( !onlybin && !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12107 return SCIP_OKAY;
12108
12109 /* swap bounds for 'standard' form */
12110 if( !SCIPisFeasZero(scip, lb) )
12111 {
12112 ub = -lb;
12113 val *= -1;
12114 }
12115
12116 found = TRUE;
12117
12118 frac += (val - SCIPfloor(scip, val)) * ub;
12119
12120 /* if we exceed the fractional part of the right hand side, we cannot tighten the coefficients
12121 *
12122 * e.g. 1.1x1 + 1.1x2 + 1.4x3 + 1.02x4 <= 2.4, here we cannot floor all fractionals because
12123 * x3, x4 set to 1 would be infeasible but feasible after flooring
12124 */
12125 if( SCIPisGT(scip, frac, siderest) )
12126 return SCIP_OKAY;
12127 }
12128 }
12129 assert(v == -1);
12130
12131 SCIPdebugMsg(scip, "rounding all non-integral coefficients and the right hand side down\n");
12132
12133 /* round rhs and coefficients to integral values */
12134 if( found )
12135 {
12136 for( v = nvars - 1; v >= 0; --v )
12137 {
12138 val = vals[v];
12139
12140 /* add the whole fractional part */
12141 if( !SCIPisIntegral(scip, val) )
12142 {
12143 lb = SCIPvarGetLbGlobal(vars[v]);
12144
12145 if( SCIPisFeasZero(scip, lb) )
12146 newval = SCIPfloor(scip, val);
12147 else
12148 newval = SCIPceil(scip, val);
12149
12150 if( SCIPisZero(scip, newval) )
12151 {
12152 /* delete old redundant coefficient */
12153 SCIP_CALL( delCoefPos(scip, cons, v) );
12154 ++(*nchgcoefs);
12155 }
12156 else
12157 {
12158 /* replace old with new coefficient */
12159 SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12160 ++(*nchgcoefs);
12161 }
12162 }
12163 }
12164 }
12165
12166 /* replace old with new right hand side */
12167 SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12168 ++(*nchgsides);
12169 }
12170 }
12171 else
12172 {
12173 if( allcoefintegral )
12174 {
12175 /* replace old with new left hand side */
12176 SCIP_CALL( chgLhs(scip, cons, SCIPceil(scip, lhs)) );
12177 ++(*nchgsides);
12178 }
12179 else
12180 {
12181 /* cannot floor left hand side to zero */
12182 if( SCIPisLT(scip, lhs, 1.0) )
12183 return SCIP_OKAY;
12184
12185 siderest = lhs - SCIPfloor(scip, lhs);
12186
12187 /* try to round down all non-integral coefficients */
12188 for( v = nvars - 1; v >= 0; --v )
12189 {
12190 val = vals[v];
12191
12192 /* add up all possible fractional parts */
12193 if( !SCIPisIntegral(scip, val) )
12194 {
12195 lb = SCIPvarGetLbGlobal(vars[v]);
12196 ub = SCIPvarGetUbGlobal(vars[v]);
12197
12198 /* at least one bound need to be at zero */
12199 if( !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12200 return SCIP_OKAY;
12201
12202 /* swap bounds for 'standard' form */
12203 if( !SCIPisFeasZero(scip, lb) )
12204 {
12205 ub = -lb;
12206 val *= -1;
12207 }
12208
12209 /* cannot floor to zero */
12210 if( SCIPisLT(scip, val, 1.0) )
12211 return SCIP_OKAY;
12212
12213 /* the fractional part on each variable need to exceed the fractional part on the left hand side */
12214 if( SCIPisLT(scip, val - SCIPfloor(scip, val), siderest) )
12215 return SCIP_OKAY;
12216
12217 found = TRUE;
12218
12219 frac += (val - SCIPfloor(scip, val)) * ub;
12220
12221 /* if we exceed the fractional part of the left hand side plus one by summing up all maximal
12222 * fractional parts of the variables, we cannot tighten the coefficients
12223 *
12224 * e.g. 4.3x1 + 1.3x2 + 1.3x3 + 1.6x4 >= 4.2, here we cannot floor all fractionals because
12225 * x2-x4 set to 1 would be feasible but not after flooring
12226 */
12227 if( SCIPisGE(scip, frac, 1 + siderest) )
12228 return SCIP_OKAY;
12229 }
12230 /* all coefficients need to be integral, otherwise we might do an invalid reduction */
12231 else
12232 return SCIP_OKAY;
12233 }
12234 assert(v == -1);
12235
12236 SCIPdebugMsg(scip, "rounding all non-integral coefficients and the left hand side down\n");
12237
12238 /* round lhs and coefficients to integral values */
12239 if( found )
12240 {
12241 for( v = nvars - 1; v >= 0; --v )
12242 {
12243 val = vals[v];
12244
12245 /* add the whole fractional part */
12246 if( !SCIPisIntegral(scip, val) )
12247 {
12248 lb = SCIPvarGetLbGlobal(vars[v]);
12249
12250 if( SCIPisFeasZero(scip, lb) )
12251 newval = SCIPfloor(scip, val);
12252 else
12253 newval = SCIPceil(scip, val);
12254
12255 if( SCIPisZero(scip, newval) )
12256 {
12257 /* delete old redundant coefficient */
12258 SCIP_CALL( delCoefPos(scip, cons, v) );
12259 ++(*nchgcoefs);
12260 }
12261 else
12262 {
12263 /* replace old with new coefficient */
12264 SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12265 ++(*nchgcoefs);
12266 }
12267 }
12268 }
12269 }
12270
12271 /* replace old with new left hand side */
12272 SCIP_CALL( chgLhs(scip, cons, SCIPfloor(scip, lhs)) );
12273 ++(*nchgsides);
12274 }
12275 }
12276
12277 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12278 assert(vars == consdata->vars);
12279 assert(vals == consdata->vals);
12280
12281 if( *infeasible )
12282 return SCIP_OKAY;
12283
12284 rhs = consdata->rhs;
12285 lhs = consdata->lhs;
12286
12287 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12288 assert(!haslhs || !SCIPisNegative(scip, lhs));
12289
12291
12292 nvars = consdata->nvars;
12293 if( nvars < 2 )
12294 return SCIP_OKAY;
12295
12296 allcoefintegral = TRUE;
12297#ifndef NDEBUG
12298 /* debug check if all coefficients are really integral */
12299 for( v = nvars - 1; v >= 0; --v )
12300 assert(SCIPisIntegral(scip, vals[v]));
12301#endif
12302 }
12303
12304 /* @todo following can also work on non integral coefficients, need more investigation */
12305 /* only check constraints with integral coefficients on all integral variables */
12306 if( !allcoefintegral )
12307 return SCIP_OKAY;
12308
12309 /* we want to avoid numerical troubles, therefore we do not change non-integral sides */
12310 if( (hasrhs && !SCIPisIntegral(scip, rhs)) || (haslhs && !SCIPisIntegral(scip, lhs)) )
12311 return SCIP_OKAY;
12312
12313 /* maximal absolute value of coefficients in constraint is one, so we cannot tighten it further */
12314 if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) )
12315 return SCIP_OKAY;
12316
12317 /* stop if the last coeffcients is one in absolute value and the variable is not binary */
12318 if( !SCIPvarIsBinary(vars[nvars - 1]) && SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) )
12319 return SCIP_OKAY;
12320
12321 assert(nvars >= 2);
12322
12323 /* start gcd procedure for all variables */
12324 do
12325 {
12326 SCIPdebug( oldnchgcoefs = *nchgcoefs; )
12327 SCIPdebug( oldnchgsides = *nchgsides; )
12328
12329 /* stop if we have two coeffcients which are one in absolute value */
12330 if( SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) && SCIPisEQ(scip, REALABS(vals[nvars - 2]), 1.0) )
12331 return SCIP_OKAY;
12332
12333 gcd = -1;
12334
12335 /* calculate greatest common divisor over all integer variables; note that the onlybin flag needs to be recomputed
12336 * because coefficients of non-binary variables might have changed to zero */
12337 if( !onlybin )
12338 {
12339 foundbin = -1;
12340 onlybin = TRUE;
12341
12342 for( v = nvars - 1; v >= 0; --v )
12343 {
12344 assert(!SCIPisZero(scip, vals[v]));
12346
12347 if( SCIPvarIsBinary(vars[v]) )
12348 {
12349 if( foundbin == -1 )
12350 foundbin = v;
12351 continue;
12352 }
12353 else
12354 onlybin = FALSE;
12355
12356 absval = REALABS(vals[v]);
12357 /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12358 * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12359 */
12360 assert(SCIPisFeasIntegral(scip, absval));
12361
12362 if( gcd == -1 )
12363 {
12364 gcd = (SCIP_Longint)(absval + feastol);
12365 assert(gcd >= 1);
12366 }
12367 else
12368 {
12369 /* calculate greatest common divisor for all general variables */
12370 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(absval + feastol));
12371 }
12372 if( gcd == 1 )
12373 break;
12374 }
12375 }
12376 else
12377 foundbin = nvars - 1;
12378
12379 /* we need at least one binary variable and a gcd greater than 1 to try to perform further coefficient changes */
12380 if( gcd == 1 || foundbin == -1)
12381 return SCIP_OKAY;
12382
12383 assert((onlybin && gcd == -1) || (!onlybin && gcd > 1));
12384
12385 candpos = -1;
12386 candpos2 = -1;
12387
12388 /* calculate greatest common divisor over all integer and binary variables and determine the candidate where we might
12389 * change the coefficient
12390 */
12391 for( v = foundbin; v >= 0; --v )
12392 {
12393 if( onlybin || SCIPvarIsBinary(vars[v]) )
12394 {
12395 absval = REALABS(vals[v]);
12396 /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12397 * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12398 */
12399 assert(SCIPisFeasIntegral(scip, absval));
12400
12401 oldgcd = gcd;
12402
12403 if( gcd == -1 )
12404 {
12405 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12406 assert(gcd >= 1);
12407 }
12408 else
12409 {
12410 /* calculate greatest common divisor for all general and binary variables */
12411 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12412 }
12413
12414 /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12415 * can terminate
12416 */
12417 if( gcd == 1 )
12418 {
12419 /* found candidate */
12420 if( candpos == -1 )
12421 {
12422 gcd = oldgcd;
12423 candpos = v;
12424
12425 /* if we have only binary variables and both first coefficients have a gcd of 1, both are candidates for
12426 * the coefficient change
12427 */
12428 if( onlybin && v == foundbin - 1 )
12429 candpos2 = foundbin;
12430 }
12431 /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12432 else
12433 {
12434 if( onlybin && candpos == v + 1 && candpos2 == v + 2 )
12435 {
12436 assert(candpos2 == nvars - 1);
12437
12438 /* take new candidates */
12439 candpos = candpos2;
12440
12441 /* recalculate gcd from scratch */
12442 gcd = (SCIP_Longint)(REALABS(vals[v+1]) + feastol);
12443 assert(gcd >= 1);
12444
12445 /* calculate greatest common divisor for all general and binary variables */
12446 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12447 if( gcd == 1 )
12448 return SCIP_OKAY;
12449 }
12450 else
12451 /* cannot determine a possible coefficient for reduction */
12452 return SCIP_OKAY;
12453 }
12454 }
12455 }
12456 }
12457 assert(gcd >= 2);
12458
12459 /* we should have found one coefficient, that led to a gcd of 1, otherwise we could normalize the constraint
12460 * further
12461 */
12462 assert(candpos >= 0 && candpos < nvars);
12463
12464 /* all variables and all coefficients are integral, so the side should be too */
12465 assert((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs)));
12466
12467 /* check again, if we have a normalized inequality (not ranged) the one side should be positive,
12468 * @see normalizeCons()
12469 */
12470 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12471 assert(!haslhs || !SCIPisNegative(scip, lhs));
12472
12473 /* determine the remainder of the side and the gcd */
12474 if( hasrhs )
12475 rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12476 else
12477 rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12478 assert(rest >= 0);
12479 assert(rest < gcd);
12480
12481 /* determine the remainder of the coefficient candidate and the gcd */
12482 if( vals[candpos] < 0 )
12483 {
12484 restcoef = ((SCIP_Longint)(vals[candpos] - feastol)) % gcd;
12485 assert(restcoef <= -1);
12486 restcoef += gcd;
12487 }
12488 else
12489 restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12490 assert(restcoef >= 1);
12491 assert(restcoef < gcd);
12492
12493 if( hasrhs )
12494 {
12495 if( rest > 0 )
12496 {
12497 /* replace old with new right hand side */
12498 SCIP_CALL( chgRhs(scip, cons, rhs - rest) );
12499 ++(*nchgsides);
12500 }
12501
12502 /* calculate new coefficient */
12503 if( restcoef > rest )
12504 newcoef = vals[candpos] - restcoef + gcd;
12505 else
12506 newcoef = vals[candpos] - restcoef;
12507 }
12508 else
12509 {
12510 if( rest > 0 )
12511 {
12512 /* replace old with new left hand side */
12513 SCIP_CALL( chgLhs(scip, cons, lhs - rest + gcd) );
12514 ++(*nchgsides);
12515 }
12516
12517 /* calculate new coefficient */
12518 if( rest == 0 || restcoef < rest )
12519 newcoef = vals[candpos] - restcoef;
12520 else
12521 newcoef = vals[candpos] - restcoef + gcd;
12522 }
12523 assert(SCIPisZero(scip, newcoef) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(newcoef) + feastol)) == gcd);
12524
12525 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));
12526
12527 if( SCIPisZero(scip, newcoef) )
12528 {
12529 /* delete redundant coefficient */
12530 SCIP_CALL( delCoefPos(scip, cons, candpos) );
12531 }
12532 else
12533 {
12534 /* replace old with new coefficient */
12535 SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12536 }
12537 ++(*nchgcoefs);
12538
12539 /* now constraint can be normalized, might be directly done by dividing it by the gcd */
12540 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12541 assert(vars == consdata->vars);
12542 assert(vals == consdata->vals);
12543
12544 if( *infeasible )
12545 return SCIP_OKAY;
12546
12548
12549 rhs = consdata->rhs;
12550 lhs = consdata->lhs;
12551 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12552 assert(!haslhs || !SCIPisNegative(scip, lhs));
12553
12554 nvars = consdata->nvars;
12555
12556 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));
12557 }
12558 while( nvars >= 2 );
12559
12560 return SCIP_OKAY;
12561}
12562
12563
12564/** tries to aggregate an (in)equality and an equality in order to decrease the number of variables in the (in)equality:
12565 * cons0 := a * cons0 + b * cons1,
12566 * where a = val1[v] and b = -val0[v] for common variable v which removes most variable weight;
12567 * for numerical stability, we will only accept integral a and b;
12568 * the variable weight is a weighted sum over all included variables, where each binary variable weighs BINWEIGHT,
12569 * each integer or implied integral variable weighs INTWEIGHT and each continuous variable weighs CONTWEIGHT
12570 */
12571static
12573 SCIP* scip, /**< SCIP data structure */
12574 SCIP_CONS* cons0, /**< (in)equality to modify */
12575 SCIP_CONS* cons1, /**< equality to use for aggregation of cons0 */
12576 int* commonidx0, /**< array with indices of variables in cons0, that appear also in cons1 */
12577 int* commonidx1, /**< array with indices of variables in cons1, that appear also in cons0 */
12578 int* diffidx0minus1, /**< array with indices of variables in cons0, that don't appear in cons1 */
12579 int* diffidx1minus0, /**< array with indices of variables in cons1, that don't appear in cons0 */
12580 int nvarscommon, /**< number of variables, that appear in both constraints */
12581 int commonidxweight, /**< variable weight sum of common variables */
12582 int diffidx0minus1weight, /**< variable weight sum of variables in cons0, that don't appear in cons1 */
12583 int diffidx1minus0weight, /**< variable weight sum of variables in cons1, that don't appear in cons0 */
12584 SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
12585 int* nchgcoefs, /**< pointer to count the number of changed coefficients */
12586 SCIP_Bool* aggregated, /**< pointer to store whether an aggregation was made */
12587 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
12588 )
12589{
12590 SCIP_CONSDATA* consdata0;
12591 SCIP_CONSDATA* consdata1;
12592 SCIP_Real a;
12593 SCIP_Real b;
12594 SCIP_Real aggrcoef;
12595 SCIP_Real scalarsum;
12596 SCIP_Real bestscalarsum;
12597 SCIP_Bool betterscalarsum;
12598 SCIP_Bool commonvarlindependent; /* indicates whether coefficient vector of common variables in linearly dependent */
12599 int varweight;
12600 int nvars;
12601 int bestvarweight;
12602 int bestnvars;
12603 int bestv;
12604 int v;
12605 int i;
12606
12607 assert(scip != NULL);
12608 assert(cons0 != NULL);
12609 assert(cons1 != NULL);
12610 assert(commonidx0 != NULL);
12611 assert(commonidx1 != NULL);
12612 assert(diffidx0minus1 != NULL);
12613 assert(diffidx1minus0 != NULL);
12614 assert(nvarscommon >= 1);
12615 assert(commonidxweight >= nvarscommon);
12616 assert(nchgcoefs != NULL);
12617 assert(aggregated != NULL);
12618
12619 assert(SCIPconsIsActive(cons0));
12620 assert(SCIPconsIsActive(cons1));
12621
12622 *infeasible = FALSE;
12623
12624 SCIPdebugMsg(scip, "try aggregation of <%s> and <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
12625
12626 /* cons0 is an (in)equality */
12627 consdata0 = SCIPconsGetData(cons0);
12628 assert(consdata0 != NULL);
12629 assert(consdata0->nvars >= 1);
12630 assert(SCIPisLE(scip, consdata0->lhs, consdata0->rhs));
12631 assert(diffidx0minus1weight >= consdata0->nvars - nvarscommon);
12632
12633 /* cons1 is an equality */
12634 consdata1 = SCIPconsGetData(cons1);
12635 assert(consdata1 != NULL);
12636 assert(consdata1->nvars >= 1);
12637 assert(SCIPisEQ(scip, consdata1->lhs, consdata1->rhs));
12638 assert(diffidx1minus0weight >= consdata1->nvars - nvarscommon);
12639
12640 *aggregated = FALSE;
12641
12642 /* search for the best common variable such that
12643 * val1[var] * consdata0 - val0[var] * consdata1
12644 * has least weighted number of variables
12645 */
12646 bestvarweight = commonidxweight + diffidx0minus1weight;
12647 bestnvars = consdata0->nvars;
12648 bestv = -1;
12649 bestscalarsum = 0.0;
12650 commonvarlindependent = TRUE;
12651 for( v = 0; v < nvarscommon; ++v )
12652 {
12653 assert(consdata0->vars[commonidx0[v]] == consdata1->vars[commonidx1[v]]);
12654 a = consdata1->vals[commonidx1[v]];
12655 b = -consdata0->vals[commonidx0[v]];
12656
12657 /* only try aggregation, if coefficients are integral (numerical stability) */
12659 {
12660 /* count the number of variables in the potential new constraint a * consdata0 + b * consdata1 */
12661 varweight = diffidx0minus1weight + diffidx1minus0weight;
12662 nvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12663 scalarsum = REALABS(a) + REALABS(b);
12664 betterscalarsum = (scalarsum < bestscalarsum);
12665 for( i = 0; i < nvarscommon
12666 && (varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum)); ++i )
12667 {
12668 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12669 if( !SCIPisZero(scip, aggrcoef) )
12670 {
12671 varweight += getVarWeight(consdata0->vars[commonidx0[i]]);
12672 nvars++;
12673 }
12674 }
12675 if( varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum) )
12676 {
12677 bestv = v;
12678 bestvarweight = varweight;
12679 bestnvars = nvars;
12680 bestscalarsum = scalarsum;
12681 }
12682 }
12683
12684 /* update commonvarlindependent flag, if still TRUE:
12685 * 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
12686 */
12687 if( commonvarlindependent && v > 0 )
12688 commonvarlindependent = SCIPisEQ(scip,
12689 consdata1->vals[commonidx1[v]] * consdata0->vals[commonidx0[0]],
12690 consdata1->vals[commonidx1[0]] * consdata0->vals[commonidx0[v]]);
12691 }
12692
12693 /* if better aggregation was found, create new constraint and delete old one */
12694 if( (bestv != -1 || commonvarlindependent) && SCIPconsGetNUpgradeLocks(cons0) == 0 )
12695 {
12696 SCIP_CONS* newcons;
12697 SCIP_CONSDATA* newconsdata;
12698 SCIP_VAR** newvars;
12699 SCIP_Real* newvals;
12700 SCIP_Real newlhs;
12701 SCIP_Real newrhs;
12702 int newnvars;
12703
12704 if( bestv != -1 )
12705 {
12706 /* choose multipliers such that the multiplier for the (in)equality cons0 is positive */
12707 if( consdata1->vals[commonidx1[bestv]] > 0.0 )
12708 {
12709 a = consdata1->vals[commonidx1[bestv]];
12710 b = -consdata0->vals[commonidx0[bestv]];
12711 }
12712 else
12713 {
12714 a = -consdata1->vals[commonidx1[bestv]];
12715 b = consdata0->vals[commonidx0[bestv]];
12716 }
12720 assert(!SCIPisZero(scip, b));
12721 }
12722 else
12723 {
12724 assert(commonvarlindependent);
12725 if( consdata1->vals[commonidx1[0]] > 0.0 )
12726 {
12727 a = consdata1->vals[commonidx1[0]];
12728 b = -consdata0->vals[commonidx0[0]];
12729 }
12730 else
12731 {
12732 a = -consdata1->vals[commonidx1[0]];
12733 b = consdata0->vals[commonidx0[0]];
12734 }
12736 assert(!SCIPisZero(scip, b));
12737
12738 /* if a/b is integral, then we can easily choose integer multipliers */
12739 if( SCIPisIntegral(scip, a/b) )
12740 {
12741 if( a/b > 0 )
12742 {
12743 a /= b;
12744 b = 1.0;
12745 }
12746 else
12747 {
12748 a /= -b;
12749 b = -1.0;
12750 }
12751 }
12752
12753 /* setup best* variables that were not setup above because we are in the commonvarlindependent case */
12754 SCIPdebug( bestvarweight = diffidx0minus1weight + diffidx1minus0weight; )
12755 bestnvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12756 }
12757
12758 SCIPdebugMsg(scip, "aggregate linear constraints <%s> := %.15g*<%s> + %.15g*<%s> -> nvars: %d -> %d, weight: %d -> %d\n",
12759 SCIPconsGetName(cons0), a, SCIPconsGetName(cons0), b, SCIPconsGetName(cons1),
12760 consdata0->nvars, bestnvars, commonidxweight + diffidx0minus1weight, bestvarweight);
12761 SCIPdebugPrintCons(scip, cons0, NULL);
12762 SCIPdebugPrintCons(scip, cons1, NULL);
12763
12764 /* get temporary memory for creating the new linear constraint */
12765 SCIP_CALL( SCIPallocBufferArray(scip, &newvars, bestnvars) );
12766 SCIP_CALL( SCIPallocBufferArray(scip, &newvals, bestnvars) );
12767
12768 /* calculate the common coefficients, if we have not recognized linear dependency */
12769 newnvars = 0;
12770 if( !commonvarlindependent )
12771 {
12772 for( i = 0; i < nvarscommon; ++i )
12773 {
12774 assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12775 assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12776
12777 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12778 if( !SCIPisZero(scip, aggrcoef) )
12779 {
12780 assert(newnvars < bestnvars);
12781 newvars[newnvars] = consdata0->vars[commonidx0[i]];
12782 newvals[newnvars] = aggrcoef;
12783 newnvars++;
12784 }
12785 }
12786 }
12787 else
12788 {
12789 /* if we recognized linear dependency of the common coefficients, then the aggregation coefficient should be 0.0 for every common variable */
12790#ifndef NDEBUG
12791 for( i = 0; i < nvarscommon; ++i )
12792 {
12793 assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12794 assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12795
12796 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12797 assert(SCIPisZero(scip, aggrcoef));
12798 }
12799#endif
12800 }
12801
12802 /* calculate the coefficients appearing in cons0 but not in cons1 */
12803 for( i = 0; i < consdata0->nvars - nvarscommon; ++i )
12804 {
12805 assert(0 <= diffidx0minus1[i] && diffidx0minus1[i] < consdata0->nvars);
12806
12807 aggrcoef = a * consdata0->vals[diffidx0minus1[i]];
12808 assert(!SCIPisZero(scip, aggrcoef));
12809 assert(newnvars < bestnvars);
12810 newvars[newnvars] = consdata0->vars[diffidx0minus1[i]];
12811 newvals[newnvars] = aggrcoef;
12812 newnvars++;
12813 }
12814
12815 /* calculate the coefficients appearing in cons1 but not in cons0 */
12816 for( i = 0; i < consdata1->nvars - nvarscommon; ++i )
12817 {
12818 assert(0 <= diffidx1minus0[i] && diffidx1minus0[i] < consdata1->nvars);
12819
12820 aggrcoef = b * consdata1->vals[diffidx1minus0[i]];
12821 assert(!SCIPisZero(scip, aggrcoef));
12822 assert(newnvars < bestnvars);
12823 newvars[newnvars] = consdata1->vars[diffidx1minus0[i]];
12824 newvals[newnvars] = aggrcoef;
12825 newnvars++;
12826 }
12827 assert(newnvars == bestnvars);
12828
12829 /* calculate the new left and right hand side of the (in)equality */
12830 assert(!SCIPisInfinity(scip, -consdata1->lhs));
12831 assert(!SCIPisInfinity(scip, consdata1->rhs));
12832 if( SCIPisInfinity(scip, -consdata0->lhs) )
12833 newlhs = -SCIPinfinity(scip);
12834 else
12835 newlhs = a * consdata0->lhs + b * consdata1->lhs;
12836 if( SCIPisInfinity(scip, consdata0->rhs) )
12837 newrhs = SCIPinfinity(scip);
12838 else
12839 newrhs = a * consdata0->rhs + b * consdata1->rhs;
12840
12841 /* create the new linear constraint */
12842 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, SCIPconsGetName(cons0), newnvars, newvars, newvals, newlhs, newrhs,
12847
12848 newconsdata = SCIPconsGetData(newcons);
12849 assert(newconsdata != NULL);
12850
12851 /* copy the upgraded flag from the old cons0 to the new constraint */
12852 newconsdata->upgraded = consdata0->upgraded;
12853
12854 SCIP_CALL( normalizeCons(scip, newcons, infeasible) );
12855
12856 /* check, if we really want to use the new constraint instead of the old one:
12857 * use the new one, if the maximum norm doesn't grow too much
12858 */
12859 if( !(*infeasible) && consdataGetMaxAbsval(SCIPconsGetData(newcons)) <= maxaggrnormscale * consdataGetMaxAbsval(consdata0) )
12860 {
12861 SCIPdebugMsg(scip, " -> aggregated to <%s>\n", SCIPconsGetName(newcons));
12862 SCIPdebugPrintCons(scip, newcons, NULL);
12863
12864 /* update the statistics: we changed all coefficients */
12865 if( !consdata0->upgraded )
12866 (*nchgcoefs) += consdata0->nvars + consdata1->nvars - nvarscommon;
12867 *aggregated = TRUE;
12868
12869 /* add the new linear constraint to the problem and delete the old constraint */
12870 SCIP_CALL( SCIPaddConsUpgrade(scip, cons0, &newcons) );
12871 SCIP_CALL( SCIPdelCons(scip, cons0) );
12872 }
12873 else
12874 {
12875 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
12876 }
12877
12878 /* free temporary memory */
12879 SCIPfreeBufferArray(scip, &newvals);
12880 SCIPfreeBufferArray(scip, &newvars);
12881 }
12882
12883 return SCIP_OKAY;
12884}
12885
12886/** gets the key of the given element */
12887static
12888SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
12889{ /*lint --e{715}*/
12890 /* the key is the element itself */
12891 return elem;
12892}
12893
12894/** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables and the
12895 * coefficients are either equal or negated
12896 */
12897static
12898SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
12899{
12900 SCIP* scip;
12901 SCIP_CONSDATA* consdata1;
12902 SCIP_CONSDATA* consdata2;
12903 SCIP_Real minscale;
12904 SCIP_Real maxscale;
12905 int i;
12906
12907 assert(key1 != NULL);
12908 assert(key2 != NULL);
12909 consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
12910 consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
12911 assert(consdata1->indexsorted);
12912 assert(consdata2->indexsorted);
12913
12914 scip = (SCIP*)userptr;
12915 assert(scip != NULL);
12916
12917 /* if it is the same constraint we dont need to check anything */
12918 if( key1 == key2 )
12919 return TRUE;
12920
12921 /* checks trivial case */
12922 if( consdata1->nvars != consdata2->nvars )
12923 return FALSE;
12924
12925 /* tests if variables are equal */
12926 for( i = 0; i < consdata1->nvars; ++i )
12927 {
12928 if( consdata1->vars[i] != consdata2->vars[i] )
12929 {
12930 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
12931 SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
12932 return FALSE;
12933 }
12934 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
12935 }
12936
12937 /* order by maxabsval */
12938 if( consdataGetMaxAbsval(consdata1) > consdataGetMaxAbsval(consdata2) )
12939 SCIPswapPointers((void**)&consdata1, (void**)&consdata2);
12940
12941 /* initialize extremal scales */
12942 minscale = SCIPinfinity(scip);
12943 maxscale = -SCIPinfinity(scip);
12944
12945 /* test if coefficient scales are equal */
12946 for( i = 0; i < consdata1->nvars; ++i )
12947 {
12948 SCIP_Real scale = consdata2->vals[i] / consdata1->vals[i];
12949
12950 if( minscale > scale )
12951 {
12952 minscale = scale;
12953
12954 if( SCIPisLT(scip, minscale, maxscale) )
12955 return FALSE;
12956 }
12957
12958 if( maxscale < scale )
12959 {
12960 maxscale = scale;
12961
12962 if( SCIPisLT(scip, minscale, maxscale) )
12963 return FALSE;
12964 }
12965 }
12966
12967 return TRUE;
12968}
12969
12970/** returns the hash value of the key */
12971static
12972SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
12973{
12974 SCIP_CONSDATA* consdata;
12975 int minidx;
12976 int mididx;
12977 int maxidx;
12978#ifndef NDEBUG
12979 SCIP* scip;
12980
12981 scip = (SCIP*)userptr;
12982 assert(scip != NULL);
12983#endif
12984
12985 assert(key != NULL);
12986 consdata = SCIPconsGetData((SCIP_CONS*)key);
12987 assert(consdata != NULL);
12988 assert(consdata->nvars > 0);
12989
12990 assert(consdata->indexsorted);
12991
12992 minidx = SCIPvarGetIndex(consdata->vars[0]);
12993 mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
12994 maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
12995
12996 /* using only the variable indices as hash, since the values are compared by epsilon */
12997 return SCIPhashFour(consdata->nvars, minidx, mididx, maxidx);
12998}
12999
13000/** returns the key for deciding which of two parallel constraints should be kept (smaller key should be kept);
13001 * prefers non-upgraded constraints and as second criterion the constraint with the smallest position
13002 */
13003static
13005 SCIP_CONS* cons /**< linear constraint */
13006 )
13007{
13008 SCIP_CONSDATA* consdata;
13009
13010 assert(cons != NULL);
13011
13012 consdata = SCIPconsGetData(cons);
13013 assert(consdata != NULL);
13014
13015 return (((unsigned int)consdata->upgraded)<<31) + (unsigned int)SCIPconsGetPos(cons); /*lint !e571*/
13016}
13017
13018/** updates the hashtable such that out of all constraints in the hashtable that are detected
13019 * to be parallel to *querycons, only one is kept in the hashtable and stored into *querycons,
13020 * and all others are removed from the hashtable and stored in the given array
13021 */
13022static
13024 SCIP_HASHTABLE* hashtable, /**< hashtable containing linear constraints */
13025 SCIP_CONS** querycons, /**< pointer to linear constraint used to look for duplicates in the hash table;
13026 * upon return will contain the constraint that should be kept */
13027 SCIP_CONS** parallelconss, /**< array to return constraints that are parallel to the given;
13028 * these constraints where removed from the hashtable */
13029 int* nparallelconss /**< pointer to return number of parallel constraints */
13030 )
13031{
13032 SCIP_CONS* parallelcons;
13033 unsigned int querykey;
13034
13035 *nparallelconss = 0;
13036 querykey = getParallelConsKey(*querycons);
13037
13038 while( (parallelcons = (SCIP_CONS*)SCIPhashtableRetrieve(hashtable, (void*)(*querycons))) != NULL )
13039 {
13040 unsigned int conskey = getParallelConsKey(parallelcons);
13041
13042 if( conskey < querykey )
13043 {
13044 parallelconss[(*nparallelconss)++] = *querycons;
13045 *querycons = parallelcons;
13046 querykey = conskey;
13047 }
13048 else
13049 {
13050 parallelconss[(*nparallelconss)++] = parallelcons;
13051 }
13052
13053 /* if the constraint that just came out of the hash table is the one that is kept,
13054 * we do not need to look into the hashtable again, since the invariant is that
13055 * in the hashtable only pair-wise non-parallel constraints are contained.
13056 * For the original querycons, however, multiple constraints that compare equal (=parallel)
13057 * could be contained due to non-transitivity of the equality comparison.
13058 * Also we can return immediately, since parallelcons is already contained in the
13059 * hashtable and we do not need to remove and reinsert it.
13060 */
13061 if( *querycons == parallelcons )
13062 return SCIP_OKAY;
13063
13064 /* remove parallelcons from the hashtable, since it will be replaced by querycons */
13065 SCIP_CALL( SCIPhashtableRemove(hashtable, (void*) parallelcons) );
13066 }
13067
13068 /* in debug mode we make sure, that the hashtable cannot contain a constraint that
13069 * comnpares equal to querycons at this point
13070 */
13071#ifndef NDEBUG
13072 SCIP_CALL_ABORT( SCIPhashtableSafeInsert(hashtable, *querycons) );
13073#else
13074 SCIP_CALL( SCIPhashtableInsert(hashtable, *querycons) );
13075#endif
13076
13077 return SCIP_OKAY;
13078}
13079
13080/** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
13081 * accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
13082 */
13083static
13085 SCIP* scip, /**< SCIP data structure */
13086 BMS_BLKMEM* blkmem, /**< block memory */
13087 SCIP_CONS** conss, /**< constraint set */
13088 int nconss, /**< number of constraints in constraint set */
13089 int* firstchange, /**< pointer to store first changed constraint */
13090 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13091 int* ndelconss, /**< pointer to count number of deleted constraints */
13092 int* nchgsides /**< pointer to count number of changed left/right hand sides */
13093 )
13094{
13095 SCIP_HASHTABLE* hashtable;
13096 SCIP_CONS** parallelconss;
13097 int nparallelconss;
13098 int hashtablesize;
13099 int c;
13100
13101 assert(scip != NULL);
13102 assert(blkmem != NULL);
13103 assert(conss != NULL);
13104 assert(firstchange != NULL);
13105 assert(cutoff != NULL);
13106 assert(ndelconss != NULL);
13107 assert(nchgsides != NULL);
13108
13109 /* create a hash table for the constraint set */
13110 hashtablesize = nconss;
13111 SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
13112 hashGetKeyLinearcons, hashKeyEqLinearcons, hashKeyValLinearcons, (void*) scip) );
13113
13114 SCIP_CALL( SCIPallocBufferArray(scip, &parallelconss, nconss) );
13115
13116 /* check all constraints in the given set for redundancy */
13117 for( c = 0; c < nconss; ++c )
13118 {
13119 SCIP_CONS* cons0;
13120 SCIP_CONSDATA* consdata0;
13121
13122 cons0 = conss[c];
13123
13124 if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
13125 continue;
13126
13127 /* do not check for parallel constraints if they should not be upgraded */
13128 if ( SCIPconsGetNUpgradeLocks(cons0) > 0 )
13129 continue;
13130
13131 /* check for interuption */
13132 if( c % 1000 == 0 && SCIPisStopped(scip) )
13133 break;
13134
13135 /* sorts the constraint */
13136 consdata0 = SCIPconsGetData(cons0);
13137 assert(consdata0 != NULL);
13138 SCIP_CALL( consdataSort(scip, consdata0) );
13139 assert(consdata0->indexsorted);
13140
13141 /* get constraints from current hash table with same variables as cons0 and with coefficients equal
13142 * to the ones of cons0 when both are scaled such that maxabsval is 1.0 and the coefficient of the
13143 * first variable is positive
13144 * Also inserts cons0 into the hashtable.
13145 */
13146 SCIP_CALL( retrieveParallelConstraints(hashtable, &cons0, parallelconss, &nparallelconss) );
13147
13148 if( nparallelconss != 0 )
13149 {
13150 SCIP_Real lhs;
13151 SCIP_Real rhs;
13152
13153 int i;
13154
13155 /* cons0 may have been changed in retrieveParallelConstraints() */
13156 consdata0 = SCIPconsGetData(cons0);
13157
13158 lhs = consdata0->lhs;
13159 rhs = consdata0->rhs;
13160
13161 for( i = 0; i < nparallelconss; ++i )
13162 {
13163 SCIP_CONS* consdel;
13164 SCIP_CONSDATA* consdatadel;
13165 SCIP_Real scale;
13166
13167 consdel = parallelconss[i];
13168 consdatadel = SCIPconsGetData(consdel);
13169
13170 /* do not delete constraint if it should not be upgraded */
13171 if ( SCIPconsGetNUpgradeLocks(consdel) > 0 )
13172 continue;
13173
13174 assert(SCIPconsIsActive(consdel));
13175 assert(!SCIPconsIsModifiable(consdel));
13176
13177 /* constraint found: create a new constraint with same coefficients and best left and right hand side;
13178 * delete old constraints afterwards
13179 */
13180 assert(consdatadel != NULL);
13181 assert(consdata0->nvars >= 1 && consdata0->nvars == consdatadel->nvars);
13182
13183 assert(consdatadel->indexsorted);
13184 assert(consdata0->vars[0] == consdatadel->vars[0]);
13185
13186 scale = consdata0->vals[0] / consdatadel->vals[0];
13187 assert(scale != 0.0);
13188
13189 /* in debug mode, check that all coefficients are equal with respect to epsilon
13190 * if the constraints are in equilibrium scale
13191 */
13192#ifndef NDEBUG
13193 {
13194 assert(consdata0->validmaxabsval);
13195 assert(consdatadel->validmaxabsval);
13196 int k;
13197 SCIP_Real scale0 = 1.0 / consdata0->maxabsval;
13198 SCIP_Real scaledel = COPYSIGN(1.0 / consdatadel->maxabsval, scale);
13199
13200 for( k = 0; k < consdata0->nvars; ++k )
13201 {
13202 assert(SCIPisEQ(scip, scale0 * consdata0->vals[k], scaledel * consdatadel->vals[k]));
13203 }
13204 }
13205#endif
13206
13207 if( scale > 0.0 )
13208 {
13209 /* the coefficients of both constraints are parallel with a positive scale */
13210 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with equal coefficients into single ranged row\n",
13211 SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13212 SCIPdebugPrintCons(scip, cons0, NULL);
13213 SCIPdebugPrintCons(scip, consdel, NULL);
13214
13215 if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13216 lhs = MAX(scale * consdatadel->lhs, lhs);
13217
13218 if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13219 rhs = MIN(scale * consdatadel->rhs, rhs);
13220 }
13221 else
13222 {
13223 /* the coefficients of both rows are negations */
13224 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with negated coefficients into single ranged row\n",
13225 SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13226 SCIPdebugPrintCons(scip, cons0, NULL);
13227 SCIPdebugPrintCons(scip, consdel, NULL);
13228
13229 if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13230 lhs = MAX(scale * consdatadel->rhs, lhs);
13231
13232 if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13233 rhs = MIN(scale * consdatadel->lhs, rhs);
13234 }
13235
13236 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13237 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, consdel) );
13238
13239 /* delete consdel */
13240 assert( ! consdata0->upgraded || consdatadel->upgraded );
13241 SCIP_CALL( SCIPdelCons(scip, consdel) );
13242 if( !consdatadel->upgraded )
13243 (*ndelconss)++;
13244 }
13245
13246 if( SCIPisFeasLT(scip, rhs, lhs) )
13247 {
13248 SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13249 *cutoff = TRUE;
13250 break;
13251 }
13252
13253 /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
13254 if( lhs > rhs )
13255 {
13256 rhs = (lhs + rhs)/2;
13257 lhs = rhs;
13258 }
13259
13260 /* update lhs and rhs of cons0 */
13261 SCIP_CALL( chgLhs(scip, cons0, lhs) );
13262 SCIP_CALL( chgRhs(scip, cons0, rhs) );
13263
13264 /* update the first changed constraint to begin the next aggregation round with */
13265 if( consdata0->changed && SCIPconsGetPos(cons0) < *firstchange )
13266 *firstchange = SCIPconsGetPos(cons0);
13267
13268 assert(SCIPconsIsActive(cons0));
13269 }
13270 }
13271#ifdef SCIP_MORE_DEBUG
13272 SCIPinfoMessage(scip, NULL, "linear pairwise comparison hashtable statistics:\n");
13274#endif
13275
13276 SCIPfreeBufferArray(scip, &parallelconss);
13277
13278 /* free hash table */
13279 SCIPhashtableFree(&hashtable);
13280
13281 return SCIP_OKAY;
13282}
13283
13284/** compares constraint with all prior constraints for possible redundancy or aggregation,
13285 * and removes or changes constraint accordingly
13286 */
13287static
13289 SCIP* scip, /**< SCIP data structure */
13290 SCIP_CONS** conss, /**< constraint set */
13291 int firstchange, /**< first constraint that changed since last pair preprocessing round */
13292 int chkind, /**< index of constraint to check against all prior indices upto startind */
13293 SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
13294 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13295 int* ndelconss, /**< pointer to count number of deleted constraints */
13296 int* nchgsides, /**< pointer to count number of changed left/right hand sides */
13297 int* nchgcoefs /**< pointer to count number of changed coefficients */
13298 )
13299{
13300 SCIP_CONS* cons0;
13301 SCIP_CONSDATA* consdata0;
13302 int* commonidx0;
13303 int* commonidx1;
13304 int* diffidx0minus1;
13305 int* diffidx1minus0;
13306 uint64_t possignature0;
13307 uint64_t negsignature0;
13308 SCIP_Bool cons0changed;
13309 SCIP_Bool cons0isequality;
13310 int diffidx1minus0size;
13311 int c;
13312 SCIP_Real cons0lhs;
13313 SCIP_Real cons0rhs;
13314 SCIP_Bool cons0upgraded;
13315
13316 assert(scip != NULL);
13317 assert(conss != NULL);
13318 assert(firstchange <= chkind);
13319 assert(cutoff != NULL);
13320 assert(ndelconss != NULL);
13321 assert(nchgsides != NULL);
13322 assert(nchgcoefs != NULL);
13323
13324 /* get the constraint to be checked against all prior constraints */
13325 cons0 = conss[chkind];
13326 assert(cons0 != NULL);
13327 assert(SCIPconsIsActive(cons0));
13329
13330 consdata0 = SCIPconsGetData(cons0);
13331 assert(consdata0 != NULL);
13332 assert(consdata0->nvars >= 1);
13333 cons0isequality = SCIPisEQ(scip, consdata0->lhs, consdata0->rhs);
13334
13335 /* sort the constraint */
13336 SCIP_CALL( consdataSort(scip, consdata0) );
13337
13338 /* calculate bit signatures of cons0 for potentially positive and negative coefficients */
13339 consdataCalcSignatures(consdata0);
13340 possignature0 = consdata0->possignature;
13341 negsignature0 = consdata0->negsignature;
13342
13343 /* get temporary memory for indices of common variables */
13344 SCIP_CALL( SCIPallocBufferArray(scip, &commonidx0, consdata0->nvars) );
13345 SCIP_CALL( SCIPallocBufferArray(scip, &commonidx1, consdata0->nvars) );
13346 SCIP_CALL( SCIPallocBufferArray(scip, &diffidx0minus1, consdata0->nvars) );
13347 SCIP_CALL( SCIPallocBufferArray(scip, &diffidx1minus0, consdata0->nvars) );
13348 diffidx1minus0size = consdata0->nvars;
13349
13350 cons0lhs = consdata0->lhs;
13351 cons0rhs = consdata0->rhs;
13352 cons0upgraded = consdata0->upgraded;
13353
13354 /* check constraint against all prior constraints */
13355 cons0changed = consdata0->changed;
13356 consdata0->changed = FALSE;
13357 for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && conss[chkind] != NULL; ++c )
13358 {
13359 SCIP_CONS* cons1;
13360 SCIP_CONSDATA* consdata1;
13361 uint64_t possignature1;
13362 uint64_t negsignature1;
13363 SCIP_Bool cons0dominateslhs;
13364 SCIP_Bool cons1dominateslhs;
13365 SCIP_Bool cons0dominatesrhs;
13366 SCIP_Bool cons1dominatesrhs;
13367 SCIP_Bool cons1isequality;
13368 SCIP_Bool coefsequal;
13369 SCIP_Bool coefsnegated;
13370 SCIP_Bool tryaggregation;
13371 int nvarscommon;
13372 int nvars0minus1;
13373 int nvars1minus0;
13374 int commonidxweight;
13375 int diffidx0minus1weight;
13376 int diffidx1minus0weight;
13377 int v0;
13378 int v1;
13379
13380 assert(cons0lhs == consdata0->lhs); /*lint !e777*/
13381 assert(cons0rhs == consdata0->rhs); /*lint !e777*/
13382 assert(cons0upgraded == consdata0->upgraded);
13383
13384 cons1 = conss[c];
13385
13386 /* cons1 has become inactive during presolving of constraint pairs */
13387 if( cons1 == NULL )
13388 continue;
13389
13390 assert(SCIPconsIsActive(cons0) && !SCIPconsIsModifiable(cons0));
13391 assert(SCIPconsIsActive(cons1) && !SCIPconsIsModifiable(cons1));
13392
13393 consdata1 = SCIPconsGetData(cons1);
13394 assert(consdata1 != NULL);
13395
13396 /* SCIPdebugMsg(scip, "preprocess linear constraint pair <%s>[chgd:%d, upgd:%d] and <%s>[chgd:%d, upgd:%d]\n",
13397 SCIPconsGetName(cons0), cons0changed, cons0upgraded,
13398 SCIPconsGetName(cons1), consdata1->changed, consdata1->upgraded); */
13399
13400 /* if both constraints didn't change since last pair processing, we can ignore the pair */
13401 if( !cons0changed && !consdata1->changed )
13402 continue;
13403
13404 /* if both constraints are already upgraded, skip the pair;
13405 * because changes on these constraints cannot be applied to the instance anymore */
13406 if( cons0upgraded && consdata1->upgraded )
13407 continue;
13408
13409 assert(consdata1->nvars >= 1);
13410
13411 /* sort the constraint */
13412 SCIP_CALL( consdataSort(scip, consdata1) );
13413
13414 /* calculate bit signatures of cons1 for potentially positive and negative coefficients */
13415 consdataCalcSignatures(consdata1);
13416 possignature1 = consdata1->possignature;
13417 negsignature1 = consdata1->negsignature;
13418
13419 /* the signatures give a quick test to check for domination and equality of coefficients */
13420 coefsequal = (possignature0 == possignature1) && (negsignature0 == negsignature1);
13421 coefsnegated = (possignature0 == negsignature1) && (negsignature0 == possignature1);
13422 cons0dominateslhs = SCIPisGE(scip, cons0lhs, consdata1->lhs)
13423 && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13424 && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13425 cons1dominateslhs = SCIPisGE(scip, consdata1->lhs, cons0lhs)
13426 && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13427 && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13428 cons0dominatesrhs = SCIPisLE(scip, cons0rhs, consdata1->rhs)
13429 && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13430 && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13431 cons1dominatesrhs = SCIPisLE(scip, consdata1->rhs, cons0rhs)
13432 && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13433 && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13434 cons1isequality = SCIPisEQ(scip, consdata1->lhs, consdata1->rhs);
13435 tryaggregation = (cons0isequality || cons1isequality) && (maxaggrnormscale > 0.0);
13436 if( !cons0dominateslhs && !cons1dominateslhs && !cons0dominatesrhs && !cons1dominatesrhs
13437 && !coefsequal && !coefsnegated && !tryaggregation )
13438 continue;
13439
13440 /* make sure, we have enough memory for the index set of V_1 \ V_0 */
13441 if( tryaggregation && consdata1->nvars > diffidx1minus0size )
13442 {
13443 SCIP_CALL( SCIPreallocBufferArray(scip, &diffidx1minus0, consdata1->nvars) );
13444 diffidx1minus0size = consdata1->nvars;
13445 }
13446
13447 /* check consdata0 against consdata1:
13448 * - if lhs0 >= lhs1 and for each variable v and each solution value x_v val0[v]*x_v <= val1[v]*x_v,
13449 * consdata0 dominates consdata1 w.r.t. left hand side
13450 * - if rhs0 <= rhs1 and for each variable v and each solution value x_v val0[v]*x_v >= val1[v]*x_v,
13451 * consdata0 dominates consdata1 w.r.t. right hand side
13452 * - if val0[v] == -val1[v] for all variables v, the two inequalities can be replaced by a single
13453 * ranged row (or equality)
13454 * - if at least one constraint is an equality, count the weighted number of common variables W_c
13455 * and the weighted number of variable in the difference sets W_0 = w(V_0 \ V_1), W_1 = w(V_1 \ V_0),
13456 * where the weight of each variable depends on its type, such that aggregations in order to remove the
13457 * number of continuous and integer variables are preferred:
13458 * - if W_c > W_1, try to aggregate consdata0 := a * consdata0 + b * consdata1 in order to decrease the
13459 * variable weight in consdata0, where a = +/- val1[v] and b = -/+ val0[v] for common v which leads to
13460 * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13461 * to be positive to not switch the sense of the (in)equality cons0
13462 * - if W_c > W_0, try to aggregate consdata1 := a * consdata1 + b * consdata0 in order to decrease the
13463 * variable weight in consdata1, where a = +/- val0[v] and b = -/+ val1[v] for common v which leads to
13464 * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13465 * to be positive to not switch the sense of the (in)equality cons1
13466 */
13467
13468 /* check consdata0 against consdata1 for redundancy, or ranged row accumulation */
13469 nvarscommon = 0;
13470 commonidxweight = 0;
13471 nvars0minus1 = 0;
13472 diffidx0minus1weight = 0;
13473 nvars1minus0 = 0;
13474 diffidx1minus0weight = 0;
13475 v0 = 0;
13476 v1 = 0;
13477 while( (v0 < consdata0->nvars || v1 < consdata1->nvars)
13478 && (cons0dominateslhs || cons1dominateslhs || cons0dominatesrhs || cons1dominatesrhs
13479 || coefsequal || coefsnegated || tryaggregation) )
13480 {
13481 SCIP_VAR* var;
13482 SCIP_Real val0;
13483 SCIP_Real val1;
13484 int varcmp;
13485
13486 /* test, if variable appears in only one or in both constraints */
13487 if( v0 < consdata0->nvars && v1 < consdata1->nvars )
13488 varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
13489 else if( v0 < consdata0->nvars )
13490 varcmp = -1;
13491 else
13492 varcmp = +1;
13493
13494 switch( varcmp )
13495 {
13496 case -1:
13497 /* variable doesn't appear in consdata1 */
13498 var = consdata0->vars[v0];
13499 val0 = consdata0->vals[v0];
13500 val1 = 0.0;
13501 if( tryaggregation )
13502 {
13503 diffidx0minus1[nvars0minus1] = v0;
13504 nvars0minus1++;
13505 diffidx0minus1weight += getVarWeight(var);
13506 }
13507 v0++;
13508 coefsequal = FALSE;
13509 coefsnegated = FALSE;
13510 break;
13511
13512 case +1:
13513 /* variable doesn't appear in consdata0 */
13514 var = consdata1->vars[v1];
13515 val0 = 0.0;
13516 val1 = consdata1->vals[v1];
13517 if( tryaggregation )
13518 {
13519 diffidx1minus0[nvars1minus0] = v1;
13520 nvars1minus0++;
13521 diffidx1minus0weight += getVarWeight(var);
13522 }
13523 v1++;
13524 coefsequal = FALSE;
13525 coefsnegated = FALSE;
13526 break;
13527
13528 case 0:
13529 /* variable appears in both constraints */
13530 assert(consdata0->vars[v0] == consdata1->vars[v1]);
13531 var = consdata0->vars[v0];
13532 val0 = consdata0->vals[v0];
13533 val1 = consdata1->vals[v1];
13534 if( tryaggregation )
13535 {
13536 commonidx0[nvarscommon] = v0;
13537 commonidx1[nvarscommon] = v1;
13538 nvarscommon++;
13539 commonidxweight += getVarWeight(var);
13540 }
13541 v0++;
13542 v1++;
13543 coefsequal = coefsequal && (SCIPisEQ(scip, val0, val1));
13544 coefsnegated = coefsnegated && (SCIPisEQ(scip, val0, -val1));
13545 break;
13546
13547 default:
13548 SCIPerrorMessage("invalid comparison result\n");
13549 SCIPABORT();
13550 var = NULL;
13551 val0 = 0.0;
13552 val1 = 0.0;
13553 }
13554 assert(var != NULL);
13555
13556 /* update domination criteria w.r.t. the coefficient and the variable's bounds */
13557 if( SCIPisGT(scip, val0, val1) )
13558 {
13560 {
13561 cons0dominatesrhs = FALSE;
13562 cons1dominateslhs = FALSE;
13563 }
13565 {
13566 cons0dominateslhs = FALSE;
13567 cons1dominatesrhs = FALSE;
13568 }
13569 }
13570 else if( SCIPisLT(scip, val0, val1) )
13571 {
13573 {
13574 cons0dominateslhs = FALSE;
13575 cons1dominatesrhs = FALSE;
13576 }
13578 {
13579 cons0dominatesrhs = FALSE;
13580 cons1dominateslhs = FALSE;
13581 }
13582 }
13583 }
13584
13585 /* check for disaggregated ranged rows */
13586 if( coefsequal || coefsnegated )
13587 {
13588 SCIP_CONS* consstay;
13589 SCIP_CONS* consdel;
13590#ifndef NDEBUG
13591 SCIP_CONSDATA* consdatastay;
13592#endif
13593 SCIP_CONSDATA* consdatadel;
13594 SCIP_Real lhs;
13595 SCIP_Real rhs;
13596 int consinddel;
13597
13598 /* the coefficients in both rows are either equal or negated: create a new constraint with same coefficients and
13599 * best left and right hand sides; delete the old constraints afterwards
13600 */
13601 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with %s coefficients into single ranged row\n",
13602 SCIPconsGetName(cons0), SCIPconsGetName(cons1), coefsequal ? "equal" : "negated");
13603 SCIPdebugPrintCons(scip, cons0, NULL);
13604 SCIPdebugPrintCons(scip, cons1, NULL);
13605
13606 if( coefsequal )
13607 {
13608 /* the coefficients of both rows are equal */
13609 lhs = MAX(consdata0->lhs, consdata1->lhs);
13610 rhs = MIN(consdata0->rhs, consdata1->rhs);
13611 }
13612 else
13613 {
13614 /* the coefficients of both rows are negations */
13615 lhs = MAX(consdata0->lhs, -consdata1->rhs);
13616 rhs = MIN(consdata0->rhs, -consdata1->lhs);
13617 }
13618 if( SCIPisFeasLT(scip, rhs, lhs) )
13619 {
13620 SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13621 *cutoff = TRUE;
13622 break;
13623 }
13624
13625 /* check which constraint has to stay;
13626 * changes applied to an upgraded constraint will not be considered in the instance */
13627 if( consdata0->upgraded )
13628 {
13629 assert(!consdata1->upgraded);
13630 consstay = cons1;
13631#ifndef NDEBUG
13632 consdatastay = consdata1;
13633#endif
13634
13635 consdel = cons0;
13636 consdatadel = consdata0;
13637 consinddel = chkind;
13638 }
13639 else
13640 {
13641 consstay = cons0;
13642#ifndef NDEBUG
13643 consdatastay = consdata0;
13644#endif
13645
13646 consdel = cons1;
13647 consdatadel = consdata1;
13648 consinddel = c;
13649 }
13650
13651 /* update the sides of consstay */
13652 SCIP_CALL( chgLhs(scip, consstay, lhs) );
13653 SCIP_CALL( chgRhs(scip, consstay, rhs) );
13654 if( !consdata0->upgraded )
13655 {
13656 assert(consstay == cons0);
13657 cons0lhs = consdata0->lhs;
13658 cons0rhs = consdata0->rhs;
13659 }
13660
13661 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13662 SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) );
13663
13664 assert( !consdatastay->upgraded );
13665 /* delete consdel */
13666 SCIP_CALL( SCIPdelCons(scip, consdel) );
13667 conss[consinddel] = NULL;
13668 if( !consdatadel->upgraded )
13669 (*ndelconss)++;
13670 continue;
13671 }
13672
13673 /* check for domination: remove dominated sides, but don't touch equalities as long as they are not totally
13674 * redundant
13675 */
13676 if( cons1dominateslhs && (!cons0isequality || cons1dominatesrhs || SCIPisInfinity(scip, consdata0->rhs) ) )
13677 {
13678 /* left hand side is dominated by consdata1: delete left hand side of consdata0 */
13679 SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13680 SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13681 SCIPdebugPrintCons(scip, cons0, NULL);
13682 SCIPdebugPrintCons(scip, cons1, NULL);
13683
13684 /* check for infeasibility */
13685 if( SCIPisFeasGT(scip, consdata1->lhs, consdata0->rhs) )
13686 {
13687 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13688 *cutoff = TRUE;
13689 break;
13690 }
13691
13692 /* remove redundant left hand side */
13693 if( !SCIPisInfinity(scip, -consdata0->lhs) )
13694 {
13695 SCIP_CALL( chgLhs(scip, cons0, -SCIPinfinity(scip)) );
13696 cons0lhs = consdata0->lhs;
13697 cons0isequality = FALSE;
13698 if( !consdata0->upgraded )
13699 {
13700 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13701 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13702
13703 (*nchgsides)++;
13704 }
13705 }
13706 }
13707 else if( cons0dominateslhs && (!cons1isequality || cons0dominatesrhs || SCIPisInfinity(scip, consdata1->rhs)) )
13708 {
13709 /* left hand side is dominated by consdata0: delete left hand side of consdata1 */
13710 SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13711 SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13712 SCIPdebugPrintCons(scip, cons1, NULL);
13713 SCIPdebugPrintCons(scip, cons0, NULL);
13714
13715 /* check for infeasibility */
13716 if( SCIPisFeasGT(scip, consdata0->lhs, consdata1->rhs) )
13717 {
13718 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13719 *cutoff = TRUE;
13720 break;
13721 }
13722
13723 /* remove redundant left hand side */
13724 if( !SCIPisInfinity(scip, -consdata1->lhs) )
13725 {
13726 SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
13727 cons1isequality = FALSE;
13728 if( !consdata1->upgraded )
13729 {
13730 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13731 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13732
13733 (*nchgsides)++;
13734 }
13735 }
13736 }
13737 if( cons1dominatesrhs && (!cons0isequality || cons1dominateslhs || SCIPisInfinity(scip, -consdata0->lhs)) )
13738 {
13739 /* right hand side is dominated by consdata1: delete right hand side of consdata0 */
13740 SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13741 SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13742 SCIPdebugPrintCons(scip, cons0, NULL);
13743 SCIPdebugPrintCons(scip, cons1, NULL);
13744
13745 /* check for infeasibility */
13746 if( SCIPisFeasLT(scip, consdata1->rhs, consdata0->lhs) )
13747 {
13748 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13749 *cutoff = TRUE;
13750 break;
13751 }
13752
13753 /* remove redundant right hand side */
13754 if( !SCIPisInfinity(scip, consdata0->rhs) )
13755 {
13756 SCIP_CALL( chgRhs(scip, cons0, SCIPinfinity(scip)) );
13757 cons0rhs = consdata0->rhs;
13758 cons0isequality = FALSE;
13759 if( !consdata0->upgraded )
13760 {
13761 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13762 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13763
13764 (*nchgsides)++;
13765 }
13766 }
13767 }
13768 else if( cons0dominatesrhs && (!cons1isequality || cons0dominateslhs || SCIPisInfinity(scip, -consdata1->lhs)) )
13769 {
13770 /* right hand side is dominated by consdata0: delete right hand side of consdata1 */
13771 SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13772 SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13773 SCIPdebugPrintCons(scip, cons1, NULL);
13774 SCIPdebugPrintCons(scip, cons0, NULL);
13775
13776 /* check for infeasibility */
13777 if( SCIPisFeasLT(scip, consdata0->rhs, consdata1->lhs) )
13778 {
13779 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13780 *cutoff = TRUE;
13781 break;
13782 }
13783
13784 /* remove redundant right hand side */
13785 if( !SCIPisInfinity(scip, consdata1->rhs) )
13786 {
13787 SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
13788 cons1isequality = FALSE;
13789 if( !consdata1->upgraded )
13790 {
13791 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13792 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13793
13794 (*nchgsides)++;
13795 }
13796 }
13797 }
13798
13799 /* check for now redundant constraints */
13800 if( SCIPisInfinity(scip, -consdata0->lhs) && SCIPisInfinity(scip, consdata0->rhs) )
13801 {
13802 /* consdata0 became redundant */
13803 SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons0));
13804 SCIP_CALL( SCIPdelCons(scip, cons0) );
13805 conss[chkind] = NULL;
13806 if( !consdata0->upgraded )
13807 {
13808 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13809 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13810
13811 (*ndelconss)++;
13812 }
13813 continue;
13814 }
13815 if( SCIPisInfinity(scip, -consdata1->lhs) && SCIPisInfinity(scip, consdata1->rhs) )
13816 {
13817 /* consdata1 became redundant */
13818 SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons1));
13819 SCIP_CALL( SCIPdelCons(scip, cons1) );
13820 conss[c] = NULL;
13821 if( !consdata1->upgraded )
13822 {
13823 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13824 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13825
13826 (*ndelconss)++;
13827 }
13828 continue;
13829 }
13830
13831 /* check, if we want to aggregate an (in)equality with an equality:
13832 * consdata0 := a * consdata0 + b * consdata1 or consdata1 := a * consdata1 + b * consdata0
13833 */
13834 if( tryaggregation )
13835 {
13836 SCIP_Bool aggregated;
13837
13838 assert(consdata0->nvars == nvarscommon + nvars0minus1);
13839 assert(consdata1->nvars == nvarscommon + nvars1minus0);
13840
13841 aggregated = FALSE;
13842 if( cons1isequality && !consdata0->upgraded && commonidxweight > diffidx1minus0weight )
13843 {
13844 /* W_c > W_1: try to aggregate consdata0 := a * consdata0 + b * consdata1 */
13845 SCIP_CALL( aggregateConstraints(scip, cons0, cons1, commonidx0, commonidx1, diffidx0minus1, diffidx1minus0,
13846 nvarscommon, commonidxweight, diffidx0minus1weight, diffidx1minus0weight, maxaggrnormscale,
13847 nchgcoefs, &aggregated, cutoff) );
13848
13849 if( *cutoff )
13850 break;
13851
13852 /* update array of active constraints */
13853 if( aggregated )
13854 {
13855 assert(!SCIPconsIsActive(cons0));
13856 assert(SCIPconsIsActive(cons1));
13857 conss[chkind] = NULL;
13858 }
13859 }
13860 if( !aggregated && cons0isequality && !consdata1->upgraded && commonidxweight > diffidx0minus1weight )
13861 {
13862 /* W_c > W_0: try to aggregate consdata1 := a * consdata1 + b * consdata0 */
13863 SCIP_CALL( aggregateConstraints(scip, cons1, cons0, commonidx1, commonidx0, diffidx1minus0, diffidx0minus1,
13864 nvarscommon, commonidxweight, diffidx1minus0weight, diffidx0minus1weight, maxaggrnormscale,
13865 nchgcoefs, &aggregated, cutoff) );
13866
13867 if( *cutoff )
13868 break;
13869
13870 /* update array of active constraints */
13871 if( aggregated )
13872 {
13873 assert(!SCIPconsIsActive(cons1));
13874 assert(SCIPconsIsActive(cons0));
13875 conss[c] = NULL;
13876 }
13877 }
13878 }
13879 }
13880
13881 /* free temporary memory */
13882 SCIPfreeBufferArray(scip, &diffidx1minus0);
13883 SCIPfreeBufferArray(scip, &diffidx0minus1);
13884 SCIPfreeBufferArray(scip, &commonidx1);
13885 SCIPfreeBufferArray(scip, &commonidx0);
13886
13887 return SCIP_OKAY;
13888}
13889
13890/** do stuffing presolving on a single constraint */
13891static
13893 SCIP* scip, /**< SCIP data structure */
13894 SCIP_CONS* cons, /**< linear constraint */
13895 SCIP_Bool singletonstuffing, /**< should stuffing of singleton continuous variables be performed? */
13896 SCIP_Bool singlevarstuffing, /**< should single variable stuffing be performed, which tries to fulfill
13897 * constraints using the cheapest variable? */
13898 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13899 int* nfixedvars, /**< pointer to count the total number of fixed variables */
13900 int* nchgbds /**< pointer to count the total number of tightened bounds */
13901 )
13902{
13903 SCIP_CONSDATA* consdata;
13904 SCIP_Real* ratios;
13905 int* varpos;
13906 SCIP_Bool* swapped;
13907 SCIP_VAR** vars;
13908 SCIP_Real* vals;
13909 SCIP_VAR* var;
13910 SCIP_Real lb;
13911 SCIP_Real ub;
13912 SCIP_Real minactivity;
13913 SCIP_Real maxactivity;
13914 SCIP_Real maxcondactivity;
13915 SCIP_Real mincondactivity;
13916 SCIP_Real rhs;
13917 SCIP_Real val;
13918 SCIP_Real obj;
13919 SCIP_Real factor;
13920 SCIP_Bool isminacttight;
13921 SCIP_Bool ismaxacttight;
13922 SCIP_Bool isminsettoinfinity;
13923 SCIP_Bool ismaxsettoinfinity;
13924 SCIP_Bool tryfixing;
13925 int nsingletons;
13926 int idx;
13927 int v;
13928 int nvars;
13929
13930 assert(scip != NULL);
13931 assert(cons != NULL);
13932 assert(nfixedvars != NULL);
13933
13934 consdata = SCIPconsGetData(cons);
13935
13936 /* we only want to run for inequalities */
13937 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->lhs) )
13938 return SCIP_OKAY;
13939
13940 if( singlevarstuffing )
13941 {
13942 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
13943 &isminsettoinfinity, &ismaxsettoinfinity);
13944 }
13945 else
13946 {
13947 minactivity = SCIP_INVALID;
13948 maxactivity = SCIP_INVALID;
13949 isminsettoinfinity = FALSE;
13950 ismaxsettoinfinity = FALSE;
13951 }
13952
13953 /* we want to have a <= constraint, if the rhs is infinite, we implicitly multiply the constraint by -1,
13954 * the new maxactivity is minus the old minactivity then
13955 */
13956 if( SCIPisInfinity(scip, consdata->rhs) )
13957 {
13958 rhs = -consdata->lhs;
13959 factor = -1.0;
13960 maxactivity = -minactivity;
13961 ismaxsettoinfinity = isminsettoinfinity;
13962 }
13963 else
13964 {
13965 assert(SCIPisInfinity(scip, -consdata->lhs));
13966 rhs = consdata->rhs;
13967 factor = 1.0;
13968 }
13969
13970 nvars = consdata->nvars;
13971 vars = consdata->vars;
13972 vals = consdata->vals;
13973
13974 /* check for continuous singletons */
13975 if( singletonstuffing )
13976 {
13977 for( v = 0; v < nvars; ++v )
13978 {
13979 var = vars[v];
13980
13983 break;
13984 }
13985 }
13986 else
13987 /* we don't want to go into the next block */
13988 v = nvars;
13989
13990 /* a singleton was found -> perform singleton variable stuffing */
13991 if( v < nvars )
13992 {
13993 assert(singletonstuffing);
13994
13998
13999 tryfixing = TRUE;
14000 nsingletons = 0;
14001 mincondactivity = 0.0;
14002 maxcondactivity = 0.0;
14003
14004 for( v = 0; v < nvars; ++v )
14005 {
14006 var = vars[v];
14007 lb = SCIPvarGetLbGlobal(var);
14008 ub = SCIPvarGetUbGlobal(var);
14010 val = factor * vals[v];
14011
14012 assert(!SCIPisZero(scip, val));
14013
14014 /* the variable is a singleton and continuous */
14017 {
14018 if( SCIPisNegative(scip, obj) && val > 0 )
14019 {
14020 /* case 1: obj < 0 and coef > 0 */
14021 if( SCIPisInfinity(scip, -lb) )
14022 {
14023 tryfixing = FALSE;
14024 break;
14025 }
14026
14027 maxcondactivity += val * lb;
14028 mincondactivity += val * lb;
14029 swapped[v] = FALSE;
14030 ratios[nsingletons] = obj / val;
14031 varpos[nsingletons] = v;
14032 nsingletons++;
14033 }
14034 else if( SCIPisPositive(scip, obj) && val < 0 )
14035 {
14036 /* case 2: obj > 0 and coef < 0 */
14037 if( SCIPisInfinity(scip, ub) )
14038 {
14039 tryfixing = FALSE;
14040 break;
14041 }
14042 /* multiply column by (-1) to become case 1.
14043 * now bounds are swapped: ub := -lb, lb := -ub
14044 */
14045
14046 maxcondactivity += val * ub;
14047 mincondactivity += val * ub;
14048 swapped[v] = TRUE;
14049 ratios[nsingletons] = obj / val;
14050 varpos[nsingletons] = v;
14051 nsingletons++;
14052 }
14053 else if( val > 0 )
14054 {
14055 /* case 3: obj >= 0 and coef >= 0 is handled by duality fixing.
14056 * we only consider the lower bound for the constants
14057 */
14059
14060 if( SCIPisInfinity(scip, -lb) )
14061 {
14062 /* maybe unbounded */
14063 tryfixing = FALSE;
14064 break;
14065 }
14066
14067 maxcondactivity += val * lb;
14068 mincondactivity += val * lb;
14069 }
14070 else
14071 {
14072 /* case 4: obj <= 0 and coef <= 0 is also handled by duality fixing.
14073 * we only consider the upper bound for the constants
14074 */
14076 assert(val < 0);
14077
14078 if( SCIPisInfinity(scip, ub) )
14079 {
14080 /* maybe unbounded */
14081 tryfixing = FALSE;
14082 break;
14083 }
14084
14085 maxcondactivity += val * ub;
14086 mincondactivity += val * ub;
14087 }
14088 }
14089 else
14090 {
14091 /* consider contribution of discrete variables, non-singleton
14092 * continuous variables and variables with more than one lock
14093 */
14094 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14095 {
14096 tryfixing = FALSE;
14097 break;
14098 }
14099
14100 if( val > 0 )
14101 {
14102 maxcondactivity += val * ub;
14103 mincondactivity += val * lb;
14104 }
14105 else
14106 {
14107 maxcondactivity += val * lb;
14108 mincondactivity += val * ub;
14109 }
14110 }
14111 }
14112 if( tryfixing && nsingletons > 0 && (SCIPisGT(scip, rhs, maxcondactivity) || SCIPisLE(scip, rhs, mincondactivity)) )
14113 {
14114 SCIP_Real delta;
14115 SCIP_Bool tightened;
14116#ifdef SCIP_DEBUG
14117 int oldnfixedvars = *nfixedvars;
14118#endif
14119
14120 SCIPsortRealInt(ratios, varpos, nsingletons);
14121
14122 /* verify which singleton continuous variables can be fixed */
14123 for( v = 0; v < nsingletons; ++v )
14124 {
14125 idx = varpos[v];
14126 var = vars[idx];
14127 val = factor * vals[idx];
14128 lb = SCIPvarGetLbGlobal(var);
14129 ub = SCIPvarGetUbGlobal(var);
14130
14132 assert((val < 0) == swapped[idx]);
14133 val = REALABS(val);
14134
14135 /* stop fixing if variable bounds are not finite */
14136 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14137 break;
14138
14142
14143 /* calculate the change in the row activities if this variable changes
14144 * its value from its worst to its best bound
14145 */
14146 if( swapped[idx] )
14147 delta = -(lb - ub) * val;
14148 else
14149 delta = (ub - lb) * val;
14150
14151 assert(!SCIPisNegative(scip, delta));
14152
14153 if( SCIPisLE(scip, delta, rhs - maxcondactivity) )
14154 {
14155 if( swapped[idx] )
14156 {
14157 SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14158 SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14159 }
14160 else
14161 {
14162 SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14163 SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14164 }
14165
14166 if( *cutoff )
14167 break;
14168 if( tightened )
14169 {
14170 (*nfixedvars)++;
14171 }
14172 }
14173 /* @note: we could in theory tighten the bound of the first singleton variable which does not fall into the above case,
14174 * since it cannot be fully fixed. However, this is not needed and should be done by activity-based bound tightening
14175 * anyway after all other continuous singleton columns were fixed; doing it here may introduce numerical
14176 * troubles in case of large bounds.
14177 */
14178 else if( SCIPisLE(scip, rhs, mincondactivity) )
14179 {
14180 if( swapped[idx] )
14181 {
14182 SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14183 SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14184 }
14185 else
14186 {
14187 SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14188 SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14189 }
14190
14191 if( *cutoff )
14192 break;
14193 if( tightened )
14194 {
14195 (*nfixedvars)++;
14196 }
14197 }
14198
14199 maxcondactivity += delta;
14200 mincondactivity += delta;
14201 }
14202
14203#ifdef SCIP_DEBUG
14204 if( *nfixedvars - oldnfixedvars > 0 )
14205 {
14206 SCIPdebugMsg(scip, "### stuffing fixed %d variables\n", *nfixedvars - oldnfixedvars);
14207 }
14208#endif
14209 }
14210
14211 SCIPfreeBufferArray(scip, &swapped);
14212 SCIPfreeBufferArray(scip, &ratios);
14213 SCIPfreeBufferArray(scip, &varpos);
14214 }
14215
14216 /* perform single-variable stuffing:
14217 * for a linear inequality
14218 * a_1 x_1 + a_2 x_2 + ... + a_n x_n <= b
14219 * with a_i > 0 and objective coefficients c_i < 0,
14220 * setting all variables to their upper bound (giving us the maximal activity of the constraint) is worst w.r.t.
14221 * feasibility of the constraint. On the other hand, this gives the best objective function contribution of the
14222 * variables contained in the constraint. The maximal activity should be larger than the rhs, otherwise the constraint
14223 * is redundant.
14224 * Now we are searching for a variable x_k with maximal ratio c_k / a_k (note that all these ratios are negative), so
14225 * that by reducing the value of this variable we reduce the activity of the constraint while having the smallest
14226 * objective deterioration per activity unit. If x_k has no downlocks, is continuous, and can be reduced enough to
14227 * render the constraint feasible, and ALL other variables have only the one uplock installed by the current constraint,
14228 * we can reduce the upper bound of x_k such that the maxactivity equals the rhs and fix all other variables to their
14229 * upper bound.
14230 * Note that the others variables may have downlocks from other constraints, which we do not need to care
14231 * about since we are setting them to the highest possible value. Also, they may be integer or binary, because the
14232 * computed ratio is still a lower bound on the change in the objective caused by reducing those variable to reach
14233 * constraint feasibility. On the other hand, uplocks on x_k from other constraint do no interfer with the method.
14234 * With a slight adjustment, the procedure even works for integral x_k. If (maxactivity - rhs)/val is integral,
14235 * the variable gets an integral value in order to fulfill the constraint tightly, and we can just apply the procedure.
14236 * If (maxactivity - rhs)/val is fractional, we need to check, if overfulfilling the constraint by setting x_k to
14237 * ceil((maxactivity - rhs)/val) is still better than setting x_k to ceil((maxactivity - rhs)/val) - 1 and
14238 * filling the remaining gap in the constraint with the next-best variable. For this, we check that
14239 * c_k * ceil((maxactivity - rhs)/val) is still better than
14240 * c_k * floor((maxactivity - rhs)/val) + c_j * ((maxactivity - rhs) - (floor((maxactivity - rhs)/val) * val))/a_j.
14241 * In this case, the upper bound of x_k is decreased to ub_k - ceil(maxactivity - rhs).
14242 * If there are variables with a_i < 0 and c_i > 0, they are negated to obtain the above form, variables with same
14243 * sign of coefficients in constraint and objective prevent the use of this method.
14244 */
14245 if( singlevarstuffing && !ismaxsettoinfinity )
14246 {
14247 SCIP_Real bestratio = -SCIPinfinity(scip);
14248 SCIP_Real secondbestratio = -SCIPinfinity(scip);
14249 SCIP_Real ratio;
14250 int bestindex = -1;
14251 int bestuplocks = 0;
14252 int bestdownlocks = 1;
14253 int downlocks;
14254 int uplocks;
14255 SCIPdebug( int oldnfixedvars = *nfixedvars; )
14256 SCIPdebug( int oldnchgbds = *nchgbds; )
14257
14258 /* loop over all variables to identify the best and second-best ratio */
14259 for( v = 0; v < nvars; ++v )
14260 {
14261 var = vars[v];
14263 val = factor * vals[v];
14264
14265 assert(!SCIPisZero(scip, val));
14266
14267 ratio = obj / val;
14268
14269 /* if both objective and constraint push the variable to the same direction, we can do nothing here */
14270 if( !SCIPisNegative(scip, ratio) )
14271 {
14272 bestindex = -1;
14273 break;
14274 }
14275
14276 if( val > 0 )
14277 {
14280 }
14281 else
14282 {
14285 }
14286
14287 /* better ratio, update best candidate
14288 * @todo use some tolerance
14289 * @todo check size of domain and updated ratio for integer variables already?
14290 */
14291 if( ratio > bestratio || ( downlocks == 0 && ratio == bestratio && ( bestdownlocks > 0 /*lint !e777*/
14292 || ( !SCIPvarIsIntegral(var) && SCIPvarIsIntegral(vars[bestindex]) ) ) ) )
14293 {
14294 /* best index becomes second-best*/
14295 if( bestindex != -1 )
14296 {
14297 /* second-best index must not have more than 1 uplock */
14298 if( bestuplocks > 1 )
14299 {
14300 bestindex = -1;
14301 break;
14302 }
14303 else
14304 {
14305 secondbestratio = bestratio;
14306 }
14307 }
14308 bestdownlocks = downlocks;
14309 bestuplocks = uplocks;
14310 bestratio = ratio;
14311 bestindex = v;
14312
14313 /* if this variable is the best in the end, we cannot do reductions since it has a downlocks,
14314 * if it is not the best, it has too many uplocks -> not applicable
14315 */
14316 if( bestdownlocks > 0 && bestuplocks > 1 )
14317 {
14318 bestindex = -1;
14319 break;
14320 }
14321 }
14322 else
14323 {
14324 /* non-best index must not have more than 1 uplock */
14325 if( uplocks > 1 )
14326 {
14327 bestindex = -1;
14328 break;
14329 }
14330 /* update second-best ratio */
14331 if( ratio > secondbestratio )
14332 {
14333 secondbestratio = ratio;
14334 }
14335 }
14336 }
14337
14338 /* check if we can apply single variable stuffing */
14339 if( bestindex != -1 && bestdownlocks == 0 )
14340 {
14341 SCIP_Bool tightened = FALSE;
14342 SCIP_Real bounddelta;
14343
14344 var = vars[bestindex];
14346 val = factor * vals[bestindex];
14347 lb = SCIPvarGetLbGlobal(var);
14348 ub = SCIPvarGetUbGlobal(var);
14349 tryfixing = TRUE;
14350
14351 if( val < 0 )
14352 {
14354
14355 /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14356 if( SCIPvarIsIntegral(var) && !SCIPisIntegral(scip, (maxactivity - rhs) / val) )
14357 {
14358 SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/-val);
14359 SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * -val);
14360 assert(SCIPisPositive(scip, activitydelta));
14361
14362 tryfixing = SCIPisLE(scip, obj, -activitydelta * secondbestratio);
14363
14364 bounddelta = SCIPceil(scip, (maxactivity - rhs)/-val);
14365 assert(SCIPisPositive(scip, bounddelta));
14366 }
14367 else
14368 bounddelta = (maxactivity - rhs)/-val;
14369
14370 tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14371
14372 if( tryfixing )
14373 {
14375
14376 if( SCIPisEQ(scip, lb + bounddelta, ub) )
14377 {
14378 SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), lb + bounddelta);
14379 SCIP_CALL( SCIPfixVar(scip, var, lb + bounddelta, cutoff, &tightened) );
14380 }
14381 else
14382 {
14383 SCIPdebugMsg(scip, "tighten the lower bound of <%s> from %g to %g (ub=%g)\n", SCIPvarGetName(var), lb, lb + bounddelta, ub);
14384 SCIP_CALL( SCIPtightenVarLb(scip, var, lb + bounddelta, FALSE, cutoff, &tightened) );
14385 }
14386 }
14387 }
14388 else
14389 {
14391
14392 /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14393 if( SCIPvarIsIntegral(var) && !SCIPisIntegral(scip, (maxactivity - rhs) / val) )
14394 {
14395 SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/val);
14396 SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * val);
14397 assert(SCIPisPositive(scip, activitydelta));
14398
14399 tryfixing = SCIPisLE(scip, -obj, activitydelta * secondbestratio);
14400
14401 bounddelta = SCIPceil(scip, (maxactivity - rhs)/val);
14402 assert(SCIPisPositive(scip, bounddelta));
14403 }
14404 else
14405 bounddelta = (maxactivity - rhs)/val;
14406
14407 tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14408
14409 if( tryfixing )
14410 {
14412
14413 if( SCIPisEQ(scip, ub - bounddelta, lb) )
14414 {
14415 SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), ub - bounddelta);
14416 SCIP_CALL( SCIPfixVar(scip, var, ub - bounddelta, cutoff, &tightened) );
14417 }
14418 else
14419 {
14420 SCIPdebugMsg(scip, "tighten the upper bound of <%s> from %g to %g (lb=%g)\n", SCIPvarGetName(var), ub, ub - bounddelta, lb);
14421 SCIP_CALL( SCIPtightenVarUb(scip, var, ub - bounddelta, FALSE, cutoff, &tightened) );
14422 }
14423 }
14424 }
14425
14426 if( *cutoff )
14427 return SCIP_OKAY;
14428 if( tightened )
14429 {
14431 ++(*nfixedvars);
14432 else
14433 ++(*nchgbds);
14434
14435 SCIPdebugMsg(scip, "cons <%s>: %g <=\n", SCIPconsGetName(cons), factor > 0 ? consdata->lhs : -consdata->rhs);
14436 for( v = 0; v < nvars; ++v )
14437 {
14438 SCIPdebugMsg(scip, "%+g <%s>([%g,%g],%g,[%d,%d],%s)\n", factor * vals[v], SCIPvarGetName(vars[v]),
14442 SCIPvarIsIntegral(vars[v]) ? "I" : "C");
14443 }
14444 SCIPdebugMsg(scip, "<= %g\n", factor > 0 ? consdata->rhs : -consdata->lhs);
14445
14446 for( v = 0; v < nvars; ++v )
14447 {
14448 if( v == bestindex )
14449 continue;
14450
14451 if( factor * vals[v] < 0 )
14452 {
14454 SCIPdebugMsg(scip, "fix <%s> to its lower bound (%g)\n",
14456 SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetLbGlobal(vars[v]), cutoff, &tightened) );
14457 }
14458 else
14459 {
14461 SCIPdebugMsg(scip, "fix <%s> to its upper bound (%g)\n",
14463 SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetUbGlobal(vars[v]), cutoff, &tightened) );
14464 }
14465
14466 if( *cutoff )
14467 return SCIP_OKAY;
14468 if( tightened )
14469 ++(*nfixedvars);
14470 }
14471 SCIPdebug( SCIPdebugMsg(scip, "### new stuffing fixed %d vars, tightened %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds); )
14472 }
14473 }
14474 }
14475
14476 return SCIP_OKAY;
14477}
14478
14479/** applies full dual presolving on variables that only appear in linear constraints */
14480static
14482 SCIP* scip, /**< SCIP data structure */
14483 SCIP_CONS** conss, /**< constraint set */
14484 int nconss, /**< number of constraints */
14485 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14486 int* nchgbds, /**< pointer to count the number of bound changes */
14487 int* nchgvartypes /**< pointer to count the number of variable type changes */
14488 )
14489{
14490 SCIP_Real* redlb;
14491 SCIP_Real* redub;
14492 int* nlocksdown;
14493 int* nlocksup;
14494 SCIP_Bool* isimplint;
14495 SCIP_VAR** origvars;
14496 SCIP_VAR** vars;
14497 SCIP_VAR** conscontvars;
14498 int nvars;
14499 int nbinvars;
14500 int nintvars;
14501 int ncontvars;
14502 int v;
14503 int c;
14504
14505 /* we calculate redundancy bounds with the following meaning:
14506 * redlb[v] == k : if x_v >= k, we can always round x_v down to x_v == k without violating any constraint
14507 * redub[v] == k : if x_v <= k, we can always round x_v up to x_v == k without violating any constraint
14508 * then:
14509 * c_v >= 0 : x_v <= redlb[v] is feasible due to optimality
14510 * c_v <= 0 : x_v >= redub[v] is feasible due to optimality
14511 */
14512
14513 /* Additionally, we detect continuous variables that are implied integral.
14514 * A continuous variable j is implied integral if it only has only +/-1 coefficients,
14515 * and all constraints (including the bounds as trivial constraints) in which:
14516 * c_j > 0: the variable is down-locked,
14517 * c_j < 0: the variable is up-locked,
14518 * c_j = 0: the variable appears
14519 * have, apart from j, only integer variables with integral coefficients and integral sides.
14520 * This is because then, the value of the variable is either determined by one of its bounds or
14521 * by one of these constraints, and in all cases, the value of the variable is integral.
14522 */
14523
14524 assert(scip != NULL);
14525 assert(nconss == 0 || conss != NULL);
14526 assert(nchgbds != NULL);
14528
14529 /* get active variables */
14531 origvars = SCIPgetVars(scip);
14532
14533 /* if the problem is a pure binary program, nothing can be achieved by full dual presolve */
14534 nbinvars = SCIPgetNBinVars(scip);
14535 if( nbinvars == nvars )
14536 return SCIP_OKAY;
14537
14538 /* get number of continuous variables */
14539 ncontvars = SCIPgetNContVars(scip);
14540 nintvars = nvars - ncontvars;
14541
14542 /* copy the variable array since this array might change during the curse of this algorithm */
14543 nvars = nvars - nbinvars;
14544 SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &(origvars[nbinvars]), nvars) );
14545
14546 /* allocate temporary memory */
14549 SCIP_CALL( SCIPallocBufferArray(scip, &nlocksdown, nvars) );
14550 SCIP_CALL( SCIPallocBufferArray(scip, &nlocksup, nvars) );
14551 SCIP_CALL( SCIPallocBufferArray(scip, &isimplint, ncontvars) );
14552 SCIP_CALL( SCIPallocBufferArray(scip, &conscontvars, ncontvars) );
14553
14554 /* initialize redundancy bounds */
14555 for( v = 0; v < nvars; ++v )
14556 {
14558 redlb[v] = SCIPvarGetLbGlobal(vars[v]);
14559 redub[v] = SCIPvarGetUbGlobal(vars[v]);
14560 }
14561 BMSclearMemoryArray(nlocksdown, nvars);
14562 BMSclearMemoryArray(nlocksup, nvars);
14563
14564 /* Initialize isimplint array: variable may be implied integral if rounded to their best bound they are integral
14565 * we better not use SCIPisFeasIntegral() in these checks.
14566 */
14567 for( v = 0; v < ncontvars; v++ )
14568 {
14569 SCIP_VAR* var;
14570 SCIP_Real obj;
14571 SCIP_Real lb;
14572 SCIP_Real ub;
14573
14574 var = vars[v + nintvars - nbinvars];
14576
14577 lb = SCIPvarGetLbGlobal(var);
14578 ub = SCIPvarGetUbGlobal(var);
14579
14581 if( SCIPisZero(scip, obj) )
14582 isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb)) && (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14583 else
14584 {
14585 if( SCIPisPositive(scip, obj) )
14586 isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb));
14587 else
14588 {
14590 isimplint[v] = (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14591 }
14592 }
14593 }
14594
14595 /* scan all constraints */
14596 for( c = 0; c < nconss; ++c )
14597 {
14598 /* we only need to consider constraints that have been locked (i.e., checked constraints or constraints that are
14599 * part of checked disjunctions)
14600 */
14601 if( SCIPconsIsLocked(conss[c]) )
14602 {
14603 SCIP_CONSDATA* consdata;
14604 SCIP_Bool lhsexists;
14605 SCIP_Bool rhsexists;
14606 SCIP_Bool hasimpliedpotential;
14607 SCIP_Bool integralcoefs;
14608 int nlockspos;
14609 int contvarpos;
14610 int nconscontvars;
14611 int i;
14612
14613 consdata = SCIPconsGetData(conss[c]);
14614 assert(consdata != NULL);
14615
14616 /* get number of times the constraint was locked */
14617 nlockspos = SCIPconsGetNLocksPos(conss[c]);
14618
14619 /* we do not want to include constraints with locked negation (this would be too weird) */
14620 if( SCIPconsGetNLocksNeg(conss[c]) > 0 )
14621 {
14622 /* mark all non-implied continuous variables */
14623 for( i = 0; i < consdata->nvars; ++i )
14624 {
14625 SCIP_VAR* var;
14626
14627 var = consdata->vars[i];
14628 if( !SCIPvarIsIntegral(var) )
14629 {
14630 int contv;
14631 contv = SCIPvarGetProbindex(var) - nintvars;
14632 assert(0 <= contv && contv < ncontvars); /* variable should be active due to applyFixings() */
14633 isimplint[contv] = FALSE;
14634 }
14635 }
14636 continue;
14637 }
14638
14639 /* check for existing sides */
14640 lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
14641 rhsexists = !SCIPisInfinity(scip, consdata->rhs);
14642
14643 /* count locks and update redundancy bounds */
14644 contvarpos = -1;
14645 nconscontvars = 0;
14646 hasimpliedpotential = FALSE;
14647 integralcoefs = !SCIPconsIsModifiable(conss[c]);
14648
14649 for( i = 0; i < consdata->nvars; ++i )
14650 {
14651 SCIP_VAR* var;
14652 SCIP_Real val;
14653 SCIP_Real minresactivity;
14654 SCIP_Real maxresactivity;
14655 SCIP_Real newredlb;
14656 SCIP_Real newredub;
14657 SCIP_Bool ismintight;
14658 SCIP_Bool ismaxtight;
14659 SCIP_Bool isminsettoinfinity;
14660 SCIP_Bool ismaxsettoinfinity;
14661 int arrayindex;
14662
14663 var = consdata->vars[i];
14664 assert(var != NULL);
14665 val = consdata->vals[i];
14666 assert(!SCIPisZero(scip, val));
14667
14668 /* check if still all integer variables have integral coefficients */
14669 if( SCIPvarIsIntegral(var) )
14670 integralcoefs = integralcoefs && SCIPisIntegral(scip, val);
14671
14672 /* we do not need to process binary variables */
14673 if( SCIPvarIsBinary(var) )
14674 continue;
14675
14676 if( SCIPconsIsModifiable(conss[c]) )
14677 {
14678 minresactivity = -SCIPinfinity(scip);
14679 maxresactivity = SCIPinfinity(scip);
14680 isminsettoinfinity = TRUE;
14681 ismaxsettoinfinity = TRUE;
14682 }
14683 else
14684 {
14685 /* calculate residual activity bounds if variable would be fixed to zero */
14686 consdataGetGlbActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
14687 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
14688
14689 /* We called consdataGetGlbActivityResiduals() saying that we do not need a good relaxation,
14690 * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
14691 * This is needed, because we do not want to rely on relaxed finite resactivities.
14692 */
14693 assert((ismintight || isminsettoinfinity) && (ismaxtight || ismaxsettoinfinity));
14694
14695 /* check minresactivity for reliability */
14696 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
14697 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, TRUE);
14698
14699 /* check maxresactivity for reliability */
14700 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
14701 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, TRUE);
14702 }
14703
14704 arrayindex = SCIPvarGetProbindex(var) - nbinvars;
14705
14706 assert(0 <= arrayindex && arrayindex < nvars); /* variable should be active due to applyFixings() */
14707
14708 newredlb = redlb[arrayindex];
14709 newredub = redub[arrayindex];
14710 if( val > 0.0 )
14711 {
14712 if( lhsexists )
14713 {
14714 /* lhs <= d*x + a*y, d > 0 -> redundant in y if x >= (lhs - min{a*y})/d */
14715 nlocksdown[arrayindex] += nlockspos;
14716 newredlb = (isminsettoinfinity ? SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14717 }
14718 if( rhsexists )
14719 {
14720 /* d*x + a*y <= rhs, d > 0 -> redundant in y if x <= (rhs - max{a*y})/d */
14721 nlocksup[arrayindex] += nlockspos;
14722 newredub = (ismaxsettoinfinity ? -SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14723 }
14724 }
14725 else
14726 {
14727 if( lhsexists )
14728 {
14729 /* lhs <= d*x + a*y, d < 0 -> redundant in y if x <= (lhs - min{a*y})/d */
14730 nlocksup[arrayindex] += nlockspos;
14731 newredub = (isminsettoinfinity ? -SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14732 }
14733 if( rhsexists )
14734 {
14735 /* d*x + a*y <= rhs, d < 0 -> redundant in y if x >= (rhs - max{a*y})/d */
14736 nlocksdown[arrayindex] += nlockspos;
14737 newredlb = (ismaxsettoinfinity ? SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14738 }
14739 }
14740
14741 /* if the variable is integer, we have to round the value to the next integral value */
14742 if( SCIPvarIsIntegral(var) )
14743 {
14744 if( !SCIPisInfinity(scip, newredlb) )
14745 newredlb = SCIPceil(scip, newredlb);
14746 if( !SCIPisInfinity(scip, -newredub) )
14747 newredub = SCIPfloor(scip, newredub);
14748 }
14749
14750 /* update redundancy bounds */
14751 redlb[arrayindex] = MAX(redlb[arrayindex], newredlb);
14752 redub[arrayindex] = MIN(redub[arrayindex], newredub);
14753
14754 /* collect the continuous variables of the constraint */
14755 if( !SCIPvarIsIntegral(var) )
14756 {
14757 int contv;
14758
14759 assert(nconscontvars < ncontvars);
14760 contvarpos = i;
14761 conscontvars[nconscontvars] = var;
14762 nconscontvars++;
14763
14764 contv = SCIPvarGetProbindex(var) - nintvars;
14765 assert(0 <= contv && contv < ncontvars);
14766 hasimpliedpotential = hasimpliedpotential || isimplint[contv];
14767 }
14768 }
14769
14770 /* update implied integrality status of continuous variables */
14771 if( hasimpliedpotential )
14772 {
14773 if( nconscontvars > 1 || !integralcoefs )
14774 {
14775 /* there is more than one continuous variable or the integer variables have fractional coefficients:
14776 * none of the continuous variables is implied integral
14777 */
14778 for( i = 0; i < nconscontvars; i++ )
14779 {
14780 int contv;
14781 contv = SCIPvarGetProbindex(conscontvars[i]) - nintvars;
14782 assert(0 <= contv && contv < ncontvars);
14783 isimplint[contv] = FALSE;
14784 }
14785 }
14786 else
14787 {
14788 SCIP_VAR* var;
14789 SCIP_Real val;
14790 SCIP_Real absval;
14791 int contv;
14792
14793 /* there is exactly one continuous variable and the integer variables have integral coefficients:
14794 * this is the interesting case, and we have to check whether the coefficient is +/-1 and the corresponding
14795 * side(s) of the constraint is integral
14796 */
14797 assert(nconscontvars == 1);
14798 assert(0 <= contvarpos && contvarpos < consdata->nvars);
14799 var = consdata->vars[contvarpos];
14800 val = consdata->vals[contvarpos];
14801 contv = SCIPvarGetProbindex(var) - nintvars;
14802 assert(0 <= contv && contv < ncontvars);
14803 assert(isimplint[contv]);
14804
14805 absval = REALABS(val);
14806 if( !SCIPisEQ(scip, absval, 1.0) )
14807 isimplint[contv] = FALSE;
14808 else
14809 {
14810 SCIP_Real obj;
14811
14813 if( obj * val >= 0.0 && lhsexists )
14814 {
14815 /* the variable may be blocked by the constraint's left hand side */
14816 isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->lhs);
14817 }
14818 if( obj * val <= 0.0 && rhsexists )
14819 {
14820 /* the variable may be blocked by the constraint's left hand side */
14821 isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->rhs);
14822 }
14823 }
14824 }
14825 }
14826 }
14827 }
14828
14829 /* check if any bounds can be tightened due to optimality */
14830 for( v = 0; v < nvars; ++v )
14831 {
14832 SCIP_VAR* var;
14833 SCIP_Real obj;
14834 SCIP_Bool infeasible;
14835 SCIP_Bool tightened;
14836
14840
14841 var = vars[v];
14843 if( !SCIPisPositive(scip, -obj) )
14844 {
14845 /* making the variable as small as possible does not increase the objective:
14846 * check if all down locks of the variables are due to linear constraints;
14847 * if variable is cost neutral and only upper bounded non-positively or negative largest bound to make
14848 * constraints redundant is huge, we better do nothing for numerical reasons
14849 */
14852 && !SCIPisHugeValue(scip, -redlb[v])
14853 && redlb[v] < SCIPvarGetUbGlobal(var) )
14854 {
14855 SCIP_Real ub;
14856
14857 /* if x_v >= redlb[v], we can always round x_v down to x_v == redlb[v] without violating any constraint
14858 * -> tighten upper bound to x_v <= redlb[v]
14859 */
14860 SCIPdebugMsg(scip, "variable <%s> only locked down in linear constraints: dual presolve <%s>[%.15g,%.15g] <= %.15g\n",
14862 redlb[v]);
14863 SCIP_CALL( SCIPtightenVarUb(scip, var, redlb[v], FALSE, &infeasible, &tightened) );
14864 assert(!infeasible);
14865
14866 ub = SCIPvarGetUbGlobal(var);
14867 redub[v] = MIN(redub[v], ub);
14868 if( tightened )
14869 (*nchgbds)++;
14870 }
14871 }
14872 if( !SCIPisPositive(scip, obj) )
14873 {
14874 /* making the variable as large as possible does not increase the objective:
14875 * check if all up locks of the variables are due to linear constraints;
14876 * if variable is cost neutral and only lower bounded non-negatively or positive smallest bound to make
14877 * constraints redundant is huge, we better do nothing for numerical reasons
14878 */
14881 && !SCIPisHugeValue(scip, redub[v])
14882 && redub[v] > SCIPvarGetLbGlobal(var) )
14883 {
14884 SCIP_Real lb;
14885
14886 /* if x_v <= redub[v], we can always round x_v up to x_v == redub[v] without violating any constraint
14887 * -> tighten lower bound to x_v >= redub[v]
14888 */
14889 SCIPdebugMsg(scip, "variable <%s> only locked up in linear constraints: dual presolve <%s>[%.15g,%.15g] >= %.15g\n",
14891 redub[v]);
14892 SCIP_CALL( SCIPtightenVarLb(scip, var, redub[v], FALSE, &infeasible, &tightened) );
14893 assert(!infeasible);
14894
14895 lb = SCIPvarGetLbGlobal(var);
14896 redlb[v] = MAX(redlb[v], lb);
14897 if( tightened )
14898 (*nchgbds)++;
14899 }
14900 }
14901 }
14902
14903 /* @TODO: improve range names */
14904 /* declare continuous variables implied integral */
14905 for( v = nintvars - nbinvars; v < nvars; ++v )
14906 {
14907 SCIP_VAR* var;
14908 SCIP_Bool infeasible;
14909
14910 var = vars[v];
14911 assert(var != NULL);
14912
14916 assert(0 <= v - nintvars + nbinvars && v - nintvars + nbinvars < ncontvars);
14917
14918 /* @TODO: relax lock conditions */
14919 /* we can only conclude implied integrality if the variable appears in no other constraint */
14920 if( isimplint[v - nintvars + nbinvars]
14922 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v] )
14923 {
14924 /* since we locally copied the variable array we can change the variable type immediately */
14927 (*nchgvartypes)++;
14928 if( infeasible )
14929 {
14930 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
14931 *cutoff = TRUE;
14932
14933 break;
14934 }
14935
14936 SCIPdebugMsg(scip, "dual presolve: declare continuous variable <%s>[%g,%g] implied integral\n",
14938 }
14939 }
14940
14941 /* free temporary memory */
14942 SCIPfreeBufferArray(scip, &conscontvars);
14943 SCIPfreeBufferArray(scip, &isimplint);
14944 SCIPfreeBufferArray(scip, &nlocksup);
14945 SCIPfreeBufferArray(scip, &nlocksdown);
14946 SCIPfreeBufferArray(scip, &redub);
14947 SCIPfreeBufferArray(scip, &redlb);
14948
14950
14951 return SCIP_OKAY;
14952}
14953
14954/** helper function to enforce constraints */
14955static
14957 SCIP* scip, /**< SCIP data structure */
14958 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
14959 SCIP_CONS** conss, /**< constraints to process */
14960 int nconss, /**< number of constraints */
14961 int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
14962 SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
14963 SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
14964 )
14965{
14966 SCIP_CONSHDLRDATA* conshdlrdata;
14967 SCIP_Bool checkrelmaxabs;
14968 SCIP_Bool violated;
14970 int c;
14971
14972 assert(scip != NULL);
14973 assert(conshdlr != NULL);
14974 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
14975 assert(result != NULL);
14976
14977 conshdlrdata = SCIPconshdlrGetData(conshdlr);
14978 assert(conshdlrdata != NULL);
14979
14980 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
14981
14982 SCIPdebugMsg(scip, "Enforcement method of linear constraints for %s solution\n", sol == NULL ? "LP" : "relaxation");
14983
14984 /* check for violated constraints
14985 * LP is processed at current node -> we can add violated linear constraints to the SCIP_LP
14986 */
14988
14989 /* check all useful linear constraints for feasibility */
14990 for( c = 0; c < nusefulconss; ++c )
14991 {
14992 SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
14993
14994 if( violated )
14995 {
14996 /* insert LP row as cut */
14997 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
14998 if ( cutoff )
15000 else
15002 }
15003 }
15004
15005 /* check all obsolete linear constraints for feasibility */
15006 for( c = nusefulconss; c < nconss && *result == SCIP_FEASIBLE; ++c )
15007 {
15008 SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15009
15010 if( violated )
15011 {
15012 /* insert LP row as cut */
15013 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15014 if ( cutoff )
15016 else
15018 }
15019 }
15020
15021 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
15022
15023 return SCIP_OKAY;
15024}
15025
15026/** adds symmetry information of constraint to a symmetry detection graph */
15027static
15029 SCIP* scip, /**< SCIP pointer */
15030 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
15031 SCIP_CONS* cons, /**< constraint */
15032 SYM_GRAPH* graph, /**< symmetry detection graph */
15033 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
15034 )
15035{
15036 SCIP_CONSDATA* consdata;
15037 SCIP_VAR** vars;
15038 SCIP_Real* vals;
15039 SCIP_Real constant = 0.0;
15040 SCIP_Real lhs;
15041 SCIP_Real rhs;
15042 int nlocvars;
15043 int nvars;
15044 int i;
15045
15046 assert(scip != NULL);
15047 assert(cons != NULL);
15048 assert(graph != NULL);
15049 assert(success != NULL);
15050
15051 consdata = SCIPconsGetData(cons);
15052 assert(consdata != NULL);
15053
15054 /* get active variables of the constraint */
15056 nlocvars = consdata->nvars;
15057
15060
15061 for( i = 0; i < nlocvars; ++i )
15062 {
15063 vars[i] = consdata->vars[i];
15064 vals[i] = consdata->vals[i];
15065 }
15066
15067 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
15068 lhs = consdata->lhs - constant;
15069 rhs = consdata->rhs - constant;
15070
15071 /* if rhs is infinite, normalize rhs to be finite to make sure that different encodings
15072 * of the same constraint are rated as equal
15073 */
15074 if ( SCIPisInfinity(scip, rhs) )
15075 {
15076 SCIP_Real tmp;
15077 assert(!SCIPisInfinity(scip, -lhs));
15078
15079 for( i = 0; i < nlocvars; ++i )
15080 vals[i] *= -1;
15081 tmp = rhs;
15082 rhs = -lhs;
15083 lhs = -tmp;
15084 }
15085
15087 cons, lhs, rhs, success) );
15088
15089 SCIPfreeBufferArray(scip, &vals);
15091
15092 return SCIP_OKAY;
15093}
15094
15095/*
15096 * Callback methods of constraint handler
15097 */
15098
15099/** copy method for constraint handler plugins (called when SCIP copies plugins) */
15100static
15101SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
15102{ /*lint --e{715}*/
15103 assert(scip != NULL);
15104 assert(conshdlr != NULL);
15105 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15106
15107 /* call inclusion method of constraint handler */
15109
15110 *valid = TRUE;
15111
15112 return SCIP_OKAY;
15113}
15114
15115/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
15116static
15117SCIP_DECL_CONSFREE(consFreeLinear)
15118{ /*lint --e{715}*/
15119 SCIP_CONSHDLRDATA* conshdlrdata;
15120
15121 assert(scip != NULL);
15122 assert(conshdlr != NULL);
15123 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15124
15125 /* free constraint handler data */
15126 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15127 assert(conshdlrdata != NULL);
15128
15129 conshdlrdataFree(scip, &conshdlrdata);
15130
15131 SCIPconshdlrSetData(conshdlr, NULL);
15132
15133 return SCIP_OKAY;
15134}
15135
15136
15137/** initialization method of constraint handler (called after problem was transformed) */
15138static
15139SCIP_DECL_CONSINIT(consInitLinear)
15140{
15141 SCIP_CONSHDLRDATA* conshdlrdata;
15142 int c;
15143
15144 assert(scip != NULL);
15145
15146 /* check for event handler */
15147 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15148 assert(conshdlrdata != NULL);
15149 assert(conshdlrdata->eventhdlr != NULL);
15150 assert(nconss == 0 || conss != NULL);
15151
15152 conshdlrdata->naddconss = 0;
15153
15154 /* catch events for the constraints */
15155 for( c = 0; c < nconss; ++c )
15156 {
15157 /* catch all events */
15158 SCIP_CALL( consCatchAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15159 }
15160
15161 return SCIP_OKAY;
15162}
15163
15164
15165/** deinitialization method of constraint handler (called before transformed problem is freed) */
15166static
15167SCIP_DECL_CONSEXIT(consExitLinear)
15168{
15169 SCIP_CONSHDLRDATA* conshdlrdata;
15170 int c;
15171
15172 assert(scip != NULL);
15173
15174 /* check for event handler */
15175 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15176 assert(conshdlrdata != NULL);
15177 assert(conshdlrdata->eventhdlr != NULL);
15178
15179 /* drop events for the constraints */
15180 for( c = nconss - 1; c >= 0; --c )
15181 {
15182 SCIP_CONSDATA* consdata;
15183
15184 consdata = SCIPconsGetData(conss[c]);
15185 assert(consdata != NULL);
15186
15187 if( consdata->eventdata != NULL )
15188 {
15189 /* drop all events */
15190 SCIP_CALL( consDropAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15191 assert(consdata->eventdata == NULL);
15192 }
15193 }
15194
15195 return SCIP_OKAY;
15196}
15197
15198/** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15199static
15201 SCIP* scip, /**< SCIP data structure */
15202 SCIP_Real lhs, /**< left hand side */
15203 SCIP_Real rhs /**< right hand side */
15204 )
15205{
15206 assert(scip != NULL);
15207
15208 return !(SCIPisEQ(scip, lhs, rhs) || SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs) );
15209}
15210
15211/** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15212static
15214 SCIP* scip, /**< SCIP data structure */
15215 SCIP_Real x /**< value */
15216 )
15217{
15218 assert(scip != NULL);
15219
15220 return (!SCIPisInfinity(scip, x) && !SCIPisNegative(scip, x) && SCIPisIntegral(scip, x));
15221}
15222
15223/** performs linear constraint type classification as used for MIPLIB
15224 *
15225 * iterates through all linear constraints and stores relevant statistics in the linear constraint statistics \p linconsstats.
15226 *
15227 * @note only constraints are iterated that belong to the linear constraint handler. If the problem has been presolved already,
15228 * constraints that were upgraded to more special types such as, e.g., varbound constraints, will not be shown correctly anymore.
15229 * Similarly, if specialized constraints were created through the API, these are currently not present.
15230 */
15232 SCIP* scip, /**< SCIP data structure */
15233 SCIP_LINCONSSTATS* linconsstats /**< linear constraint type classification */
15234 )
15235{
15236 int c;
15237 SCIP_CONSHDLR* conshdlr;
15238 SCIP_CONS** conss;
15239 int nconss;
15240
15241 assert(scip != NULL);
15242 assert(linconsstats != NULL);
15243 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
15244 assert(conshdlr != NULL);
15245
15247 {
15248 conss = SCIPgetConss(scip);
15249 nconss = SCIPgetNConss(scip);
15250 }
15251 else
15252 {
15253 conss = SCIPconshdlrGetConss(conshdlr);
15254 nconss = SCIPconshdlrGetNConss(conshdlr);
15255 }
15256
15257 /* reset linear constraint type classification */
15258 SCIPlinConsStatsReset(linconsstats);
15259
15260 /* loop through all constraints */
15261 for( c = 0; c < nconss; c++ )
15262 {
15263 SCIP_CONS* cons;
15264 SCIP_CONSDATA* consdata;
15265 SCIP_Real lhs;
15266 SCIP_Real rhs;
15267 int i;
15268
15269 /* get constraint */
15270 cons = conss[c];
15271 assert(cons != NULL);
15272
15273 /* skip constraints that are not handled by the constraint handler */
15274 if( SCIPconsGetHdlr(cons) != conshdlr )
15275 continue;
15276
15277 /* get constraint data */
15278 consdata = SCIPconsGetData(cons);
15279 assert(consdata != NULL);
15280 rhs = consdata->rhs;
15281 lhs = consdata->lhs;
15282
15283 /* merge multiples and delete variables with zero coefficient */
15284 SCIP_CALL( mergeMultiples(scip, cons) );
15285 for( i = 0; i < consdata->nvars; i++ )
15286 {
15287 assert(!SCIPisZero(scip, consdata->vals[i]));
15288 }
15289
15290 /* is constraint of type SCIP_CONSTYPE_EMPTY? */
15291 if( consdata->nvars == 0 )
15292 {
15293 SCIPdebugMsg(scip, "classified as EMPTY: ");
15296
15297 continue;
15298 }
15299
15300 /* is constraint of type SCIP_CONSTYPE_FREE? */
15301 if( SCIPisInfinity(scip, rhs) && SCIPisInfinity(scip, -lhs) )
15302 {
15303 SCIPdebugMsg(scip, "classified as FREE: ");
15306
15307 continue;
15308 }
15309
15310 /* is constraint of type SCIP_CONSTYPE_SINGLETON? */
15311 if( consdata->nvars == 1 )
15312 {
15313 SCIPdebugMsg(scip, "classified as SINGLETON: ");
15316
15317 continue;
15318 }
15319
15320 /* is constraint of type SCIP_CONSTYPE_AGGREGATION? */
15321 if( consdata->nvars == 2 && SCIPisEQ(scip, lhs, rhs) )
15322 {
15323 SCIPdebugMsg(scip, "classified as AGGREGATION: ");
15326
15327 continue;
15328 }
15329
15330 /* is constraint of type SCIP_CONSTYPE_{VARBOUND,PRECEDENCE}? */
15331 if( consdata->nvars == 2 )
15332 {
15333 /* precedence constraints have same variable type and same absolute coefficient with opposite sign */
15334 if( SCIPvarGetType(consdata->vars[0]) == SCIPvarGetType(consdata->vars[1])
15335 && SCIPisEQ(scip, consdata->vals[0], -consdata->vals[1]) )
15336 {
15337 SCIPdebugMsg(scip, "classified as PRECEDENCE: ");
15340
15341 continue;
15342 }
15343 /* varbound constraints have otherwise a binary variable */
15344 else if( SCIPvarGetType(consdata->vars[0]) == SCIP_VARTYPE_BINARY
15345 || SCIPvarGetType(consdata->vars[1]) == SCIP_VARTYPE_BINARY )
15346 {
15347 SCIPdebugMsg(scip, "classified as VARBOUND: ");
15350
15351 continue;
15352 }
15353 }
15354
15355 /* is constraint of type SCIP_CONSTYPE_{SETPARTITION, SETPACKING, SETCOVERING, CARDINALITY, INVKNAPSACK}? */
15356 {
15357 SCIP_Real scale;
15358 SCIP_Real b;
15359 SCIP_Bool unmatched;
15360 int nnegbinvars;
15361
15362 unmatched = FALSE;
15363 nnegbinvars = 0;
15364
15365 scale = REALABS(consdata->vals[0]);
15366
15367 /* scan through variables and detect if all variables are binary and have a coefficient +/-1 */
15368 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15369 {
15370 unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15371 unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15372 unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15373 unmatched = unmatched || !SCIPisEQ(scip, REALABS(consdata->vals[i]), scale);
15374
15375 if( consdata->vals[i] < 0.0 )
15376 nnegbinvars++;
15377 }
15378
15379 if( !unmatched )
15380 {
15381 if( SCIPisEQ(scip, lhs, rhs) )
15382 {
15383 b = rhs/scale + nnegbinvars;
15384 if( SCIPisEQ(scip, 1.0, b) )
15385 {
15386 SCIPdebugMsg(scip, "classified as SETPARTITION: ");
15389
15390 continue;
15391 }
15392 else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15393 {
15394 SCIPdebugMsg(scip, "classified as CARDINALITY: ");
15397
15398 continue;
15399 }
15400 }
15401
15402 /* compute right hand side divided by scale */
15403 if( !SCIPisInfinity(scip, rhs) )
15404 b = rhs/scale + nnegbinvars;
15405 else
15406 b = SCIPinfinity(scip);
15407
15408 if( SCIPisEQ(scip, 1.0, b) )
15409 {
15410 SCIPdebugMsg(scip, "classified as SETPACKING: ");
15413
15414 /* relax right hand side to prevent further classifications */
15415 rhs = SCIPinfinity(scip);
15416 }
15417 else if( !SCIPisInfinity(scip, b) && SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15418 {
15419 SCIPdebugMsg(scip, "classified as INVKNAPSACK: ");
15421
15423
15424 /* relax right hand side to prevent further classifications */
15425 rhs = SCIPinfinity(scip);
15426 }
15427
15428 if( !SCIPisInfinity(scip, lhs) )
15429 b = lhs/scale + nnegbinvars;
15430 else
15431 b = SCIPinfinity(scip);
15432
15433 if( SCIPisEQ(scip, 1.0, b) )
15434 {
15435 SCIPdebugMsg(scip, "classified as SETCOVERING: ");
15438
15439 /* relax left hand side to prevent further classifications */
15440 lhs = -SCIPinfinity(scip);
15441 }
15442
15443 /* if both sides are infinite at this point, no further classification is necessary for this constraint */
15444 if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
15445 continue;
15446 }
15447 }
15448
15449 /* is constraint of type SCIP_CONSTYPE_{EQKNAPSACK, BINPACKING, KNAPSACK}? */
15450 /* @todo If coefficients or rhs are not integral, we currently do not check
15451 * if the constraint could be scaled (finitely), such that they are.
15452 */
15453 {
15454 SCIP_Real b;
15455 SCIP_Bool unmatched;
15456
15457 b = rhs;
15458 unmatched = FALSE;
15459 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15460 {
15461 unmatched = unmatched || !SCIPvarIsIntegral(consdata->vars[i]);
15462 unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15463 unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15464 unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15465
15466 if( SCIPisNegative(scip, consdata->vals[i]) )
15467 b -= consdata->vals[i];
15468 }
15469 unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15470
15471 if( !unmatched )
15472 {
15473 if( SCIPisEQ(scip, lhs, rhs) )
15474 {
15475 SCIPdebugMsg(scip, "classified as EQKNAPSACK: ");
15477
15479
15480 continue;
15481 }
15482 else
15483 {
15484 SCIP_Bool matched;
15485
15486 matched = FALSE;
15487 for( i = 0; i < consdata->nvars && !matched; i++ )
15488 {
15489 matched = matched || SCIPisEQ(scip, b, REALABS(consdata->vals[i]));
15490 }
15491
15492 SCIPdebugMsg(scip, "classified as %s: ", matched ? "BINPACKING" : "KNAPSACK");
15495 }
15496
15497 /* check if finite left hand side allows for a second classification, relax already used right hand side */
15498 if( SCIPisInfinity(scip, -lhs) )
15499 continue;
15500 else
15501 rhs = SCIPinfinity(scip);
15502 }
15503 }
15504
15505 /* is constraint of type SCIP_CONSTYPE_{INTKNAPSACK}? */
15506 {
15507 SCIP_Real b;
15508 SCIP_Bool unmatched;
15509
15510 unmatched = FALSE;
15511
15512 b = rhs;
15513 unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15514
15515 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15516 {
15517 unmatched = unmatched || !SCIPvarIsIntegral(consdata->vars[i]);
15518 unmatched = unmatched || SCIPisNegative(scip, SCIPvarGetLbGlobal(consdata->vars[i]));
15519 unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15520 unmatched = unmatched || SCIPisNegative(scip, consdata->vals[i]);
15521 }
15522
15523 if( !unmatched )
15524 {
15525 SCIPdebugMsg(scip, "classified as INTKNAPSACK: ");
15528
15529 /* check if finite left hand side allows for a second classification, relax already used right hand side */
15530 if( SCIPisInfinity(scip, -lhs) )
15531 continue;
15532 else
15533 rhs = SCIPinfinity(scip);
15534 }
15535 }
15536
15537 /* is constraint of type SCIP_CONSTYPE_{MIXEDBINARY}? */
15538 {
15539 SCIP_Bool unmatched;
15540
15541 unmatched = FALSE;
15542 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15543 {
15544 if( SCIPvarIsIntegral(consdata->vars[i])
15545 && ( SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0)
15546 || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0) ) )
15547 unmatched = TRUE;
15548 }
15549
15550 if( !unmatched )
15551 {
15552 SCIPdebugMsg(scip, "classified as MIXEDBINARY (%d): ", isRangedRow(scip, lhs, rhs) ? 2 : 1);
15555
15556 continue;
15557 }
15558 }
15559
15560 /* no special structure detected */
15561 SCIPdebugMsg(scip, "classified as GENERAL: ");
15563 SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_GENERAL, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15564 }
15565
15566 return SCIP_OKAY;
15567}
15568
15569
15570/** presolving deinitialization method of constraint handler (called after presolving has been finished) */
15571static
15572SCIP_DECL_CONSEXITPRE(consExitpreLinear)
15573{ /*lint --e{715}*/
15574 int c;
15575#ifdef SCIP_STATISTIC
15576 SCIP_CONSHDLRDATA* conshdlrdata;
15577 int ngoodconss;
15578 int nallconss;
15579#endif
15580
15581 /* delete all linear constraints that were upgraded to a more specific constraint type;
15582 * make sure, only active variables remain in the remaining constraints
15583 */
15584 assert(scip != NULL);
15585
15586#ifdef SCIP_STATISTIC
15587 /* count number of well behaved linear constraints */
15588 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15589 assert(conshdlrdata != NULL);
15590
15591 ngoodconss = 0;
15592 nallconss = 0;
15593
15594 for( c = 0; c < nconss; ++c )
15595 {
15596 SCIP_CONSDATA* consdata;
15597
15598 if( SCIPconsIsDeleted(conss[c]) )
15599 continue;
15600
15601 consdata = SCIPconsGetData(conss[c]);
15602 assert(consdata != NULL);
15603
15604 if( consdata->upgraded )
15605 continue;
15606
15607 nallconss++;
15608
15610
15611 if( SCIPisLT(scip, consdata->maxactdelta, conshdlrdata->maxeasyactivitydelta) )
15612 ngoodconss++;
15613 }
15614 if( nallconss )
15615 {
15616 SCIPstatisticMessage("below threshold: %d / %d ratio= %g\n", ngoodconss, nallconss, (100.0 * ngoodconss / nallconss));
15617 }
15618#endif
15619
15620 for( c = 0; c < nconss; ++c )
15621 {
15622 SCIP_CONSDATA* consdata;
15623
15624 if( SCIPconsIsDeleted(conss[c]) )
15625 continue;
15626
15627 consdata = SCIPconsGetData(conss[c]);
15628 assert(consdata != NULL);
15629
15630 if( consdata->upgraded )
15631 {
15632 /* this is no problem reduction, because the upgraded constraint was added to the problem before, and the
15633 * (redundant) linear constraint was only kept in order to support presolving the the linear constraint handler
15634 */
15635 SCIP_CALL( SCIPdelCons(scip, conss[c]) );
15636 }
15637 else
15638 {
15639 /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */
15640 SCIP_CALL( applyFixings(scip, conss[c], NULL) );
15641 }
15642 }
15643
15644 return SCIP_OKAY;
15645}
15646
15647/** solving process initialization method of constraint handler */
15648static
15649SCIP_DECL_CONSINITSOL(consInitsolLinear)
15650{ /*lint --e{715}*/
15651 /* add nlrow representation to NLP, if NLP had been constructed */
15653 {
15654 int c;
15655 for( c = 0; c < nconss; ++c )
15656 {
15657 SCIP_CALL( addNlrow(scip, conss[c]) );
15658 }
15659 }
15660
15661 return SCIP_OKAY;
15662}
15663
15664/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
15665static
15666SCIP_DECL_CONSEXITSOL(consExitsolLinear)
15667{ /*lint --e{715}*/
15668 int c;
15669
15670 assert(scip != NULL);
15671
15672 /* release the rows and nlrows of all constraints */
15673 for( c = 0; c < nconss; ++c )
15674 {
15675 SCIP_CONSDATA* consdata;
15676
15677 consdata = SCIPconsGetData(conss[c]);
15678 assert(consdata != NULL);
15679
15680 if( consdata->row != NULL )
15681 {
15682 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
15683 }
15684
15685 if( consdata->nlrow != NULL )
15686 {
15687 SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
15688 }
15689 }
15690
15691 /* if this is a restart, convert cutpool rows into linear constraints */
15692 if( restart )
15693 {
15694 int ncutsadded;
15695
15696 ncutsadded = 0;
15697
15698 /* create out of all active cuts in cutpool linear constraints */
15699 SCIP_CALL( SCIPconvertCutsToConss(scip, NULL, NULL, TRUE, &ncutsadded) );
15700
15701 if( ncutsadded > 0 )
15702 {
15704 "(restart) converted %d cuts from the global cut pool into linear constraints\n", ncutsadded);
15705 /* an extra blank line should be printed separately since the buffer message handler only handles up to one
15706 * line correctly
15707 */
15709 }
15710 }
15711
15712 return SCIP_OKAY;
15713}
15714
15715
15716/** constraint activation notification method of constraint handler */
15717static
15718SCIP_DECL_CONSACTIVE(consActiveLinear)
15719{ /*lint --e{715}*/
15720 assert(cons != NULL);
15721
15723 {
15724 SCIP_CALL( addNlrow(scip, cons) );
15725 }
15726
15727 return SCIP_OKAY;
15728}
15729
15730/** constraint deactivation notification method of constraint handler */
15731static
15732SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
15733{ /*lint --e{715}*/
15734 SCIP_CONSDATA* consdata;
15735
15736 assert(scip != NULL);
15737 assert(conshdlr != NULL);
15738 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15739 assert(cons != NULL );
15740
15741 /* get constraint data */
15742 consdata = SCIPconsGetData(cons);
15743 assert(consdata != NULL);
15744
15745 if( SCIPconsIsDeleted(cons) )
15746 {
15747 SCIP_CONSHDLRDATA* conshdlrdata;
15748
15749 /* check for event handler */
15750 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15751 assert(conshdlrdata != NULL);
15752 assert(conshdlrdata->eventhdlr != NULL);
15753
15754 /* free event data */
15755 if( consdata->eventdata != NULL )
15756 {
15757 /* drop bound change events of variables */
15758 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15759 }
15760 assert(consdata->eventdata == NULL);
15761 }
15762
15763 /* remove row from NLP, if still in solving
15764 * if we are in exitsolve, the whole NLP will be freed anyway
15765 */
15766 if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
15767 {
15768 SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
15769 }
15770
15771 return SCIP_OKAY;
15772}
15773
15774
15775/** frees specific constraint data */
15776static
15777SCIP_DECL_CONSDELETE(consDeleteLinear)
15778{ /*lint --e{715}*/
15779 assert(scip != NULL);
15780 assert(conshdlr != NULL);
15781 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15782
15783 if( (*consdata)->eventdata != NULL )
15784 {
15785 SCIP_CONSHDLRDATA* conshdlrdata;
15786
15787 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15788 assert(conshdlrdata != NULL);
15789
15790 /* drop all events */
15791 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15792 assert((*consdata)->eventdata == NULL);
15793 }
15794
15795 /* free linear constraint */
15796 SCIP_CALL( consdataFree(scip, consdata) );
15797
15798 return SCIP_OKAY;
15799}
15800
15801
15802/** transforms constraint data into data belonging to the transformed problem */
15803static
15804SCIP_DECL_CONSTRANS(consTransLinear)
15805{ /*lint --e{715}*/
15806 SCIP_CONSDATA* sourcedata;
15807 SCIP_CONSDATA* targetdata;
15808
15809 /*debugMsg(scip, "Trans method of linear constraints\n");*/
15810
15811 assert(scip != NULL);
15812 assert(conshdlr != NULL);
15813 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15815 assert(sourcecons != NULL);
15816 assert(targetcons != NULL);
15817
15818 sourcedata = SCIPconsGetData(sourcecons);
15819 assert(sourcedata != NULL);
15820 assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
15821
15822 /* create linear constraint data for target constraint */
15823 SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars, sourcedata->vals, sourcedata->lhs,
15824 sourcedata->rhs) );
15825
15826#ifndef NDEBUG
15827 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
15828 if( SCIPconsIsEnforced(sourcecons) || SCIPconsIsChecked(sourcecons) )
15829 {
15830 int n;
15831 for(n = targetdata->nvars - 1; n >= 0; --n )
15832 assert(!SCIPvarIsRelaxationOnly(targetdata->vars[n]));
15833 }
15834#endif
15835
15836 /* create target constraint */
15837 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
15838 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
15839 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
15840 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
15841 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
15842
15843 return SCIP_OKAY;
15844}
15845
15846
15847/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
15848static
15849SCIP_DECL_CONSINITLP(consInitlpLinear)
15850{ /*lint --e{715}*/
15851 int c;
15852
15853 assert(scip != NULL);
15854 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15855
15856 *infeasible = FALSE;
15857
15858 for( c = 0; c < nconss && !(*infeasible); ++c )
15859 {
15860 assert(SCIPconsIsInitial(conss[c]));
15861 SCIP_CALL( addRelaxation(scip, conss[c], infeasible) );
15862 }
15863
15864 return SCIP_OKAY;
15865}
15866
15867
15868/** separation method of constraint handler for LP solutions */
15869static
15870SCIP_DECL_CONSSEPALP(consSepalpLinear)
15871{ /*lint --e{715}*/
15872 SCIP_CONSHDLRDATA* conshdlrdata;
15873 SCIP_Real loclowerbound;
15874 SCIP_Real glblowerbound;
15875 SCIP_Real cutoffbound;
15876 SCIP_Real maxbound;
15877 SCIP_Bool separatecards;
15879 int c;
15880 int depth;
15881 int nrounds;
15882 int maxsepacuts;
15883 int ncuts;
15884
15885 assert(scip != NULL);
15886 assert(conshdlr != NULL);
15887 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15888 assert(result != NULL);
15889
15890 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15891 assert(conshdlrdata != NULL);
15893 nrounds = SCIPgetNSepaRounds(scip);
15894
15895 /*debugMsg(scip, "Sepa method of linear constraints\n");*/
15896
15898
15899 /* only call the separator a given number of times at each node */
15900 if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
15901 || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
15902 return SCIP_OKAY;
15903
15904 /* get the maximal number of cuts allowed in a separation round */
15905 maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
15906
15907 /* check if we want to produce knapsack cardinality cuts at this node */
15908 loclowerbound = SCIPgetLocalLowerbound(scip);
15909 glblowerbound = SCIPgetLowerbound(scip);
15910 cutoffbound = SCIPgetCutoffbound(scip);
15911 maxbound = glblowerbound + conshdlrdata->maxcardbounddist * (cutoffbound - glblowerbound);
15912 separatecards = SCIPisLE(scip, loclowerbound, maxbound);
15913 separatecards = separatecards && (SCIPgetNLPBranchCands(scip) > 0);
15914
15916 ncuts = 0;
15917 cutoff = FALSE;
15918
15919 /* check all useful linear constraints for feasibility */
15920 for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
15921 {
15922 /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
15923 SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, NULL, separatecards, conshdlrdata->separateall, &ncuts, &cutoff) );
15924 }
15925
15926 /* adjust return value */
15927 if( cutoff )
15929 else if( ncuts > 0 )
15931
15932 /* combine linear constraints to get more cuts */
15933 /**@todo further cuts of linear constraints */
15934
15935 return SCIP_OKAY;
15936}
15937
15938
15939/** separation method of constraint handler for arbitrary primal solutions */
15940static
15941SCIP_DECL_CONSSEPASOL(consSepasolLinear)
15942{ /*lint --e{715}*/
15943 SCIP_CONSHDLRDATA* conshdlrdata;
15944 int c;
15945 int depth;
15946 int nrounds;
15947 int maxsepacuts;
15948 int ncuts;
15950
15951 assert(scip != NULL);
15952 assert(conshdlr != NULL);
15953 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15954 assert(result != NULL);
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(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16027 assert(result != NULL);
16028
16029 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16030 assert(conshdlrdata != NULL);
16031
16032 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16033
16034 SCIPdebugMsg(scip, "Enfops method of linear constraints\n");
16035
16036 /* if the solution is infeasible anyway due to objective value, skip the enforcement */
16037 if( objinfeasible )
16038 {
16039 SCIPdebugMsg(scip, "-> pseudo solution is objective infeasible, return.\n");
16040
16042 return SCIP_OKAY;
16043 }
16044
16045 /* check all linear constraints for feasibility */
16046 violated = FALSE;
16047 for( c = 0; c < nconss && !violated; ++c )
16048 {
16049 SCIP_CALL( checkCons(scip, conss[c], NULL, TRUE, checkrelmaxabs, &violated) );
16050 }
16051
16052 if( violated )
16054 else
16056
16057 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
16058
16059 return SCIP_OKAY;
16060}
16061
16062
16063/** feasibility check method of constraint handler for integral solutions */
16064static
16065SCIP_DECL_CONSCHECK(consCheckLinear)
16066{ /*lint --e{715}*/
16067 SCIP_CONSHDLRDATA* conshdlrdata;
16068 SCIP_Bool checkrelmaxabs;
16069 int c;
16070
16071 assert(scip != NULL);
16072 assert(conshdlr != NULL);
16073 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16074 assert(result != NULL);
16075
16077
16078 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16079 assert(conshdlrdata != NULL);
16080
16081 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16082
16083 /*debugMsg(scip, "Check method of linear constraints\n");*/
16084
16085 /* check all linear constraints for feasibility */
16086 for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
16087 {
16088 SCIP_Bool violated = FALSE;
16089 SCIP_CALL( checkCons(scip, conss[c], sol, checklprows, checkrelmaxabs, &violated) );
16090
16091 if( violated )
16092 {
16094
16095 if( printreason )
16096 {
16097 SCIP_CONSDATA* consdata;
16098 SCIP_Real activity;
16099
16100 consdata = SCIPconsGetData(conss[c]);
16101 assert( consdata != NULL);
16102
16103 activity = consdataGetActivity(scip, consdata, sol);
16104
16105 SCIP_CALL( consPrintConsSol(scip, conss[c], sol, NULL ) );
16106 SCIPinfoMessage(scip, NULL, ";\n");
16107
16108 if( activity == SCIP_INVALID || SCIPisInfinity(scip, ABS(activity)) ) /*lint !e777*/
16109 SCIPinfoMessage(scip, NULL, "activity invalid due to infinity contributions\n");
16110 else if( SCIPisFeasLT(scip, activity, consdata->lhs) )
16111 SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - activity);
16112 else if( SCIPisFeasGT(scip, activity, consdata->rhs) )
16113 SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - consdata->rhs);
16114 }
16115 }
16116 }
16117
16118 return SCIP_OKAY;
16119}
16120
16121
16122/** domain propagation method of constraint handler */
16123static
16124SCIP_DECL_CONSPROP(consPropLinear)
16125{ /*lint --e{715}*/
16126 SCIP_CONSHDLRDATA* conshdlrdata;
16127 SCIP_Bool rangedrowpropagation = FALSE;
16128 SCIP_Bool tightenbounds;
16130
16131 int nchgbds;
16132 int i;
16133
16134 assert(scip != NULL);
16135 assert(conshdlr != NULL);
16136 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16137 assert(result != NULL);
16138
16139 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16140 assert(conshdlrdata != NULL);
16141
16142 /*debugMsg(scip, "Prop method of linear constraints\n");*/
16143
16144 /* check, if we want to tighten variable's bounds (in probing, we always want to tighten the bounds) */
16145 if( SCIPinProbing(scip) )
16146 tightenbounds = TRUE;
16147 else
16148 {
16149 int depth;
16150 int propfreq;
16151 int tightenboundsfreq;
16152 int rangedrowfreq;
16153
16155 propfreq = SCIPconshdlrGetPropFreq(conshdlr);
16156 tightenboundsfreq = propfreq * conshdlrdata->tightenboundsfreq;
16157 tightenbounds = (conshdlrdata->tightenboundsfreq >= 0)
16158 && ((tightenboundsfreq == 0 && depth == 0) || (tightenboundsfreq >= 1 && (depth % tightenboundsfreq == 0)));
16159
16160 /* check if we want to do ranged row propagation */
16161 rangedrowpropagation = conshdlrdata->rangedrowpropagation;
16162 rangedrowpropagation = rangedrowpropagation && !SCIPinRepropagation(scip);
16163 rangedrowpropagation = rangedrowpropagation && (depth <= conshdlrdata->rangedrowmaxdepth);
16164 rangedrowfreq = propfreq * conshdlrdata->rangedrowfreq;
16165 rangedrowpropagation = rangedrowpropagation && (conshdlrdata->rangedrowfreq >= 0)
16166 && ((rangedrowfreq == 0 && depth == 0) || (rangedrowfreq >= 1 && (depth % rangedrowfreq == 0)));
16167 }
16168
16169 cutoff = FALSE;
16170 nchgbds = 0;
16171
16172 /* process constraints marked for propagation */
16173 for( i = 0; i < nmarkedconss && !cutoff; i++ )
16174 {
16176 SCIP_CALL( propagateCons(scip, conss[i], tightenbounds, rangedrowpropagation,
16177 conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, &nchgbds) );
16178 }
16179
16180 /* adjust result code */
16181 if( cutoff )
16183 else if( nchgbds > 0 )
16185 else
16187
16188 return SCIP_OKAY;
16189}
16190
16191
16192#define MAXCONSPRESOLROUNDS 10
16193/** presolving method of constraint handler */
16194static
16195SCIP_DECL_CONSPRESOL(consPresolLinear)
16196{ /*lint --e{715}*/
16197 SCIP_CONSHDLRDATA* conshdlrdata;
16198 SCIP_CONS* cons;
16199 SCIP_CONSDATA* consdata;
16200 SCIP_Real minactivity;
16201 SCIP_Real maxactivity;
16202 SCIP_Bool isminacttight;
16203 SCIP_Bool ismaxacttight;
16204 SCIP_Bool isminsettoinfinity;
16205 SCIP_Bool ismaxsettoinfinity;
16207 int oldnfixedvars;
16208 int oldnaggrvars;
16209 int oldnchgbds;
16210 int oldndelconss;
16211 int oldnupgdconss;
16212 int oldnchgcoefs;
16213 int oldnchgsides;
16214 int firstchange;
16215 int firstupgradetry;
16216 int c;
16217
16218 assert(scip != NULL);
16219 assert(conshdlr != NULL);
16220 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16221 assert(result != NULL);
16222
16223 /*debugMsg(scip, "Presol method of linear constraints\n");*/
16224
16225 /* remember old preprocessing counters */
16226 cutoff = FALSE;
16227 oldnfixedvars = *nfixedvars;
16228 oldnaggrvars = *naggrvars;
16229 oldnchgbds = *nchgbds;
16230 oldndelconss = *ndelconss;
16231 oldnupgdconss = *nupgdconss;
16232 oldnchgcoefs = *nchgcoefs;
16233 oldnchgsides = *nchgsides;
16234
16235 /* get constraint handler data */
16236 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16237 assert(conshdlrdata != NULL);
16238
16239 /* process single constraints */
16240 firstchange = INT_MAX;
16241 firstupgradetry = INT_MAX;
16242 for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
16243 {
16244 int npresolrounds;
16245 SCIP_Bool infeasible;
16246
16247 infeasible = FALSE;
16248
16249 cons = conss[c];
16250 assert(SCIPconsIsActive(cons));
16251 consdata = SCIPconsGetData(cons);
16252 assert(consdata != NULL);
16253
16254 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
16255 if( SCIPisEQ(scip, consdata->rhs, consdata->lhs) )
16256 {
16257 consdata->lhs = consdata->rhs;
16258 assert(consdata->row == NULL);
16259 }
16260
16261 if( consdata->eventdata == NULL )
16262 {
16263 /* catch bound change events of variables */
16264 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
16265 assert(consdata->eventdata != NULL);
16266 }
16267
16268 /* constraint should not be already presolved in the initial round */
16269 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || SCIPconsIsMarkedPropagate(cons));
16270 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || consdata->boundstightened == 0);
16271 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->presolved);
16272 assert(!SCIPconsIsMarkedPropagate(cons) || !consdata->presolved);
16273
16274 /* incorporate fixings and aggregations in constraint */
16275 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
16276
16277 if( infeasible )
16278 {
16279 SCIPdebugMsg(scip, " -> infeasible fixing\n");
16280 cutoff = TRUE;
16281 break;
16282 }
16283
16284 assert(consdata->removedfixings);
16285
16286 /* we can only presolve linear constraints, that are not modifiable */
16287 if( SCIPconsIsModifiable(cons) )
16288 continue;
16289
16290 /* remember the first changed constraint to begin the next aggregation round with */
16291 if( firstchange == INT_MAX && consdata->changed )
16292 firstchange = c;
16293
16294 /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16295 if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16296 firstupgradetry = c;
16297
16298 /* check, if constraint is already preprocessed */
16299 if( consdata->presolved )
16300 continue;
16301
16302 assert(SCIPconsIsActive(cons));
16303
16304 SCIPdebugMsg(scip, "presolving linear constraint <%s>\n", SCIPconsGetName(cons));
16306
16307 /* apply presolving as long as possible on the single constraint (however, abort after a certain number of rounds
16308 * to avoid nearly infinite cycling due to very small bound changes)
16309 */
16310 npresolrounds = 0;
16311 while( !consdata->presolved && npresolrounds < MAXCONSPRESOLROUNDS && !SCIPisStopped(scip) )
16312 {
16313 assert(!cutoff);
16314 npresolrounds++;
16315
16316 /* mark constraint being presolved and propagated */
16317 consdata->presolved = TRUE;
16319
16320 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
16321
16322 if( infeasible )
16323 {
16324 SCIPdebugMsg(scip, " -> infeasible normalization\n");
16325 cutoff = TRUE;
16326 break;
16327 }
16328
16329 /* tighten left and right hand side due to integrality */
16330 SCIP_CALL( tightenSides(scip, cons, nchgsides, &infeasible) );
16331
16332 if( infeasible )
16333 {
16334 SCIPdebugMsg(scip, " -> infeasibility detected during tightening sides\n");
16335 cutoff = TRUE;
16336 break;
16337 }
16338
16339 /* check bounds */
16340 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16341 {
16342 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16343 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16344 cutoff = TRUE;
16345 break;
16346 }
16347
16348 /* tighten variable's bounds */
16349 SCIP_CALL( tightenBounds(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, nchgbds) );
16350 if( cutoff )
16351 break;
16352
16353 /* check for fixed variables */
16354 SCIP_CALL( fixVariables(scip, cons, &cutoff, nfixedvars) );
16355 if( cutoff )
16356 break;
16357
16358 /* if the maximal coefficient is large, recompute the activities before infeasibility and redundancy checks */
16359 if( ( consdata->validmaxabsval && consdata->maxabsval > MAXVALRECOMP )
16360 || ( consdata->validminabsval && consdata->minabsval < MINVALRECOMP ) )
16361 {
16364 }
16365
16366 /* get activity bounds */
16367 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
16368 &isminsettoinfinity, &ismaxsettoinfinity);
16369
16370 /* check constraint for infeasibility and redundancy */
16371 if( SCIPisFeasGT(scip, minactivity, consdata->rhs) || SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
16372 {
16373 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16374 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16375 cutoff = TRUE;
16376 break;
16377 }
16378 else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16379 {
16380 SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16381 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16382 SCIP_CALL( SCIPdelCons(scip, cons) );
16383 assert(!SCIPconsIsActive(cons));
16384
16385 if( !consdata->upgraded )
16386 (*ndelconss)++;
16387 break;
16388 }
16389 else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisGE(scip, minactivity, consdata->lhs) )
16390 {
16391 SCIPdebugMsg(scip, "linear constraint <%s> left hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16392 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16393 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
16394 if( !consdata->upgraded )
16395 (*nchgsides)++;
16396 }
16397 else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16398 {
16399 SCIPdebugMsg(scip, "linear constraint <%s> right hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16400 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16402 if( !consdata->upgraded )
16403 (*nchgsides)++;
16404 }
16405
16406 /* handle empty constraint */
16407 if( consdata->nvars == 0 )
16408 {
16409 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16410 {
16411 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16412 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16413 cutoff = TRUE;
16414 }
16415 else
16416 {
16417 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16418 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16419 SCIP_CALL( SCIPdelCons(scip, cons) );
16420 assert(!SCIPconsIsActive(cons));
16421
16422 if( !consdata->upgraded )
16423 (*ndelconss)++;
16424 }
16425 break;
16426 }
16427
16428 /* reduce big-M coefficients, that make the constraint redundant if the variable is on a bound */
16429 SCIP_CALL( consdataTightenCoefs(scip, cons, nchgcoefs, nchgsides) );
16430
16431 /* try to simplify inequalities */
16432 if( conshdlrdata->simplifyinequalities )
16433 {
16434 SCIP_CALL( simplifyInequalities(scip, cons, nchgcoefs, nchgsides, &cutoff) );
16435
16436 if( cutoff )
16437 break;
16438 }
16439
16440 /* aggregation variable in equations */
16441 if( conshdlrdata->aggregatevariables )
16442 {
16443 SCIP_CALL( aggregateVariables(scip, cons, &cutoff, nfixedvars, naggrvars) );
16444 if( cutoff )
16445 break;
16446 }
16447 }
16448
16449 if( !cutoff && !SCIPisStopped(scip) )
16450 {
16451 /* perform ranged row propagation */
16452 if( conshdlrdata->rangedrowpropagation )
16453 {
16454 int lastnfixedvars;
16455
16456 lastnfixedvars = *nfixedvars;
16457
16458 SCIP_CALL( rangedRowPropagation(scip, cons, &cutoff, nfixedvars, nchgbds, naddconss) );
16459 if( !cutoff )
16460 {
16461 if( lastnfixedvars < *nfixedvars )
16462 {
16463 SCIP_CALL( applyFixings(scip, cons, &cutoff) );
16464 }
16465 }
16466 }
16467
16468 /* extract cliques from constraint */
16469 if( conshdlrdata->extractcliques && !cutoff && SCIPconsIsActive(cons) )
16470 {
16471 SCIP_CALL( extractCliques(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars,
16472 nfixedvars, nchgbds, &cutoff) );
16473
16474 /* check if the constraint got redundant or infeasible */
16475 if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 0 )
16476 {
16477 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16478 {
16479 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16480 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16481 cutoff = TRUE;
16482 }
16483 else
16484 {
16485 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16486 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16487 SCIP_CALL( SCIPdelCons(scip, cons) );
16488 assert(!SCIPconsIsActive(cons));
16489
16490 if( !consdata->upgraded )
16491 (*ndelconss)++;
16492 }
16493 }
16494 }
16495
16496 /* convert special equalities */
16497 if( !cutoff && SCIPconsIsActive(cons) )
16498 {
16499 SCIP_CALL( convertEquality(scip, cons, conshdlrdata, &cutoff, nfixedvars, naggrvars, ndelconss, nchgvartypes) );
16500 }
16501
16502 /* apply dual presolving for variables that appear in only one constraint */
16503 if( !cutoff && SCIPconsIsActive(cons) && conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) )
16504 {
16505 SCIP_CALL( dualPresolve(scip, conshdlrdata, cons, &cutoff, nfixedvars, naggrvars, ndelconss, nchgvartypes) );
16506 }
16507
16508 /* check if an inequality is parallel to the objective function */
16509 if( !cutoff && SCIPconsIsActive(cons) )
16510 {
16511 SCIP_CALL( checkParallelObjective(scip, cons, conshdlrdata) );
16512 }
16513
16514 /* remember the first changed constraint to begin the next aggregation round with */
16515 if( firstchange == INT_MAX && consdata->changed )
16516 firstchange = c;
16517
16518 /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16519 if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16520 firstupgradetry = c;
16521 }
16522
16523 /* singleton column stuffing */
16524 if( !cutoff && SCIPconsIsActive(cons) && SCIPconsIsChecked(cons) &&
16525 (conshdlrdata->singletonstuffing || conshdlrdata->singlevarstuffing) && SCIPallowStrongDualReds(scip) )
16526 {
16527 SCIP_CALL( presolStuffing(scip, cons, conshdlrdata->singletonstuffing,
16528 conshdlrdata->singlevarstuffing, &cutoff, nfixedvars, nchgbds) );
16529
16530 /* handle empty constraint */
16531 if( consdata->nvars == 0 )
16532 {
16533 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16534 {
16535 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16536 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16537 cutoff = TRUE;
16538 }
16539 else
16540 {
16541 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16542 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16543 SCIP_CALL( SCIPdelCons(scip, cons) );
16544 assert(!SCIPconsIsActive(cons));
16545
16546 if( !consdata->upgraded )
16547 (*ndelconss)++;
16548 }
16549 break;
16550 }
16551 }
16552 }
16553
16554 /* process pairs of constraints: check them for redundancy and try to aggregate them;
16555 * only apply this expensive procedure in exhaustive presolving timing
16556 */
16557 if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && (conshdlrdata->presolusehashing || conshdlrdata->presolpairwise) && !SCIPisStopped(scip) )
16558 {
16559 assert(firstchange >= 0);
16560
16561 if( firstchange < nconss && conshdlrdata->presolusehashing )
16562 {
16563 /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
16564 SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff,
16565 ndelconss, nchgsides) );
16566 }
16567
16568 if( firstchange < nconss && conshdlrdata->presolpairwise )
16569 {
16570 SCIP_CONS** usefulconss;
16571 int nusefulconss;
16572 int firstchangenew;
16573 SCIP_Longint npaircomparisons;
16574
16575 npaircomparisons = 0;
16576 oldndelconss = *ndelconss;
16577 oldnchgsides = *nchgsides;
16578 oldnchgcoefs = *nchgcoefs;
16579
16580 /* allocate temporary memory */
16581 SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, nconss) );
16582
16583 nusefulconss = 0;
16584 firstchangenew = -1;
16585 for( c = 0; c < nconss; ++c )
16586 {
16587 /* update firstchange */
16588 if( c == firstchange )
16589 firstchangenew = nusefulconss;
16590
16591 /* ignore inactive and modifiable constraints */
16592 if( !SCIPconsIsActive(conss[c]) || SCIPconsIsModifiable(conss[c]) )
16593 continue;
16594
16595 usefulconss[nusefulconss] = conss[c];
16596 ++nusefulconss;
16597 }
16598 firstchange = firstchangenew;
16599 assert(firstchangenew >= 0 && firstchangenew <= nusefulconss);
16600
16601 for( c = firstchange; c < nusefulconss && !cutoff && !SCIPisStopped(scip); ++c )
16602 {
16603 /* constraint has become inactive or modifiable during pairwise presolving */
16604 if( usefulconss[c] == NULL )
16605 continue;
16606
16607 npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? c : (c - firstchange); /*lint !e776*/
16608
16609 assert(SCIPconsIsActive(usefulconss[c]) && !SCIPconsIsModifiable(usefulconss[c]));
16610 SCIP_CALL( preprocessConstraintPairs(scip, usefulconss, firstchange, c, conshdlrdata->maxaggrnormscale,
16611 &cutoff, ndelconss, nchgsides, nchgcoefs) );
16612
16613 if( npaircomparisons > conshdlrdata->nmincomparisons )
16614 {
16615 assert(npaircomparisons > 0);
16616 if( ((*ndelconss - oldndelconss) + (*nchgsides - oldnchgsides)/2.0 + (*nchgcoefs - oldnchgcoefs)/10.0) / ((SCIP_Real) npaircomparisons) < conshdlrdata->mingainpernmincomp )
16617 break;
16618 oldndelconss = *ndelconss;
16619 oldnchgsides = *nchgsides;
16620 oldnchgcoefs = *nchgcoefs;
16621 npaircomparisons = 0;
16622 }
16623 }
16624 /* free temporary memory */
16625 SCIPfreeBufferArray(scip, &usefulconss);
16626 }
16627 }
16628
16629 /* before upgrading, check whether we can apply some additional dual presolving, because a variable only appears
16630 * in linear constraints and we therefore have full information about it
16631 */
16632 if( !cutoff && firstupgradetry < nconss
16633 && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
16634 && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides
16635 )
16636 {
16637 if( conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) && !SCIPisStopped(scip) )
16638 {
16639 SCIP_CALL( fullDualPresolve(scip, conss, nconss, &cutoff, nchgbds, nchgvartypes) );
16640 }
16641 }
16642
16643 /* try to upgrade constraints into a more specific constraint type;
16644 * only upgrade constraints, if no reductions were found in this round (otherwise, the linear constraint handler
16645 * may find additional reductions before giving control away to other (less intelligent?) constraint handlers)
16646 */
16647 if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && SCIPisPresolveFinished(scip) )
16648 {
16649 for( c = firstupgradetry; c < nconss && !SCIPisStopped(scip); ++c )
16650 {
16651 cons = conss[c];
16652
16653 /* don't upgrade modifiable constraints */
16654 if( SCIPconsIsModifiable(cons) )
16655 continue;
16656
16657 consdata = SCIPconsGetData(cons);
16658 assert(consdata != NULL);
16659
16660 /* only upgrade completely presolved constraints, that changed since the last upgrading call */
16661 if( consdata->upgradetried )
16662 continue;
16663 /* @todo force that upgrade will be performed later? */
16664 if( !consdata->presolved )
16665 continue;
16666
16667 consdata->upgradetried = TRUE;
16668 if( SCIPconsIsActive(cons) )
16669 {
16670 SCIP_CONS* upgdcons;
16671
16672 SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
16673 if( upgdcons != NULL )
16674 {
16675 /* add the upgraded constraint to the problem */
16676 SCIP_CALL( SCIPaddConsUpgrade(scip, cons, &upgdcons) );
16677 ++(*nupgdconss);
16678
16679 /* mark the linear constraint being upgraded and to be removed after presolving;
16680 * don't delete it directly, because it may help to preprocess other linear constraints
16681 */
16682 assert(!consdata->upgraded);
16683 consdata->upgraded = TRUE;
16684
16685 /* delete upgraded inequalities immediately;
16686 * delete upgraded equalities, if we don't need it anymore for aggregation and redundancy checking
16687 */
16688 if( SCIPisLT(scip, consdata->lhs, consdata->rhs)
16689 || !conshdlrdata->presolpairwise
16690 || (conshdlrdata->maxaggrnormscale == 0.0) )
16691 {
16692 SCIP_CALL( SCIPdelCons(scip, cons) );
16693 }
16694 }
16695 }
16696 }
16697 }
16698
16699 /* return the correct result code */
16700 if( cutoff )
16702 else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss
16703 || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
16705 else
16707
16708 return SCIP_OKAY;
16709}
16710
16711
16712/** propagation conflict resolving method of constraint handler */
16713static
16714SCIP_DECL_CONSRESPROP(consRespropLinear)
16715{ /*lint --e{715}*/
16716 assert(scip != NULL);
16717 assert(cons != NULL);
16718 assert(result != NULL);
16719
16720 SCIP_CALL( resolvePropagation(scip, cons, infervar, intToInferInfo(inferinfo), boundtype, bdchgidx, result) );
16721
16722 return SCIP_OKAY;
16723}
16724
16725
16726/** variable rounding lock method of constraint handler */
16727static
16728SCIP_DECL_CONSLOCK(consLockLinear)
16729{ /*lint --e{715}*/
16730 SCIP_CONSDATA* consdata;
16731 SCIP_Bool haslhs;
16732 SCIP_Bool hasrhs;
16733 int i;
16734
16735 assert(scip != NULL);
16736 assert(cons != NULL);
16737 consdata = SCIPconsGetData(cons);
16738 assert(consdata != NULL);
16739
16740 haslhs = !SCIPisInfinity(scip, -consdata->lhs);
16741 hasrhs = !SCIPisInfinity(scip, consdata->rhs);
16742
16743 /* update rounding locks of every single variable */
16744 for( i = 0; i < consdata->nvars; ++i )
16745 {
16746 if( SCIPisPositive(scip, consdata->vals[i]) )
16747 {
16748 if( haslhs )
16749 {
16750 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16751 }
16752 if( hasrhs )
16753 {
16754 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16755 }
16756 }
16757 else
16758 {
16759 if( haslhs )
16760 {
16761 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16762 }
16763 if( hasrhs )
16764 {
16765 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16766 }
16767 }
16768 }
16769
16770 return SCIP_OKAY;
16771}
16772
16773
16774/** variable deletion method of constraint handler */
16775static
16776SCIP_DECL_CONSDELVARS(consDelvarsLinear)
16777{
16778 assert(scip != NULL);
16779 assert(conshdlr != NULL);
16780 assert(conss != NULL || nconss == 0);
16781
16782 if( nconss > 0 )
16783 {
16784 SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
16785 }
16786
16787 return SCIP_OKAY;
16788}
16789
16790/** constraint display method of constraint handler */
16791static
16792SCIP_DECL_CONSPRINT(consPrintLinear)
16793{ /*lint --e{715}*/
16794 assert(scip != NULL);
16795 assert(conshdlr != NULL);
16796 assert(cons != NULL);
16797
16799
16800 return SCIP_OKAY;
16801}
16802
16803/** constraint copying method of constraint handler */
16804static
16805SCIP_DECL_CONSCOPY(consCopyLinear)
16806{ /*lint --e{715}*/
16807 SCIP_VAR** sourcevars;
16808 SCIP_Real* sourcecoefs;
16809 const char* consname;
16810 int nvars;
16811
16812 assert(scip != NULL);
16813 assert(sourcescip != NULL);
16814 assert(sourcecons != NULL);
16815
16816 /* get variables and coefficients of the source constraint */
16817 sourcevars = SCIPgetVarsLinear(sourcescip, sourcecons);
16818 sourcecoefs = SCIPgetValsLinear(sourcescip, sourcecons);
16819 nvars = SCIPgetNVarsLinear(sourcescip, sourcecons);
16820
16821 if( name != NULL )
16822 consname = name;
16823 else
16824 consname = SCIPconsGetName(sourcecons);
16825
16826 SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, sourcecoefs,
16827 SCIPgetLhsLinear(sourcescip, sourcecons), SCIPgetRhsLinear(sourcescip, sourcecons), varmap, consmap,
16828 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
16829 assert(cons != NULL || *valid == FALSE);
16830
16831 /* @todo should also the checkabsolute flag of the constraint be copied? */
16832
16833 return SCIP_OKAY;
16834}
16835
16836/** find operators '<=', '==', '>=', [free] in input string and return those places
16837 *
16838 * There should only be one operator, except for ranged rows for which exactly two operators '<=' must be present.
16839 */
16840static
16842 const char* str, /**< null terminated input string */
16843 char** firstoperator, /**< pointer to store the string starting at the first operator */
16844 char** secondoperator, /**< pointer to store the string starting at the second operator */
16845 SCIP_Bool* success /**< pointer to store if the line contains a valid operator order */
16846 )
16847{
16848 char* curr;
16849
16850 assert(str != NULL);
16851 assert(firstoperator != NULL);
16852 assert(secondoperator != NULL);
16853
16854 *firstoperator = NULL;
16855 *secondoperator = NULL;
16856
16857 curr = (char*)str;
16858 *success = TRUE;
16859
16860 /* loop over the input string to find all operators */
16861 while( *curr && *success )
16862 {
16863 SCIP_Bool found = FALSE;
16864 int increment = 1;
16865
16866 /* try if we found a possible operator */
16867 switch( *curr )
16868 {
16869 case '<':
16870 case '=':
16871 case '>':
16872
16873 /* check if the two characters curr[0,1] form an operator together */
16874 if( curr[1] == '=' )
16875 {
16876 found = TRUE;
16877
16878 /* update increment to continue after this operator */
16879 increment = 2;
16880 }
16881 break;
16882 case '[':
16883 if( strncmp(curr, "[free]", 6) == 0 )
16884 {
16885 found = TRUE;
16886
16887 /* update increment to continue after this operator */
16888 increment = 6;
16889 }
16890 break;
16891 default:
16892 break;
16893 }
16894
16895 /* assign the found operator to the first or second pointer and check for violations of the linear constraint grammar */
16896 if( found )
16897 {
16898 if( *firstoperator == NULL )
16899 {
16900 *firstoperator = curr;
16901 }
16902 else
16903 {
16904 if( *secondoperator != NULL )
16905 {
16906 SCIPerrorMessage("Found more than two operators in line %s\n", str);
16907 *success = FALSE;
16908 }
16909 else if( strncmp(*firstoperator, "<=", 2) != 0 )
16910 {
16911 SCIPerrorMessage("Two operators in line that is not a ranged row: %s", str);
16912 *success = FALSE;
16913 }
16914 else if( strncmp(curr, "<=", 2) != 0 )
16915 {
16916 SCIPerrorMessage("Bad second operator, expected ranged row specification: %s", str);
16917 *success = FALSE;
16918 }
16919
16920 *secondoperator = curr;
16921 }
16922 }
16923
16924 curr += increment;
16925 }
16926
16927 /* check if we did find at least one operator */
16928 if( *success )
16929 {
16930 if( *firstoperator == NULL )
16931 {
16932 SCIPerrorMessage("Could not find any operator in line %s\n", str);
16933 *success = FALSE;
16934 }
16935 }
16936}
16937
16938/** constraint parsing method of constraint handler */
16939static
16940SCIP_DECL_CONSPARSE(consParseLinear)
16941{ /*lint --e{715}*/
16942 SCIP_VAR** vars;
16943 SCIP_Real* coefs = NULL;
16944 int nvars;
16945 int coefssize = 100;
16946 int requsize;
16947 SCIP_Real lhs;
16948 SCIP_Real rhs;
16949 char* endptr;
16950 char* firstop;
16951 char* secondop;
16952 SCIP_Bool operatorsuccess;
16953 char* lhsstrptr = NULL;
16954 char* rhsstrptr = NULL;
16955 char* varstrptr = (char*)str;
16956
16957 assert(scip != NULL);
16958 assert(success != NULL);
16959 assert(str != NULL);
16960 assert(name != NULL);
16961 assert(cons != NULL);
16962
16963 *success = FALSE;
16964
16965 /* return of string empty */
16966 if( !(*str) )
16967 return SCIP_OKAY;
16968
16969 /* set left and right hand side to their default values */
16970 lhs = -SCIPinfinity(scip);
16971 rhs = SCIPinfinity(scip);
16972
16973 /* ignore whitespace */
16974 SCIP_CALL( SCIPskipSpace((char**)&str) );
16975
16976 /* find operators in the line first, all other remaining parsing depends on occurence of the operators '<=', '>=', '==',
16977 * and the special word [free]
16978 */
16979 findOperators(str, &firstop, &secondop, &operatorsuccess);
16980
16981 /* if the grammar is not valid for parsing a linear constraint, return */
16982 if( ! operatorsuccess )
16983 return SCIP_OKAY;
16984 assert(firstop != NULL);
16985
16986 /* assign the strings for parsing the left hand side, right hand side, and the linear variable sum */
16987 switch( *firstop )
16988 {
16989 case '<':
16990 assert(firstop[1] == '=');
16991 /* we have ranged row lhs <= a_1 x_1 + ... + a_n x_n <= rhs */
16992 if( secondop != NULL )
16993 {
16994 assert(secondop[0] == '<' && secondop[1] == '=');
16995 lhsstrptr = (char *)str;
16996 varstrptr = firstop + 2;
16997 rhsstrptr = secondop + 2;
16998 }
16999 else
17000 {
17001 /* we have an inequality with infinite left hand side a_1 x_1 + ... + a_n x_n <= rhs */
17002 lhsstrptr = NULL;
17003 varstrptr = (char *)str;
17004 rhsstrptr = firstop + 2;
17005 }
17006 break;
17007 case '>':
17008 assert(firstop[1] == '=');
17009 assert(secondop == NULL);
17010 /* we have a_1 x_1 + ... + a_n x_n >= lhs */
17011 lhsstrptr = firstop + 2;
17012 break;
17013 case '=':
17014 assert(firstop[1] == '=');
17015 assert(secondop == NULL);
17016 /* we have a_1 x_1 + ... + a_n x_n == lhs (rhs) */
17017 rhsstrptr = firstop + 2;
17018 lhsstrptr = firstop + 2;
17019 break;
17020 case '[':
17021 assert(strncmp(firstop, "[free]", 6) == 0);
17022 assert(secondop == NULL);
17023 /* nothing to assign in case of a free a_1 x_1 + ... + a_n x_n [free] */
17024 break;
17025 default:
17026 /* it should not be possible that a different character appears in that position */
17027 SCIPerrorMessage("Parsing has wrong operator character '%c', should be one of <=>[", *firstop);
17028 return SCIP_READERROR;
17029 }
17030
17031 /* parse left hand side, if necessary */
17032 if( lhsstrptr != NULL )
17033 {
17034 if( ! SCIPparseReal(scip, lhsstrptr, &lhs, &endptr) )
17035 {
17036 SCIPerrorMessage("error parsing left hand side number from <%s>\n", lhsstrptr);
17037 return SCIP_OKAY;
17038 }
17039
17040 /* in case of an equation, assign the left also to the right hand side */
17041 if( rhsstrptr == lhsstrptr )
17042 rhs = lhs;
17043 }
17044
17045 /* parse right hand side, if different from left hand side */
17046 if( rhsstrptr != NULL && rhsstrptr != lhsstrptr )
17047 {
17048 if( ! SCIPparseReal(scip, rhsstrptr, &rhs, &endptr) )
17049 {
17050 SCIPerrorMessage("error parsing right hand side number from <%s>\n", lhsstrptr);
17051 return SCIP_OKAY;
17052 }
17053 }
17054
17055 /* initialize buffers for storing the variables and coefficients */
17056 SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) );
17057 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
17058
17059 assert(varstrptr != NULL);
17060
17061 /* parse linear sum to get variables and coefficients */
17062 SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17063
17064 if( *success && requsize > coefssize )
17065 {
17066 /* realloc buffers and try again */
17067 coefssize = requsize;
17068 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, coefssize) );
17069 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
17070
17071 SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17072 assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
17073 }
17074
17075 if( !*success )
17076 {
17077 SCIPerrorMessage("no luck in parsing linear sum '%s'\n", varstrptr);
17078 }
17079 else
17080 {
17081 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
17082 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17083 }
17084
17085 SCIPfreeBufferArray(scip, &coefs);
17087
17088 return SCIP_OKAY;
17089}
17090
17091
17092/** constraint method of constraint handler which returns the variables (if possible) */
17093static
17094SCIP_DECL_CONSGETVARS(consGetVarsLinear)
17095{ /*lint --e{715}*/
17096 SCIP_CONSDATA* consdata;
17097
17098 consdata = SCIPconsGetData(cons);
17099 assert(consdata != NULL);
17100
17101 if( varssize < consdata->nvars )
17102 (*success) = FALSE;
17103 else
17104 {
17105 assert(vars != NULL);
17106
17107 BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
17108 (*success) = TRUE;
17109 }
17110
17111 return SCIP_OKAY;
17112}
17113
17114/**! [Callback for the number of variables]*/
17115/** constraint method of constraint handler which returns the number of variables (if possible) */
17116static
17117SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
17118{ /*lint --e{715}*/
17119 SCIP_CONSDATA* consdata;
17120
17121 consdata = SCIPconsGetData(cons);
17122 assert(consdata != NULL);
17123
17124 (*nvars) = consdata->nvars;
17125 (*success) = TRUE;
17126
17127 return SCIP_OKAY;
17128}
17129/**! [Callback for the number of variables]*/
17130
17131/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
17132static
17133SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphLinear)
17134{ /*lint --e{715}*/
17135 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
17136
17137 return SCIP_OKAY;
17138}
17139
17140/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
17141static
17142SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphLinear)
17143{ /*lint --e{715}*/
17144 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
17145
17146 return SCIP_OKAY;
17147}
17148
17149/*
17150 * Callback methods of event handler
17151 */
17152
17153/** execution method of event handler */
17154static
17155SCIP_DECL_EVENTEXEC(eventExecLinear)
17156{ /*lint --e{715}*/
17157 SCIP_CONS* cons;
17158 SCIP_CONSDATA* consdata;
17159 SCIP_VAR* var;
17160 SCIP_EVENTTYPE eventtype;
17161
17162 assert(scip != NULL);
17163 assert(eventhdlr != NULL);
17164 assert(eventdata != NULL);
17165 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
17166 assert(event != NULL);
17167
17168 cons = eventdata->cons;
17169 assert(cons != NULL);
17170 consdata = SCIPconsGetData(cons);
17171 assert(consdata != NULL);
17172
17173 /* we can skip events droped for deleted constraints */
17174 if( SCIPconsIsDeleted(cons) )
17175 return SCIP_OKAY;
17176
17177 eventtype = SCIPeventGetType(event);
17178 var = SCIPeventGetVar(event);
17179
17181 {
17182 SCIP_Real oldbound;
17183 SCIP_Real newbound;
17184 SCIP_Real val;
17185 int varpos;
17186
17187 varpos = eventdata->varpos;
17188 assert(0 <= varpos && varpos < consdata->nvars);
17189 oldbound = SCIPeventGetOldbound(event);
17190 newbound = SCIPeventGetNewbound(event);
17191 assert(var != NULL);
17192 assert(consdata->vars[varpos] == var);
17193 val = consdata->vals[varpos];
17194
17195 /* we only need to update the activities if the constraint is active,
17196 * otherwise we mark them to be invalid
17197 */
17198 if( SCIPconsIsActive(cons) )
17199 {
17200 /* update the activity values */
17202 consdataUpdateActivitiesLb(scip, consdata, var, oldbound, newbound, val, TRUE);
17203 else
17204 {
17206 consdataUpdateActivitiesUb(scip, consdata, var, oldbound, newbound, val, TRUE);
17207 }
17208 }
17209 else
17211
17212 consdata->presolved = FALSE;
17213 consdata->rangedrowpropagated = 0;
17214
17215 /* bound change can turn the constraint infeasible or redundant only if it was a tightening */
17217 {
17219
17220 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17221 if( consdata->maxactdeltavar == var )
17222 {
17223 consdata->maxactdelta = SCIP_INVALID;
17224 consdata->maxactdeltavar = NULL;
17225 }
17226
17227 /* check whether bound tightening might now be successful */
17228 if( consdata->boundstightened > 0)
17229 {
17230 switch( eventtype )
17231 {
17233 if( (val > 0.0 ? !SCIPisInfinity(scip, consdata->rhs) : !SCIPisInfinity(scip, -consdata->lhs)) )
17234 consdata->boundstightened = 0;
17235 break;
17237 if( (val > 0.0 ? !SCIPisInfinity(scip, -consdata->lhs) : !SCIPisInfinity(scip, consdata->rhs)) )
17238 consdata->boundstightened = 0;
17239 break;
17240 default:
17241 SCIPerrorMessage("invalid event type %" SCIP_EVENTTYPE_FORMAT "\n", eventtype);
17242 return SCIP_INVALIDDATA;
17243 }
17244 }
17245 }
17246 /* update maximal activity delta if a bound was relaxed */
17247 else if( !SCIPisInfinity(scip, consdata->maxactdelta) )
17248 {
17249 SCIP_Real lb;
17250 SCIP_Real ub;
17251 SCIP_Real domain;
17252 SCIP_Real delta;
17253
17255
17256 lb = SCIPvarGetLbLocal(var);
17257 ub = SCIPvarGetUbLocal(var);
17258
17259 domain = ub - lb;
17260 delta = REALABS(val) * domain;
17261
17262 if( delta > consdata->maxactdelta )
17263 {
17264 consdata->maxactdelta = delta;
17265 consdata->maxactdeltavar = var;
17266 }
17267 }
17268 }
17269 else if( (eventtype & SCIP_EVENTTYPE_VARFIXED) != SCIP_EVENTTYPE_DISABLED )
17270 {
17271 /* we want to remove the fixed variable */
17272 consdata->presolved = FALSE;
17273 consdata->removedfixings = FALSE;
17274 consdata->rangedrowpropagated = 0;
17275
17276 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17277 if( consdata->maxactdeltavar == var )
17278 {
17279 consdata->maxactdelta = SCIP_INVALID;
17280 consdata->maxactdeltavar = NULL;
17281 }
17282 }
17283 else if( (eventtype & SCIP_EVENTTYPE_VARUNLOCKED) != SCIP_EVENTTYPE_DISABLED )
17284 {
17285 /* there is only one lock left: we may multi-aggregate the variable as slack of an equation */
17288 consdata->presolved = FALSE;
17289 }
17290 else if( (eventtype & SCIP_EVENTTYPE_GBDCHANGED) != SCIP_EVENTTYPE_DISABLED )
17291 {
17292 SCIP_Real oldbound;
17293 SCIP_Real newbound;
17294 SCIP_Real val;
17295 int varpos;
17296
17297 varpos = eventdata->varpos;
17298 assert(0 <= varpos && varpos < consdata->nvars);
17299 oldbound = SCIPeventGetOldbound(event);
17300 newbound = SCIPeventGetNewbound(event);
17301 assert(var != NULL);
17302 assert(consdata->vars[varpos] == var);
17303 val = consdata->vals[varpos];
17304
17305 consdata->rangedrowpropagated = 0;
17306
17307 /* update the activity values */
17309 consdataUpdateActivitiesGlbLb(scip, consdata, oldbound, newbound, val, TRUE);
17310 else
17311 {
17313 consdataUpdateActivitiesGlbUb(scip, consdata, oldbound, newbound, val, TRUE);
17314 }
17315
17316 /* if the variable is binary but not fixed it had to become binary due to this global change */
17318 {
17320 consdata->indexsorted = FALSE;
17321 else
17322 consdata->coefsorted = FALSE;
17323 }
17324 }
17325 else if( (eventtype & SCIP_EVENTTYPE_TYPECHANGED) != SCIP_EVENTTYPE_DISABLED )
17326 {
17328
17329 /* for presolving it only matters if a variable becomes integral */
17330 consdata->presolved = (consdata->presolved && (SCIPeventGetOldtype(event) != SCIP_VARTYPE_CONTINUOUS || SCIPvarIsImpliedIntegral(var)));
17331
17332 /* the ordering is preserved if the variable remains binary */
17333 consdata->indexsorted = (consdata->indexsorted && SCIPvarIsBinary(var) && (SCIPeventGetOldtype(event) != SCIP_VARTYPE_CONTINUOUS || SCIPvarIsImpliedIntegral(var)));
17334 }
17336 {
17338
17339 /* for presolving it only matters if a variable becomes integral */
17340 consdata->presolved = (consdata->presolved && (SCIPeventGetOldImpltype(event) != SCIP_IMPLINTTYPE_NONE || SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS));
17341
17342 /* the ordering is preserved if the variable remains binary */
17343 consdata->indexsorted = (consdata->indexsorted && SCIPvarIsBinary(var) && (SCIPeventGetOldImpltype(event) != SCIP_IMPLINTTYPE_NONE || SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS));
17344 }
17345 else
17346 {
17348 consdata->varsdeleted = TRUE;
17349 }
17350
17351 return SCIP_OKAY;
17352}
17353
17354
17355/*
17356 * Callback methods of conflict handler
17357 */
17358
17359/** conflict processing method of conflict handler (called when conflict was found) */
17360static
17361SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
17362{ /*lint --e{715}*/
17363 SCIP_VAR** vars;
17364 SCIP_Real* vals;
17365 SCIP_Real lhs;
17366 int i;
17367
17368 assert(scip != NULL);
17369 assert(conflicthdlr != NULL);
17370 assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
17371 assert(bdchginfos != NULL || nbdchginfos == 0);
17372 assert(result != NULL);
17373
17374 /* don't process already resolved conflicts */
17375 if( resolved )
17376 {
17378 return SCIP_OKAY;
17379 }
17380
17382
17383 /* create array of variables and coefficients: sum_{i \in P} x_i - sum_{i \in N} x_i >= 1 - |N| */
17384 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
17385 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nbdchginfos) );
17386 lhs = 1.0;
17387 for( i = 0; i < nbdchginfos; ++i )
17388 {
17389 assert(bdchginfos != NULL);
17390
17391 vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
17392
17393 /* we can only treat binary variables */
17394 /**@todo extend linear conflict constraints to some non-binary cases */
17395 if( !SCIPvarIsBinary(vars[i]) )
17396 break;
17397
17398 /* check whether the variable is fixed to zero (P) or one (N) in the conflict set */
17399 if( SCIPbdchginfoGetNewbound(bdchginfos[i]) < 0.5 )
17400 vals[i] = 1.0;
17401 else
17402 {
17403 vals[i] = -1.0;
17404 lhs -= 1.0;
17405 }
17406 }
17407
17408 if( i == nbdchginfos )
17409 {
17410 SCIP_CONS* cons;
17411 SCIP_CONS* upgdcons;
17412 char consname[SCIP_MAXSTRLEN];
17413
17414 /* create a constraint out of the conflict set */
17416 SCIP_CALL( SCIPcreateConsLinear(scip, &cons, consname, nbdchginfos, vars, vals, lhs, SCIPinfinity(scip),
17417 FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
17418
17419 /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
17420 SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
17421 if( upgdcons != NULL )
17422 {
17423 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
17424 cons = upgdcons;
17425 }
17426
17427 /* add conflict to SCIP */
17428 SCIP_CALL( SCIPaddConflict(scip, node, &cons, validnode, conftype, cutoffinvolved) );
17429
17431 }
17432
17433 /* free temporary memory */
17434 SCIPfreeBufferArray(scip, &vals);
17436
17437 return SCIP_OKAY;
17438}
17439
17440
17441/*
17442 * Nonlinear constraint upgrading
17443 */
17444
17445/** tries to upgrade a nonlinear constraint into a linear constraint */
17446static
17447SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
17448{
17449 SCIP_CONSDATA* consdata;
17450 SCIP_EXPR* expr;
17451 SCIP_Real lhs;
17452 SCIP_Real rhs;
17453 int i;
17454
17455 assert(nupgdconss != NULL);
17456 assert(upgdconss != NULL);
17457 assert(upgdconsssize > 0);
17458
17459 expr = SCIPgetExprNonlinear(cons);
17460 assert(expr != NULL);
17461
17462 /* not a linear constraint if the expression is not a sum
17463 * (unless the expression is a variable or a constant or a constant*variable, but these are simplified away in cons_nonlinear)
17464 */
17465 if( !SCIPisExprSum(scip, expr) )
17466 return SCIP_OKAY;
17467
17468 /* if at least one child is not a variable, then not a linear constraint */
17469 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17470 if( !SCIPisExprVar(scip, SCIPexprGetChildren(expr)[i]) )
17471 return SCIP_OKAY;
17472
17473 /* consider constant part of the sum expression */
17476
17477 SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
17478 0, NULL, NULL, lhs, rhs,
17482 SCIPconsIsStickingAtNode(cons)) );
17483 assert(upgdconss[0] != NULL);
17484
17485 consdata = SCIPconsGetData(upgdconss[0]);
17486
17487 /* add linear terms */
17489 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17490 {
17492 }
17493
17494 /* check violation of this linear constraint with absolute tolerances, to be consistent with the original nonlinear constraint */
17495 consdata->checkabsolute = TRUE;
17496
17497 *nupgdconss = 1;
17498
17499 SCIPdebugMsg(scip, "created linear constraint:\n");
17500 SCIPdebugPrintCons(scip, upgdconss[0], NULL);
17501
17502 return SCIP_OKAY;
17503} /*lint !e715*/
17504
17505/*
17506 * constraint specific interface methods
17507 */
17508
17509/** creates the handler for linear constraints and includes it in SCIP */
17511 SCIP* scip /**< SCIP data structure */
17512 )
17513{
17514 SCIP_CONSHDLRDATA* conshdlrdata;
17515 SCIP_CONSHDLR* conshdlr;
17516 SCIP_EVENTHDLR* eventhdlr;
17517 SCIP_CONFLICTHDLR* conflicthdlr;
17518
17519 assert(scip != NULL);
17520
17521 /* create event handler for bound change events */
17523 eventExecLinear, NULL) );
17524
17525 /* create conflict handler for linear constraints */
17527 conflictExecLinear, NULL) );
17528
17529 /* create constraint handler data */
17530 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
17531
17532 /* include constraint handler */
17535 consEnfolpLinear, consEnfopsLinear, consCheckLinear, consLockLinear,
17536 conshdlrdata) );
17537
17538 assert(conshdlr != NULL);
17539
17540 /* set non-fundamental callbacks via specific setter functions */
17541 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLinear, consCopyLinear) );
17542 SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveLinear) );
17543 SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveLinear) );
17544 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLinear) );
17545 SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsLinear) );
17546 SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitLinear) );
17547 SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLinear) );
17548 SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolLinear) );
17549 SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLinear) );
17550 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLinear) );
17551 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLinear) );
17552 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLinear) );
17553 SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitLinear) );
17554 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLinear) );
17555 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLinear) );
17557 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLinear) );
17560 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLinear) );
17561 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLinear, consSepasolLinear, CONSHDLR_SEPAFREQ,
17563 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLinear) );
17564 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLinear) );
17565 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphLinear) );
17566 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphLinear) );
17567
17568 if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
17569 {
17570 /* include the linear constraint upgrade in the nonlinear constraint handler */
17572 }
17573
17574 /* add linear constraint handler parameters */
17576 "constraints/" CONSHDLR_NAME "/tightenboundsfreq",
17577 "multiplier on propagation frequency, how often the bounds are tightened (-1: never, 0: only at root)",
17578 &conshdlrdata->tightenboundsfreq, TRUE, DEFAULT_TIGHTENBOUNDSFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17580 "constraints/" CONSHDLR_NAME "/maxrounds",
17581 "maximal number of separation rounds per node (-1: unlimited)",
17582 &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
17584 "constraints/" CONSHDLR_NAME "/maxroundsroot",
17585 "maximal number of separation rounds per node in the root node (-1: unlimited)",
17586 &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
17588 "constraints/" CONSHDLR_NAME "/maxsepacuts",
17589 "maximal number of cuts separated per separation round",
17590 &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
17592 "constraints/" CONSHDLR_NAME "/maxsepacutsroot",
17593 "maximal number of cuts separated per separation round in the root node",
17594 &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
17596 "constraints/" CONSHDLR_NAME "/presolpairwise",
17597 "should pairwise constraint comparison be performed in presolving?",
17598 &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
17600 "constraints/" CONSHDLR_NAME "/presolusehashing",
17601 "should hash table be used for detecting redundant constraints in advance",
17602 &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
17604 "constraints/" CONSHDLR_NAME "/nmincomparisons",
17605 "number for minimal pairwise presolve comparisons",
17606 &conshdlrdata->nmincomparisons, TRUE, DEFAULT_NMINCOMPARISONS, 1, INT_MAX, NULL, NULL) );
17608 "constraints/" CONSHDLR_NAME "/mingainpernmincomparisons",
17609 "minimal gain per minimal pairwise presolve comparisons to repeat pairwise comparison round",
17610 &conshdlrdata->mingainpernmincomp, TRUE, DEFAULT_MINGAINPERNMINCOMP, 0.0, 1.0, NULL, NULL) );
17612 "constraints/" CONSHDLR_NAME "/maxaggrnormscale",
17613 "maximal allowed relative gain in maximum norm for constraint aggregation (0.0: disable constraint aggregation)",
17614 &conshdlrdata->maxaggrnormscale, TRUE, DEFAULT_MAXAGGRNORMSCALE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17616 "constraints/" CONSHDLR_NAME "/maxeasyactivitydelta",
17617 "maximum activity delta to run easy propagation on linear constraint (faster, but numerically less stable)",
17618 &conshdlrdata->maxeasyactivitydelta, TRUE, DEFAULT_MAXEASYACTIVITYDELTA, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17620 "constraints/" CONSHDLR_NAME "/maxcardbounddist",
17621 "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for separating knapsack cardinality cuts",
17622 &conshdlrdata->maxcardbounddist, TRUE, DEFAULT_MAXCARDBOUNDDIST, 0.0, 1.0, NULL, NULL) );
17624 "constraints/" CONSHDLR_NAME "/separateall",
17625 "should all constraints be subject to cardinality cut generation instead of only the ones with non-zero dual value?",
17626 &conshdlrdata->separateall, FALSE, DEFAULT_SEPARATEALL, NULL, NULL) );
17628 "constraints/" CONSHDLR_NAME "/aggregatevariables",
17629 "should presolving search for aggregations in equations",
17630 &conshdlrdata->aggregatevariables, TRUE, DEFAULT_AGGREGATEVARIABLES, NULL, NULL) );
17632 "constraints/" CONSHDLR_NAME "/simplifyinequalities",
17633 "should presolving try to simplify inequalities",
17634 &conshdlrdata->simplifyinequalities, TRUE, DEFAULT_SIMPLIFYINEQUALITIES, NULL, NULL) );
17636 "constraints/" CONSHDLR_NAME "/dualpresolving",
17637 "should dual presolving steps be performed?",
17638 &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
17640 "constraints/" CONSHDLR_NAME "/singletonstuffing",
17641 "should stuffing of singleton continuous variables be performed?",
17642 &conshdlrdata->singletonstuffing, TRUE, DEFAULT_SINGLETONSTUFFING, NULL, NULL) );
17644 "constraints/" CONSHDLR_NAME "/singlevarstuffing",
17645 "should single variable stuffing be performed, which tries to fulfill constraints using the cheapest variable?",
17646 &conshdlrdata->singlevarstuffing, TRUE, DEFAULT_SINGLEVARSTUFFING, NULL, NULL) );
17648 "constraints/" CONSHDLR_NAME "/sortvars", "apply binaries sorting in decr. order of coeff abs value?",
17649 &conshdlrdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL) );
17651 "constraints/" CONSHDLR_NAME "/checkrelmaxabs",
17652 "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)?",
17653 &conshdlrdata->checkrelmaxabs, TRUE, DEFAULT_CHECKRELMAXABS, NULL, NULL) );
17655 "constraints/" CONSHDLR_NAME "/detectcutoffbound",
17656 "should presolving try to detect constraints parallel to the objective function defining an upper bound and prevent these constraints from entering the LP?",
17657 &conshdlrdata->detectcutoffbound, TRUE, DEFAULT_DETECTCUTOFFBOUND, NULL, NULL) );
17659 "constraints/" CONSHDLR_NAME "/detectlowerbound",
17660 "should presolving try to detect constraints parallel to the objective function defining a lower bound and prevent these constraints from entering the LP?",
17661 &conshdlrdata->detectlowerbound, TRUE, DEFAULT_DETECTLOWERBOUND, NULL, NULL) );
17663 "constraints/" CONSHDLR_NAME "/detectpartialobjective",
17664 "should presolving try to detect subsets of constraints parallel to the objective function?",
17665 &conshdlrdata->detectpartialobjective, TRUE, DEFAULT_DETECTPARTIALOBJECTIVE, NULL, NULL) );
17667 "constraints/" CONSHDLR_NAME "/rangedrowpropagation",
17668 "should presolving and propagation try to improve bounds, detect infeasibility, and extract sub-constraints from ranged rows and equations?",
17669 &conshdlrdata->rangedrowpropagation, TRUE, DEFAULT_RANGEDROWPROPAGATION, NULL, NULL) );
17671 "constraints/" CONSHDLR_NAME "/rangedrowartcons",
17672 "should presolving and propagation extract sub-constraints from ranged rows and equations?",
17673 &conshdlrdata->rangedrowartcons, TRUE, DEFAULT_RANGEDROWARTCONS, NULL, NULL) );
17675 "constraints/" CONSHDLR_NAME "/rangedrowmaxdepth",
17676 "maximum depth to apply ranged row propagation",
17677 &conshdlrdata->rangedrowmaxdepth, TRUE, DEFAULT_RANGEDROWMAXDEPTH, 0, INT_MAX, NULL, NULL) );
17679 "constraints/" CONSHDLR_NAME "/rangedrowfreq",
17680 "frequency for applying ranged row propagation",
17681 &conshdlrdata->rangedrowfreq, TRUE, DEFAULT_RANGEDROWFREQ, 1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17683 "constraints/" CONSHDLR_NAME "/multaggrremove",
17684 "should multi-aggregations only be performed if the constraint can be removed afterwards?",
17685 &conshdlrdata->multaggrremove, TRUE, DEFAULT_MULTAGGRREMOVE, NULL, NULL) );
17687 "constraints/" CONSHDLR_NAME "/maxmultaggrquot",
17688 "maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation",
17689 &conshdlrdata->maxmultaggrquot, TRUE, DEFAULT_MAXMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17691 "constraints/" CONSHDLR_NAME "/maxdualmultaggrquot",
17692 "maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation",
17693 &conshdlrdata->maxdualmultaggrquot, TRUE, DEFAULT_MAXDUALMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17695 "constraints/" CONSHDLR_NAME "/extractcliques",
17696 "should Cliques be extracted?",
17697 &conshdlrdata->extractcliques, TRUE, DEFAULT_EXTRACTCLIQUES, NULL, NULL) );
17698
17699 return SCIP_OKAY;
17700}
17701
17702/** includes a linear constraint update method into the linear constraint handler */
17704 SCIP* scip, /**< SCIP data structure */
17705 SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
17706 int priority, /**< priority of upgrading method */
17707 const char* conshdlrname /**< name of the constraint handler */
17708 )
17709{
17710 SCIP_CONSHDLR* conshdlr;
17711 SCIP_CONSHDLRDATA* conshdlrdata;
17712 SCIP_LINCONSUPGRADE* linconsupgrade;
17714 char paramdesc[SCIP_MAXSTRLEN];
17715
17716 assert(scip != NULL);
17717 assert(linconsupgd != NULL);
17718 assert(conshdlrname != NULL );
17719
17720 /* find the linear constraint handler */
17721 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17722 if( conshdlr == NULL )
17723 {
17724 SCIPerrorMessage("linear constraint handler not found\n");
17725 return SCIP_PLUGINNOTFOUND;
17726 }
17727
17728 conshdlrdata = SCIPconshdlrGetData(conshdlr);
17729 assert(conshdlrdata != NULL);
17730
17731 /* check if linear constraint update method already exists in constraint handler data */
17732 if( !conshdlrdataHasUpgrade(scip, conshdlrdata, linconsupgd, conshdlrname) )
17733 {
17734 /* create a linear constraint upgrade data object */
17735 SCIP_CALL( linconsupgradeCreate(scip, &linconsupgrade, linconsupgd, priority) );
17736
17737 /* insert linear constraint update method into constraint handler data */
17738 SCIP_CALL( conshdlrdataIncludeUpgrade(scip, conshdlrdata, linconsupgrade) );
17739
17740 /* adds parameter to turn on and off the upgrading step */
17741 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/linear/upgrade/%s", conshdlrname);
17742 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "enable linear upgrading for constraint handler <%s>", conshdlrname);
17744 paramname, paramdesc,
17745 &linconsupgrade->active, FALSE, TRUE, NULL, NULL) );
17746 }
17747
17748 return SCIP_OKAY;
17749}
17750
17751/** creates and captures a linear constraint
17752 *
17753 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17754 */
17756 SCIP* scip, /**< SCIP data structure */
17757 SCIP_CONS** cons, /**< pointer to hold the created constraint */
17758 const char* name, /**< name of constraint */
17759 int nvars, /**< number of nonzeros in the constraint */
17760 SCIP_VAR** vars, /**< array with variables of constraint entries */
17761 SCIP_Real* vals, /**< array with coefficients of constraint entries */
17762 SCIP_Real lhs, /**< left hand side of constraint */
17763 SCIP_Real rhs, /**< right hand side of constraint */
17764 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
17765 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
17766 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
17767 * Usually set to TRUE. */
17768 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
17769 * TRUE for model constraints, FALSE for additional, redundant constraints. */
17770 SCIP_Bool check, /**< should the constraint be checked for feasibility?
17771 * TRUE for model constraints, FALSE for additional, redundant constraints. */
17772 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
17773 * Usually set to TRUE. */
17774 SCIP_Bool local, /**< is constraint only valid locally?
17775 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
17776 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
17777 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
17778 * adds coefficients to this constraint. */
17779 SCIP_Bool dynamic, /**< is constraint subject to aging?
17780 * Usually set to FALSE. Set to TRUE for own cuts which
17781 * are separated as constraints. */
17782 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
17783 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
17784 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
17785 * if it may be moved to a more global node?
17786 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
17787 )
17788{
17789 SCIP_CONSHDLR* conshdlr;
17790 SCIP_CONSDATA* consdata;
17791 int i;
17792
17793 assert(scip != NULL);
17794 assert(cons != NULL);
17795
17796 /* find the linear constraint handler */
17797 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17798 if( conshdlr == NULL )
17799 {
17800 SCIPerrorMessage("linear constraint handler not found\n");
17801 return SCIP_PLUGINNOTFOUND;
17802 }
17803
17804 /* terminate if a coefficient is infinite */
17805 assert(SCIPisFinite(lhs));
17806 assert(SCIPisFinite(rhs));
17807 for( i = 0; i < nvars; ++i )
17808 {
17809 assert(SCIPisFinite(vals[i]));
17810 if( SCIPisInfinity(scip, REALABS(vals[i])) )
17811 {
17812 SCIPerrorMessage("coefficient of variable <%s> in constraint <%s> is infinite,"
17813 " consider adjusting the infinity threshold\n", SCIPvarGetName(vars[i]), name);
17814 SCIPABORT();
17815 return SCIP_INVALIDDATA;
17816 }
17817 }
17818
17819 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
17820 * constraint after presolving we have to ensure that it holds active variables
17821 */
17823 {
17824 SCIP_VAR** consvars;
17825 SCIP_Real* consvals;
17826 SCIP_Real constant = 0.0;
17827 int nconsvars;
17828 int requiredsize;
17829
17830 nconsvars = nvars;
17831 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, vars, nconsvars) );
17832 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) );
17833
17834 /* get active variables for new constraint */
17835 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize) );
17836
17837 /* if space was not enough we need to resize the buffers */
17838 if( requiredsize > nconsvars )
17839 {
17840 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
17841 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
17842
17843 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize) );
17844 }
17845 assert(requiredsize == nconsvars);
17846
17847 /* adjust sides and check that we do not subtract infinity values */
17848 if( SCIPisInfinity(scip, REALABS(constant)) )
17849 {
17850 SCIPfreeBufferArray(scip, &consvals);
17851 SCIPfreeBufferArray(scip, &consvars);
17852 SCIPerrorMessage("while creating constraint <%s> inactive variables lead to an infinite constant\n", name);
17853 SCIPABORT();
17854 return SCIP_INVALIDDATA;
17855 }
17856 else
17857 {
17858 if( !SCIPisInfinity(scip, REALABS(lhs)) )
17859 lhs -= constant;
17860 if( !SCIPisInfinity(scip, REALABS(rhs)) )
17861 rhs -= constant;
17862
17863 if( SCIPisInfinity(scip, -lhs) )
17864 lhs = -SCIPinfinity(scip);
17865 else if( SCIPisInfinity(scip, lhs) )
17866 lhs = SCIPinfinity(scip);
17867
17868 if( SCIPisInfinity(scip, rhs) )
17869 rhs = SCIPinfinity(scip);
17870 else if( SCIPisInfinity(scip, -rhs) )
17871 rhs = -SCIPinfinity(scip);
17872 }
17873
17874 /* create constraint data */
17875 SCIP_CALL( consdataCreate(scip, &consdata, nconsvars, consvars, consvals, lhs, rhs) );
17876
17877 SCIPfreeBufferArray(scip, &consvals);
17878 SCIPfreeBufferArray(scip, &consvars);
17879 }
17880 else
17881 {
17882 /* create constraint data */
17883 SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, vals, lhs, rhs) );
17884 }
17885 assert(consdata != NULL);
17886
17887#ifndef NDEBUG
17888 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
17889 if( check || enforce )
17890 {
17891 int n;
17892 for(n = consdata->nvars - 1; n >= 0; --n )
17893 assert(!SCIPvarIsRelaxationOnly(consdata->vars[n]));
17894 }
17895#endif
17896
17897 /* create constraint */
17898 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
17899 local, modifiable, dynamic, removable, stickingatnode) );
17900
17901 return SCIP_OKAY;
17902}
17903
17904/** creates and captures a linear constraint
17905 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
17906 * method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
17907 *
17908 * @see SCIPcreateConsLinear() for information about the basic constraint flag configuration
17909 *
17910 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17911 */
17913 SCIP* scip, /**< SCIP data structure */
17914 SCIP_CONS** cons, /**< pointer to hold the created constraint */
17915 const char* name, /**< name of constraint */
17916 int nvars, /**< number of nonzeros in the constraint */
17917 SCIP_VAR** vars, /**< array with variables of constraint entries */
17918 SCIP_Real* vals, /**< array with coefficients of constraint entries */
17919 SCIP_Real lhs, /**< left hand side of constraint */
17920 SCIP_Real rhs /**< right hand side of constraint */
17921 )
17922{
17923 assert(scip != NULL);
17924
17925 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, vals, lhs, rhs,
17927
17928 return SCIP_OKAY;
17929}
17930
17931/** creates by copying and captures a linear constraint */
17933 SCIP* scip, /**< target SCIP data structure */
17934 SCIP_CONS** cons, /**< pointer to store the created target constraint */
17935 SCIP* sourcescip, /**< source SCIP data structure */
17936 const char* name, /**< name of constraint */
17937 int nvars, /**< number of variables in source variable array */
17938 SCIP_VAR** sourcevars, /**< source variables of the linear constraints */
17939 SCIP_Real* sourcecoefs, /**< coefficient array of the linear constraint, or NULL if all coefficients are one */
17940 SCIP_Real lhs, /**< left hand side of the linear constraint */
17941 SCIP_Real rhs, /**< right hand side of the linear constraint */
17942 SCIP_HASHMAP* varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
17943 * variables of the target SCIP */
17944 SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
17945 * target constraints */
17946 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
17947 SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
17948 SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
17949 SCIP_Bool check, /**< should the constraint be checked for feasibility? */
17950 SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
17951 SCIP_Bool local, /**< is constraint only valid locally? */
17952 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
17953 SCIP_Bool dynamic, /**< is constraint subject to aging? */
17954 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
17955 SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even
17956 * if it may be moved to a more global node? */
17957 SCIP_Bool global, /**< create a global or a local copy? */
17958 SCIP_Bool* valid /**< pointer to store if the copying was valid */
17959 )
17960{
17961 SCIP_VAR** vars;
17962 SCIP_Real* coefs;
17963
17964 SCIP_Real constant;
17965 int requiredsize;
17966 int v;
17967 SCIP_Bool success;
17968
17969 if( SCIPisGT(scip, lhs, rhs) )
17970 {
17971 *valid = FALSE;
17972 return SCIP_OKAY;
17973 }
17974
17975 (*valid) = TRUE;
17976
17977 if( nvars == 0 )
17978 {
17979 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, 0, NULL, NULL, lhs, rhs,
17980 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17981 return SCIP_OKAY;
17982 }
17983
17984 /* duplicate variable array */
17986
17987 /* duplicate coefficient array */
17988 if( sourcecoefs != NULL )
17989 {
17990 SCIP_CALL( SCIPduplicateBufferArray(scip, &coefs, sourcecoefs, nvars) );
17991 }
17992 else
17993 {
17995 for( v = 0; v < nvars; ++v )
17996 coefs[v] = 1.0;
17997 }
17998
17999 constant = 0.0;
18000
18001 /* transform source variable to active variables of the source SCIP since only these can be mapped to variables of
18002 * the target SCIP
18003 */
18004 if( !SCIPvarIsOriginal(vars[0]) )
18005 {
18006 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize) );
18007
18008 if( requiredsize > nvars )
18009 {
18010 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
18011 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requiredsize) );
18012
18013 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize) );
18014 }
18015 assert(requiredsize == nvars);
18016 }
18017 else
18018 {
18019 for( v = 0; v < nvars; ++v )
18020 {
18022 SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &coefs[v], &constant) );
18023 assert(vars[v] != NULL);
18024 }
18025 }
18026
18027 success = TRUE;
18028 /* map variables of the source constraint to variables of the target SCIP */
18029 for( v = 0; v < nvars && success; ++v )
18030 {
18031 SCIP_VAR* var;
18032 var = vars[v];
18033
18034 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18035 assert(!SCIPvarIsRelaxationOnly(var) || (!check && !enforce));
18036
18037 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &vars[v], varmap, consmap, global, &success) );
18038 assert(!(success) || vars[v] != NULL);
18039 }
18040
18041 /* only create the target constraint, if all variables could be copied */
18042 if( success )
18043 {
18044 if( !SCIPisInfinity(scip, -lhs) )
18045 lhs -= constant;
18046
18047 if( !SCIPisInfinity(scip, rhs) )
18048 rhs -= constant;
18049
18050 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
18051 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18052 }
18053 else
18054 *valid = FALSE;
18055
18056 /* free buffer array */
18057 SCIPfreeBufferArray(scip, &coefs);
18059
18060 return SCIP_OKAY;
18061}
18062
18063/** adds coefficient to linear constraint (if it is not zero) */
18065 SCIP* scip, /**< SCIP data structure */
18066 SCIP_CONS* cons, /**< constraint data */
18067 SCIP_VAR* var, /**< variable of constraint entry */
18068 SCIP_Real val /**< coefficient of constraint entry */
18069 )
18070{
18071 assert(scip != NULL);
18072 assert(cons != NULL);
18073 assert(var != NULL);
18074
18075 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18076 {
18077 SCIPerrorMessage("constraint is not linear\n");
18078 return SCIP_INVALIDDATA;
18079 }
18080
18081 /* terminate if coefficient is infinite */
18082 assert(SCIPisFinite(val));
18083 if( SCIPisInfinity(scip, REALABS(val)) )
18084 {
18085 SCIPerrorMessage("coefficient of variable <%s> in constraint <%s> is infinite,"
18086 " consider adjusting the infinity threshold\n", SCIPvarGetName(var), SCIPconsGetName(cons));
18087 SCIPABORT();
18088 return SCIP_INVALIDDATA;
18089 }
18090
18091 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
18092 * constraint after presolving we have to ensure that it holds active variables
18093 */
18095 {
18096 SCIP_CONSDATA* consdata;
18097 SCIP_VAR** consvars;
18098 SCIP_Real* consvals;
18099 SCIP_Real constant = 0.0;
18100 SCIP_Real rhs;
18101 SCIP_Real lhs;
18102 int nconsvars;
18103 int requiredsize;
18104 int v;
18105
18106 nconsvars = 1;
18107 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
18108 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
18109 consvars[0] = var;
18110 consvals[0] = val;
18111
18112 /* get active variables for new constraint */
18113 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize) );
18114
18115 /* if space was not enough we need to resize the buffers */
18116 if( requiredsize > nconsvars )
18117 {
18118 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
18119 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
18120
18121 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize) );
18122 }
18123 assert(requiredsize == nconsvars);
18124
18125 consdata = SCIPconsGetData(cons);
18126 assert(consdata != NULL);
18127
18128 lhs = consdata->lhs;
18129 rhs = consdata->rhs;
18130
18131 /* adjust sides and check that we do not subtract infinity values */
18132 /* constant is infinite */
18133 if( SCIPisInfinity(scip, REALABS(constant)) )
18134 {
18135 if( constant < 0.0 )
18136 {
18137 if( SCIPisInfinity(scip, lhs) )
18138 {
18139 SCIPfreeBufferArray(scip, &consvals);
18140 SCIPfreeBufferArray(scip, &consvars);
18141
18142 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));
18143
18144 SCIPABORT();
18145 return SCIP_INVALIDDATA; /*lint !e527*/
18146 }
18147 if( SCIPisInfinity(scip, rhs) )
18148 {
18149 SCIPfreeBufferArray(scip, &consvals);
18150 SCIPfreeBufferArray(scip, &consvars);
18151
18152 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));
18153
18154 SCIPABORT();
18155 return SCIP_INVALIDDATA; /*lint !e527*/
18156 }
18157
18158 lhs = -SCIPinfinity(scip);
18159 rhs = -SCIPinfinity(scip);
18160 }
18161 else
18162 {
18163 if( SCIPisInfinity(scip, -lhs) )
18164 {
18165 SCIPfreeBufferArray(scip, &consvals);
18166 SCIPfreeBufferArray(scip, &consvars);
18167
18168 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));
18169
18170 SCIPABORT();
18171 return SCIP_INVALIDDATA; /*lint !e527*/
18172 }
18173 if( SCIPisInfinity(scip, -rhs) )
18174 {
18175 SCIPfreeBufferArray(scip, &consvals);
18176 SCIPfreeBufferArray(scip, &consvars);
18177
18178 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));
18179
18180 SCIPABORT();
18181 return SCIP_INVALIDDATA; /*lint !e527*/
18182 }
18183
18184 lhs = SCIPinfinity(scip);
18185 rhs = SCIPinfinity(scip);
18186 }
18187 }
18188 /* constant is not infinite */
18189 else
18190 {
18191 if( !SCIPisInfinity(scip, REALABS(lhs)) )
18192 lhs -= constant;
18193 if( !SCIPisInfinity(scip, REALABS(rhs)) )
18194 rhs -= constant;
18195
18196 if( SCIPisInfinity(scip, -lhs) )
18197 lhs = -SCIPinfinity(scip);
18198 else if( SCIPisInfinity(scip, lhs) )
18199 lhs = SCIPinfinity(scip);
18200
18201 if( SCIPisInfinity(scip, rhs) )
18202 rhs = SCIPinfinity(scip);
18203 else if( SCIPisInfinity(scip, -rhs) )
18204 rhs = -SCIPinfinity(scip);
18205 }
18206
18207 /* add all active variables to constraint */
18208 for( v = nconsvars - 1; v >= 0; --v )
18209 {
18210 if( !SCIPisZero(scip, consvals[v]) )
18211 {
18212 SCIP_CALL( addCoef(scip, cons, consvars[v], consvals[v]) );
18213 }
18214 }
18215
18216 /* update left and right hand sides */
18217 SCIP_CALL( chgLhs(scip, cons, lhs) );
18218 SCIP_CALL( chgRhs(scip, cons, rhs) );
18219
18220 SCIPfreeBufferArray(scip, &consvals);
18221 SCIPfreeBufferArray(scip, &consvars);
18222 }
18223 else if( !SCIPisZero(scip, val) )
18224 {
18225 SCIP_CALL( addCoef(scip, cons, var, val) );
18226 }
18227
18228 return SCIP_OKAY;
18229}
18230
18231/** changes coefficient of variable in linear constraint; deletes the variable if coefficient is zero; adds variable if
18232 * not yet contained in the constraint
18233 *
18234 * @note This method may only be called during problem creation stage for an original constraint and variable.
18235 *
18236 * @note This method requires linear time to search for occurences of the variable in the constraint data.
18237 */
18239 SCIP* scip, /**< SCIP data structure */
18240 SCIP_CONS* cons, /**< constraint data */
18241 SCIP_VAR* var, /**< variable of constraint entry */
18242 SCIP_Real val /**< new coefficient of constraint entry */
18243 )
18244{
18245 SCIP_CONSDATA* consdata;
18246 SCIP_VAR** vars;
18247 SCIP_Bool found;
18248 int i;
18249
18250 assert(scip != NULL);
18251 assert(cons != NULL);
18252 assert(var != NULL);
18253
18254 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18255 {
18256 SCIPerrorMessage("constraint is not linear\n");
18257 return SCIP_INVALIDDATA;
18258 }
18259
18261 {
18262 SCIPerrorMessage("method may only be called during problem creation stage for original constraints and variables\n");
18263 return SCIP_INVALIDDATA;
18264 }
18265
18266 consdata = SCIPconsGetData(cons);
18267 assert(consdata != NULL);
18268
18269 vars = consdata->vars;
18270 found = FALSE;
18271 i = 0;
18272 while( i < consdata->nvars )
18273 {
18274 if( vars[i] == var )
18275 {
18276 if( found || SCIPisZero(scip, val) )
18277 {
18278 SCIP_CALL( delCoefPos(scip, cons, i) );
18279
18280 /* decrease i by one since otherwise we would skip the coefficient which has been switched to position i */
18281 i--;
18282 }
18283 else
18284 {
18285 SCIP_CALL( chgCoefPos(scip, cons, i, val) );
18286 }
18287 found = TRUE;
18288 }
18289 i++;
18290 }
18291
18292 if( !found )
18293 {
18294 SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
18295 }
18296
18297 return SCIP_OKAY;
18298}
18299
18300/** deletes variable from linear constraint
18301 *
18302 * @note This method may only be called during problem creation stage for an original constraint and variable.
18303 *
18304 * @note This method requires linear time to search for occurences of the variable in the constraint data.
18305 */
18307 SCIP* scip, /**< SCIP data structure */
18308 SCIP_CONS* cons, /**< constraint data */
18309 SCIP_VAR* var /**< variable of constraint entry */
18310 )
18311{
18312 assert(scip != NULL);
18313 assert(cons != NULL);
18314 assert(var != NULL);
18315
18316 SCIP_CALL( SCIPchgCoefLinear(scip, cons, var, 0.0) );
18317
18318 return SCIP_OKAY;
18319}
18320
18321/** gets left hand side of linear constraint */
18323 SCIP* scip, /**< SCIP data structure */
18324 SCIP_CONS* cons /**< constraint data */
18325 )
18326{
18327 SCIP_CONSDATA* consdata;
18328
18329 assert(scip != NULL);
18330 assert(cons != NULL);
18331
18332 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18333 {
18334 SCIPerrorMessage("constraint is not linear\n");
18335 SCIPABORT();
18336 return SCIP_INVALID; /*lint !e527*/
18337 }
18338
18339 consdata = SCIPconsGetData(cons);
18340 assert(consdata != NULL);
18341
18342 return consdata->lhs;
18343}
18344
18345/** gets right hand side of linear constraint */
18347 SCIP* scip, /**< SCIP data structure */
18348 SCIP_CONS* cons /**< constraint data */
18349 )
18350{
18351 SCIP_CONSDATA* consdata;
18352
18353 assert(scip != NULL);
18354 assert(cons != NULL);
18355
18356 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18357 {
18358 SCIPerrorMessage("constraint is not linear\n");
18359 SCIPABORT();
18360 return SCIP_INVALID; /*lint !e527*/
18361 }
18362
18363 consdata = SCIPconsGetData(cons);
18364 assert(consdata != NULL);
18365
18366 return consdata->rhs;
18367}
18368
18369/** changes left hand side of linear constraint */
18371 SCIP* scip, /**< SCIP data structure */
18372 SCIP_CONS* cons, /**< constraint data */
18373 SCIP_Real lhs /**< new left hand side */
18374 )
18375{
18376 assert(scip != NULL);
18377 assert(cons != NULL);
18378
18379 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18380 {
18381 SCIPerrorMessage("constraint is not linear\n");
18382 return SCIP_INVALIDDATA;
18383 }
18384
18385 SCIP_CALL( chgLhs(scip, cons, lhs) );
18386
18387 return SCIP_OKAY;
18388}
18389
18390/** changes right hand side of linear constraint */
18392 SCIP* scip, /**< SCIP data structure */
18393 SCIP_CONS* cons, /**< constraint data */
18394 SCIP_Real rhs /**< new right hand side */
18395 )
18396{
18397 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18398 {
18399 SCIPerrorMessage("constraint is not linear\n");
18400 return SCIP_INVALIDDATA;
18401 }
18402
18403 SCIP_CALL( chgRhs(scip, cons, rhs) );
18404
18405 return SCIP_OKAY;
18406}
18407
18408/** gets the number of variables in the linear constraint */
18410 SCIP* scip, /**< SCIP data structure */
18411 SCIP_CONS* cons /**< constraint data */
18412 )
18413{
18414 SCIP_CONSDATA* consdata;
18415
18416 assert(scip != NULL);
18417 assert(cons != NULL);
18418
18419 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18420 {
18421 SCIPerrorMessage("constraint is not linear\n");
18422 SCIPABORT();
18423 return -1; /*lint !e527*/
18424 }
18425
18426 consdata = SCIPconsGetData(cons);
18427 assert(consdata != NULL);
18428
18429 return consdata->nvars;
18430}
18431
18432/** gets the array of variables in the linear constraint; the user must not modify this array! */
18434 SCIP* scip, /**< SCIP data structure */
18435 SCIP_CONS* cons /**< constraint data */
18436 )
18437{
18438 SCIP_CONSDATA* consdata;
18439
18440 assert(scip != NULL);
18441 assert(cons != NULL);
18442
18443 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18444 {
18445 SCIPerrorMessage("constraint is not linear\n");
18446 SCIPABORT();
18447 return NULL; /*lint !e527*/
18448 }
18449
18450 consdata = SCIPconsGetData(cons);
18451 assert(consdata != NULL);
18452
18453 return consdata->vars;
18454}
18455
18456/** gets the array of coefficient values in the linear constraint; the user must not modify this array! */
18458 SCIP* scip, /**< SCIP data structure */
18459 SCIP_CONS* cons /**< constraint data */
18460 )
18461{
18462 SCIP_CONSDATA* consdata;
18463
18464 assert(scip != NULL);
18465 assert(cons != NULL);
18466
18467 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18468 {
18469 SCIPerrorMessage("constraint is not linear\n");
18470 SCIPABORT();
18471 return NULL; /*lint !e527*/
18472 }
18473
18474 consdata = SCIPconsGetData(cons);
18475 assert(consdata != NULL);
18476
18477 return consdata->vals;
18478}
18479
18480/** gets the activity of the linear constraint in the given solution
18481 *
18482 * @note if the solution contains values at infinity, this method will return SCIP_INVALID in case the activity
18483 * comprises positive and negative infinity contributions
18484 */
18486 SCIP* scip, /**< SCIP data structure */
18487 SCIP_CONS* cons, /**< constraint data */
18488 SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18489 )
18490{
18491 SCIP_CONSDATA* consdata;
18492
18493 assert(scip != NULL);
18494 assert(cons != NULL);
18495
18496 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18497 {
18498 SCIPerrorMessage("constraint is not linear\n");
18499 SCIPABORT();
18500 return SCIP_INVALID; /*lint !e527*/
18501 }
18502
18503 consdata = SCIPconsGetData(cons);
18504 assert(consdata != NULL);
18505
18506 if( consdata->row != NULL )
18507 return SCIPgetRowSolActivity(scip, consdata->row, sol);
18508 else
18509 return consdataGetActivity(scip, consdata, sol);
18510}
18511
18512/** gets the feasibility of the linear constraint in the given solution */
18514 SCIP* scip, /**< SCIP data structure */
18515 SCIP_CONS* cons, /**< constraint data */
18516 SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18517 )
18518{
18519 SCIP_CONSDATA* consdata;
18520
18521 assert(scip != NULL);
18522 assert(cons != NULL);
18523
18524 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18525 {
18526 SCIPerrorMessage("constraint is not linear\n");
18527 SCIPABORT();
18528 return SCIP_INVALID; /*lint !e527*/
18529 }
18530
18531 consdata = SCIPconsGetData(cons);
18532 assert(consdata != NULL);
18533
18534 if( consdata->row != NULL )
18535 return SCIPgetRowSolFeasibility(scip, consdata->row, sol);
18536 else
18537 return consdataGetFeasibility(scip, consdata, sol);
18538}
18539
18540/** gets the dual solution of the linear constraint in the current LP */
18542 SCIP* scip, /**< SCIP data structure */
18543 SCIP_CONS* cons /**< constraint data */
18544 )
18545{
18546 SCIP_CONSDATA* consdata;
18547
18548 assert(scip != NULL);
18549 assert(cons != NULL);
18550 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18551
18552 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18553 {
18554 SCIPerrorMessage("constraint is not linear\n");
18555 SCIPABORT();
18556 return SCIP_INVALID; /*lint !e527*/
18557 }
18558
18559 consdata = SCIPconsGetData(cons);
18560 assert(consdata != NULL);
18561
18562 if( consdata->row != NULL )
18563 return SCIProwGetDualsol(consdata->row);
18564 else
18565 return 0.0;
18566}
18567
18568/** gets the dual Farkas value of the linear constraint in the current infeasible LP */
18570 SCIP* scip, /**< SCIP data structure */
18571 SCIP_CONS* cons /**< constraint data */
18572 )
18573{
18574 SCIP_CONSDATA* consdata;
18575
18576 assert(scip != NULL);
18577 assert(cons != NULL);
18578 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18579
18580 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18581 {
18582 SCIPerrorMessage("constraint is not linear\n");
18583 SCIPABORT();
18584 return SCIP_INVALID; /*lint !e527*/
18585 }
18586
18587 consdata = SCIPconsGetData(cons);
18588 assert(consdata != NULL);
18589
18590 if( consdata->row != NULL )
18591 return SCIProwGetDualfarkas(consdata->row);
18592 else
18593 return 0.0;
18594}
18595
18596/** returns the linear relaxation of the given linear constraint; may return NULL if no LP row was yet created;
18597 * the user must not modify the row!
18598 */
18600 SCIP* scip, /**< SCIP data structure */
18601 SCIP_CONS* cons /**< constraint data */
18602 )
18603{
18604 SCIP_CONSDATA* consdata;
18605
18606 assert(scip != NULL);
18607 assert(cons != NULL);
18608
18609 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18610 {
18611 SCIPerrorMessage("constraint is not linear\n");
18612 SCIPABORT();
18613 return NULL; /*lint !e527*/
18614 }
18615
18616 consdata = SCIPconsGetData(cons);
18617 assert(consdata != NULL);
18618
18619 return consdata->row;
18620}
18621
18622/** creates and returns the row of the given linear constraint */
18624 SCIP* scip, /**< SCIP data structure */
18625 SCIP_CONS* cons /**< constraint data */
18626 )
18627{
18628 SCIP_CONSDATA* consdata;
18629
18630 assert(scip != NULL);
18631 assert(cons != NULL);
18632
18633 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18634 {
18635 SCIPerrorMessage("constraint is not linear\n");
18636 SCIPABORT();
18637 return SCIP_ERROR; /*lint !e527*/
18638 }
18639
18640 consdata = SCIPconsGetData(cons);
18641 assert(consdata != NULL);
18642
18643 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
18645
18646 SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) ) ;
18647
18648 return SCIP_OKAY;
18649}
18650
18651/** tries to automatically convert a linear constraint into a more specific and more specialized constraint */
18653 SCIP* scip, /**< SCIP data structure */
18654 SCIP_CONS* cons, /**< source constraint to try to convert */
18655 SCIP_CONS** upgdcons /**< pointer to store upgraded constraint, or NULL if not successful */
18656 )
18657{
18658 SCIP_CONSHDLR* conshdlr;
18659 SCIP_CONSHDLRDATA* conshdlrdata;
18660 SCIP_CONSDATA* consdata;
18661 SCIP_VAR* var;
18662 SCIP_Real val;
18663 SCIP_Real lb;
18664 SCIP_Real ub;
18665 SCIP_Real poscoeffsum;
18666 SCIP_Real negcoeffsum;
18667 SCIP_Bool infeasible;
18668 SCIP_Bool integral;
18669 int nchgsides = 0;
18670 int nposbin;
18671 int nnegbin;
18672 int nposint;
18673 int nnegint;
18674 int nposimpl;
18675 int nnegimpl;
18676 int nposimplbin;
18677 int nnegimplbin;
18678 int nposcont;
18679 int nnegcont;
18680 int ncoeffspone;
18681 int ncoeffsnone;
18682 int ncoeffspint;
18683 int ncoeffsnint;
18684 int ncoeffspfrac;
18685 int ncoeffsnfrac;
18686 int i;
18687
18688 assert(scip != NULL);
18689 assert(cons != NULL);
18690 assert(upgdcons != NULL);
18691
18692 *upgdcons = NULL;
18693
18694 /* we cannot upgrade a modifiable linear constraint, since we don't know what additional coefficients to expect */
18695 if( SCIPconsIsModifiable(cons) )
18696 return SCIP_OKAY;
18697
18698 /* check for upgradability */
18699 if( SCIPconsGetNUpgradeLocks(cons) > 0 )
18700 return SCIP_OKAY;
18701
18702 /* get the constraint handler and check, if it's really a linear constraint */
18703 conshdlr = SCIPconsGetHdlr(cons);
18704 if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
18705 {
18706 SCIPerrorMessage("constraint is not linear\n");
18707 return SCIP_INVALIDDATA;
18708 }
18709
18710 /* get constraint handler data and constraint data */
18711 conshdlrdata = SCIPconshdlrGetData(conshdlr);
18712 assert(conshdlrdata != NULL);
18713 consdata = SCIPconsGetData(cons);
18714 assert(consdata != NULL);
18715
18716 /* check, if the constraint was already upgraded and will be deleted anyway after preprocessing */
18717 if( consdata->upgraded )
18718 return SCIP_OKAY;
18719
18720 /* check, if the constraint is already stored as LP row */
18721 if( consdata->row != NULL )
18722 {
18723 if( SCIProwIsInLP(consdata->row) )
18724 {
18725 SCIPerrorMessage("cannot upgrade linear constraint that is already stored as row in the LP\n");
18726 return SCIP_INVALIDDATA;
18727 }
18728 else
18729 {
18730 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
18731 }
18732 }
18733
18734 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
18735
18736 /* normalizeCons() can only detect infeasibility when scaling with the gcd. in that case, the scaling was
18737 * skipped and we hope that the infeasibility gets detected later again.
18738 *
18739 * TODO: do we want to try to upgrade the constraint anyway?
18740 *
18741 * TODO: this needs to be fixed on master by changing the API and passing a pointer to whether the constraint is
18742 * proven to be infeasible.
18743 */
18744 if( infeasible ) /*lint !e774*/
18745 return SCIP_OKAY;
18746
18747 /* tighten sides */
18748 SCIP_CALL( tightenSides(scip, cons, &nchgsides, &infeasible) );
18749
18750 if( infeasible ) /*lint !e774*/
18751 return SCIP_OKAY;
18752
18753 /*
18754 * calculate some statistics on linear constraint
18755 */
18756
18757 nposbin = 0;
18758 nnegbin = 0;
18759 nposint = 0;
18760 nnegint = 0;
18761 nposimpl = 0;
18762 nnegimpl = 0;
18763 nposimplbin = 0;
18764 nnegimplbin = 0;
18765 nposcont = 0;
18766 nnegcont = 0;
18767 ncoeffspone = 0;
18768 ncoeffsnone = 0;
18769 ncoeffspint = 0;
18770 ncoeffsnint = 0;
18771 ncoeffspfrac = 0;
18772 ncoeffsnfrac = 0;
18773 integral = TRUE;
18774 poscoeffsum = 0.0;
18775 negcoeffsum = 0.0;
18776
18777 for( i = 0; i < consdata->nvars; ++i )
18778 {
18779 var = consdata->vars[i];
18780 val = consdata->vals[i];
18781 lb = SCIPvarGetLbLocal(var);
18782 ub = SCIPvarGetUbLocal(var);
18783 assert(!SCIPisZero(scip, val));
18784
18786 {
18787 if( SCIPvarIsBinary(var) )
18788 {
18789 if( val >= 0.0 )
18790 ++nposimplbin;
18791 else
18792 ++nnegimplbin;
18793 }
18794 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18795 integral = integral && SCIPisIntegral(scip, val);
18796 if( val >= 0.0 )
18797 ++nposimpl;
18798 else
18799 ++nnegimpl;
18800 }
18801 else
18802 {
18803 switch( SCIPvarGetType(var) )
18804 {
18806 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18807 integral = integral && SCIPisIntegral(scip, val);
18808 if( val >= 0.0 )
18809 ++nposbin;
18810 else
18811 ++nnegbin;
18812 break;
18814 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18815 integral = integral && SCIPisIntegral(scip, val);
18816 if( val >= 0.0 )
18817 ++nposint;
18818 else
18819 ++nnegint;
18820 break;
18822 integral = integral && SCIPisEQ(scip, lb, ub) && SCIPisIntegral(scip, val * lb);
18823 if( val >= 0.0 )
18824 ++nposcont;
18825 else
18826 ++nnegcont;
18827 break;
18828 default:
18829 SCIPerrorMessage("unknown variable type\n");
18830 return SCIP_INVALIDDATA;
18831 } /*lint !e788*/
18832 }
18833
18834 if( SCIPisEQ(scip, val, 1.0) )
18835 ncoeffspone++;
18836 else if( SCIPisEQ(scip, val, -1.0) )
18837 ncoeffsnone++;
18838 else if( SCIPisIntegral(scip, val) )
18839 {
18840 if( SCIPisPositive(scip, val) )
18841 ncoeffspint++;
18842 else
18843 ncoeffsnint++;
18844 }
18845 else
18846 {
18847 if( SCIPisPositive(scip, val) )
18848 ncoeffspfrac++;
18849 else
18850 ncoeffsnfrac++;
18851 }
18852 if( SCIPisPositive(scip, val) )
18853 poscoeffsum += val;
18854 else
18855 negcoeffsum += val;
18856 }
18857
18858 /*
18859 * call the upgrading methods
18860 */
18861
18862 SCIPdebugMsg(scip, "upgrading linear constraint <%s> (%d upgrade methods):\n",
18863 SCIPconsGetName(cons), conshdlrdata->nlinconsupgrades);
18864 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",
18865 nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposcont, nnegcont,
18866 ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18867 poscoeffsum, negcoeffsum, integral);
18868
18869 /* try all upgrading methods in priority order in case the upgrading step is enable */
18870 for( i = 0; i < conshdlrdata->nlinconsupgrades && *upgdcons == NULL; ++i )
18871 {
18872 if( conshdlrdata->linconsupgrades[i]->active )
18873 {
18874 SCIP_CALL( conshdlrdata->linconsupgrades[i]->linconsupgd(scip, cons, consdata->nvars,
18875 consdata->vars, consdata->vals, consdata->lhs, consdata->rhs,
18876 nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposimplbin, nnegimplbin, nposcont, nnegcont,
18877 ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18878 poscoeffsum, negcoeffsum, integral,
18879 upgdcons) );
18880 }
18881 }
18882
18883#ifdef SCIP_DEBUG
18884 if( *upgdcons != NULL )
18885 {
18887 SCIPdebugMsg(scip, " -> upgraded to constraint type <%s>\n", SCIPconshdlrGetName(SCIPconsGetHdlr(*upgdcons)));
18888 SCIPdebugPrintCons(scip, *upgdcons, NULL);
18889 }
18890#endif
18891
18892 return SCIP_OKAY; /*lint !e438*/
18893}
18894
18895/** cleans up (multi-)aggregations and fixings from linear constraints */
18897 SCIP* scip, /**< SCIP data structure */
18898 SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
18899 SCIP_Bool* infeasible, /**< pointer to return whether the problem was detected to be infeasible */
18900 int* ndelconss /**< pointer to count number of deleted constraints */
18901 )
18902{
18903 SCIP_CONSHDLR* conshdlr;
18904 SCIP_CONS** conss;
18905 int nconss;
18906 int i;
18907
18908 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
18909 if( conshdlr == NULL )
18910 return SCIP_OKAY;
18911
18912 assert(infeasible != NULL);
18913 *infeasible = FALSE;
18914
18915 nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr);
18916 conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);
18917
18918 /* loop backwards since then deleted constraints do not interfere with the loop */
18919 for( i = nconss - 1; i >= 0; --i )
18920 {
18921 SCIP_CALL( applyFixings(scip, conss[i], infeasible) );
18922
18923 if( *infeasible )
18924 break;
18925
18926 if( SCIPconsGetData(conss[i])->nvars >= 1 )
18927 continue;
18928
18929 SCIP_CALL( SCIPdelCons(scip, conss[i]) );
18930 ++(*ndelconss);
18931 }
18932
18933 return SCIP_OKAY;
18934}
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:173
#define DEFAULT_DUALPRESOLVING
Definition cons_and.c:110
#define CONSHDLR_NEEDSCONS
Definition cons_and.c:97
#define CONSHDLR_SEPAFREQ
Definition cons_and.c:90
#define CONSHDLR_CHECKPRIORITY
Definition cons_and.c:89
#define CONSHDLR_DESC
Definition cons_and.c:86
#define CONSHDLR_PROP_TIMING
Definition cons_and.c:100
#define CONSHDLR_MAXPREROUNDS
Definition cons_and.c:94
#define DEFAULT_PRESOLPAIRWISE
Definition cons_and.c:105
#define CONSHDLR_SEPAPRIORITY
Definition cons_and.c:87
Proprule
Definition cons_and.c:166
@ PROPRULE_INVALID
Definition cons_and.c:167
#define DEFAULT_PRESOLUSEHASHING
Definition cons_and.c:113
#define CONSHDLR_PROPFREQ
Definition cons_and.c:91
#define CONSHDLR_PRESOLTIMING
Definition cons_and.c:99
#define CONSHDLR_EAGERFREQ
Definition cons_and.c:92
#define CONSHDLR_ENFOPRIORITY
Definition cons_and.c:88
#define CONSHDLR_DELAYSEPA
Definition cons_and.c:95
#define CONSHDLR_NAME
Definition cons_and.c:85
#define CONSHDLR_DELAYPROP
Definition cons_and.c:96
#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 propagateCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool tightenbounds, SCIP_Bool rangedrowpropagation, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, SCIP_Bool *cutoff, int *nchgbds)
static SCIP_RETCODE updateCutoffbound(SCIP *scip, SCIP_CONS *cons, SCIP_Real primalbound)
static void consdataUpdateDelCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
#define DEFAULT_RANGEDROWARTCONS
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, int pos)
#define MAXSCALEDCOEFINTEGER
static void consdataUpdateAddCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
static void getMinActivity(SCIP *scip, SCIP_CONSDATA *consdata, int posinf, int neginf, int poshuge, int neghuge, SCIP_Real delta, SCIP_Bool global, SCIP_Bool goodrelax, SCIP_Real *minactivity, SCIP_Bool *istight, SCIP_Bool *issettoinfinity)
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
#define BINWEIGHT
static SCIP_RETCODE chgRhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
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)
#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:312
#define SCIPdebugAddSolVal(scip, var, val)
Definition debug.h:311
#define NULL
Definition def.h:255
#define SCIP_MAXSTRLEN
Definition def.h:276
#define COPYSIGN
Definition def.h:246
#define SCIP_Longint
Definition def.h:148
#define SCIP_MAXTREEDEPTH
Definition def.h:304
#define SCIP_REAL_MAX
Definition def.h:165
#define SCIP_INVALID
Definition def.h:185
#define SCIP_Bool
Definition def.h:98
#define MIN(x, y)
Definition def.h:231
#define MAX3(x, y, z)
Definition def.h:235
#define SCIP_Real
Definition def.h:163
#define ABS(x)
Definition def.h:223
#define TRUE
Definition def.h:100
#define FALSE
Definition def.h:101
#define MAX(x, y)
Definition def.h:227
#define SCIP_CALL_ABORT(x)
Definition def.h:341
#define SCIP_LONGINT_FORMAT
Definition def.h:155
#define MIN3(x, y, z)
Definition def.h:239
#define SCIPABORT()
Definition def.h:334
#define REALABS(x)
Definition def.h:189
#define EPSGT(x, y, eps)
Definition def.h:193
#define SCIP_CALL(x)
Definition def.h:362
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:2051
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
SCIP_RETCODE SCIPgetIntParam(SCIP *scip, const char *name, int *value)
Definition scip_param.c:269
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:4798
void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
Definition cons.c:4346
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:4755
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:5282
SCIP_RETCODE SCIPsetConshdlrGetSignedPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:924
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4778
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4316
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:4336
int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4812
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:4735
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:8419
int SCIPconsGetPos(SCIP_CONS *cons)
Definition cons.c:8399
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition cons.c:8648
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition cons.c:8409
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition cons.c:8558
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition scip_cons.c:2536
int SCIPconsGetNUpgradeLocks(SCIP_CONS *cons)
Definition cons.c:8841
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:8598
SCIP_Bool SCIPconsIsOriginal(SCIP_CONS *cons)
Definition cons.c:8688
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition cons.c:8588
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition cons.c:8518
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition cons.c:8698
int SCIPconsGetNLocksPos(SCIP_CONS *cons)
Definition cons.c:8738
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:8782
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition cons.c:8578
SCIP_RETCODE SCIPunmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition scip_cons.c:2042
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition cons.c:8450
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:8608
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition cons.c:8628
int SCIPconsGetNLocksNeg(SCIP_CONS *cons)
Definition cons.c:8748
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition cons.c:8389
SCIP_Bool SCIPconsIsLocked(SCIP_CONS *cons)
Definition cons.c:8728
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:8638
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:8668
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:8568
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition scip_cons.c:1784
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition cons.c:8658
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:424
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:8283
void SCIPlinConsStatsReset(SCIP_LINCONSSTATS *linconsstats)
Definition cons.c:8251
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:1765
void SCIPupdateSolLPConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
Definition scip_sol.c:469
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:23514
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:18320
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition var.c:23534
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:23843
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition var.c:23868
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition var.c:23642
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition var.c:23478
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:23386
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4386
SCIP_Bool SCIPdoNotAggr(SCIP *scip)
Definition scip_var.c:10909
SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
Definition var.c:23498
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24268
SCIP_Bool SCIPdoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:10942
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition var.c:23430
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:23506
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition var.c:23900
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:23453
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:24142
int SCIPvarGetIndex(SCIP_VAR *var)
Definition var.c:23652
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:23662
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:23267
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:24929
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:24312
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:23490
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:23806
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition var.c:23794
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:23524
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24234
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition var.c:23443
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition var.c:23600
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition var.c:23417
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition var.c:24120
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:23463
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition var.c:17274
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:24919
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4328
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:23818
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:955
#define SCIP_DECL_CONSGETPERMSYMGRAPH(x)
Definition type_cons.h:937
#define SCIP_DECL_CONSENFOLP(x)
Definition type_cons.h:363
#define SCIP_DECL_CONSDELETE(x)
Definition type_cons.h:229
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:866
#define SCIP_DECL_CONSINITSOL(x)
Definition type_cons.h:201
#define SCIP_DECL_CONSPRINT(x)
Definition type_cons.h:768
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition type_cons.h:64
#define SCIP_DECL_CONSSEPALP(x)
Definition type_cons.h:288
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:505
#define SCIP_DECL_CONSGETNVARS(x)
Definition type_cons.h:884
#define SCIP_DECL_CONSRESPROP(x)
Definition type_cons.h:611
@ SCIP_LINCONSTYPE_BINPACKING
Definition type_cons.h:85
@ SCIP_LINCONSTYPE_VARBOUND
Definition type_cons.h:78
@ SCIP_LINCONSTYPE_EMPTY
Definition type_cons.h:73
@ SCIP_LINCONSTYPE_INVKNAPSACK
Definition type_cons.h:83
@ SCIP_LINCONSTYPE_PRECEDENCE
Definition type_cons.h:77
@ SCIP_LINCONSTYPE_AGGREGATION
Definition type_cons.h:76
@ SCIP_LINCONSTYPE_MIXEDBINARY
Definition type_cons.h:88
@ SCIP_LINCONSTYPE_SINGLETON
Definition type_cons.h:75
@ SCIP_LINCONSTYPE_SETCOVERING
Definition type_cons.h:81
@ SCIP_LINCONSTYPE_EQKNAPSACK
Definition type_cons.h:84
@ SCIP_LINCONSTYPE_FREE
Definition type_cons.h:74
@ SCIP_LINCONSTYPE_KNAPSACK
Definition type_cons.h:86
@ SCIP_LINCONSTYPE_SETPARTITION
Definition type_cons.h:79
@ SCIP_LINCONSTYPE_INTKNAPSACK
Definition type_cons.h:87
@ SCIP_LINCONSTYPE_SETPACKING
Definition type_cons.h:80
@ SCIP_LINCONSTYPE_GENERAL
Definition type_cons.h:89
@ SCIP_LINCONSTYPE_CARDINALITY
Definition type_cons.h:82
#define SCIP_DECL_CONSACTIVE(x)
Definition type_cons.h:690
#define SCIP_DECL_CONSENFOPS(x)
Definition type_cons.h:431
#define SCIP_DECL_CONSPARSE(x)
Definition type_cons.h:844
#define SCIP_DECL_CONSTRANS(x)
Definition type_cons.h:239
#define SCIP_DECL_CONSDEACTIVE(x)
Definition type_cons.h:705
#define SCIP_DECL_CONSPRESOL(x)
Definition type_cons.h:560
#define SCIP_DECL_CONSINITLP(x)
Definition type_cons.h:259
#define SCIP_DECL_CONSEXITPRE(x)
Definition type_cons.h:180
#define SCIP_DECL_CONSLOCK(x)
Definition type_cons.h:675
struct SCIP_Conshdlr SCIP_CONSHDLR
Definition type_cons.h:62
#define SCIP_DECL_CONSCOPY(x)
Definition type_cons.h:809
#define SCIP_DECL_CONSINIT(x)
Definition type_cons.h:126
struct SCIP_ConsData SCIP_CONSDATA
Definition type_cons.h:65
#define SCIP_DECL_CONSCHECK(x)
Definition type_cons.h:474
#define SCIP_DECL_CONSHDLRCOPY(x)
Definition type_cons.h:108
#define SCIP_DECL_CONSEXITSOL(x)
Definition type_cons.h:216
#define SCIP_DECL_CONSFREE(x)
Definition type_cons.h:116
#define SCIP_DECL_CONSSEPASOL(x)
Definition type_cons.h:320
#define SCIP_DECL_CONSDELVARS(x)
Definition type_cons.h:752
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_ERROR
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
@ SCIP_STAGE_PROBLEM
Definition type_set.h:45
@ SCIP_STAGE_INITSOLVE
Definition type_set.h:52
@ SCIP_STAGE_EXITPRESOLVE
Definition type_set.h:50
@ SCIP_STAGE_SOLVING
Definition type_set.h:53
@ SCIP_STAGE_TRANSFORMING
Definition type_set.h:46
@ SCIP_STAGE_PRESOLVED
Definition type_set.h:51
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