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
5800 fixedact = 0;
5801 nfixedconsvars = 0;
5802
5803 /* calculate fixed activity and number of fixed variables */
5804 for( v = consdata->nvars - 1; v >= 0; --v )
5805 {
5806 /* all zero coefficients should be eliminated */
5807 assert(!SCIPisZero(scip, consdata->vals[v]));
5808
5809 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5810 {
5811 fixedact += SCIPvarGetLbLocal(consdata->vars[v]) * consdata->vals[v];
5812 ++nfixedconsvars;
5813 }
5814 }
5815
5816 /* do not work with huge fixed activities */
5817 if( SCIPisHugeValue(scip, REALABS(fixedact)) )
5818 return SCIP_OKAY;
5819
5820 /* compute lhs and rhs for unfixed variables only and get number of unfixed variables */
5821 assert(!SCIPisInfinity(scip, -fixedact) && !SCIPisInfinity(scip, fixedact));
5822 lhs = consdata->lhs - fixedact;
5823 rhs = consdata->rhs - fixedact;
5824 nunfixedvars = consdata->nvars - nfixedconsvars;
5825
5826 /* allocate temporary memory for variables and coefficients which may lead to infeasibility */
5827 SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvars, nunfixedvars) );
5828 SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvals, nunfixedvars) );
5829
5830 absminbincoef = SCIP_REAL_MAX;
5831 ncontvars = 0;
5832 gcdisone = TRUE;
5833 possiblegcd = TRUE;
5834
5835 /* we now partition all unfixed variables in two groups:
5836 *
5837 * The first one contains all integral variables with integral coefficient so that all variables in this group will
5838 * have a gcd greater than 1. This group will be implicitly given.
5839 *
5840 * The second group will contain all left unfixed variables and will be saved as infcheckvars with corresponding
5841 * coefficients as infcheckvals. The order of these variables should be the same as in the consdata object.
5842 */
5843
5844 /* first find integral variables with integral coefficient greater than 1, thereby collecting all other unfixed
5845 * variables
5846 */
5847 ninfcheckvars = 0;
5848 v = -1;
5849 pos = -1;
5850 do
5851 {
5852 ++v;
5853
5854 /* partition the variables, do not change the order of collection, because it might be used later on */
5855 while( v < consdata->nvars && ( !SCIPvarIsIntegral(consdata->vars[v])
5856 || !SCIPisIntegral(scip, consdata->vals[v]) || SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0) ) )
5857 {
5858 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5859 {
5860 if( !SCIPvarIsIntegral(consdata->vars[v]) )
5861 ++ncontvars;
5862 else if( SCIPvarIsBinary(consdata->vars[v]) )
5863 {
5864 SCIP_Real absval;
5865
5866 absval = REALABS(consdata->vals[v]);
5867
5868 if( absminbincoef > absval )
5869 absminbincoef = absval;
5870 }
5871
5872 gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5873 possiblegcd = FALSE;
5874 infcheckvars[ninfcheckvars] = consdata->vars[v];
5875 infcheckvals[ninfcheckvars] = consdata->vals[v];
5876 ++ninfcheckvars;
5877
5878 if( pos == -1 )
5879 pos = v;
5880 }
5881 ++v;
5882 }
5883 }
5884 while( v < consdata->nvars && SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) );
5885
5886 /* if the first group of variables is empty, we stop */
5887 /* @todo try to propagate/split up a constraint of the form:
5888 * x_1 + ... + x_m + a_1*y_1 + ... + a_n*y_n = k + c,
5889 * 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]
5890 */
5891 if( v == consdata->nvars )
5892 goto TERMINATE;
5893
5894 /* we need at least two non-continuous variables */
5895 if( ncontvars + 2 > nunfixedvars )
5896 goto TERMINATE;
5897
5898 assert(!SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])));
5899 assert(SCIPvarIsIntegral(consdata->vars[v]) && SCIPisIntegral(scip, consdata->vals[v]) && REALABS(consdata->vals[v]) > 1.5);
5900
5901 feastol = SCIPfeastol(scip);
5902
5903 gcd = (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol);
5904 assert(gcd >= 2);
5905
5906 /* go on to partition the variables, do not change the order of collection, because it might be used later on;
5907 * calculate gcd over the first part of variables */
5908 for( ; v < consdata->nvars; ++v )
5909 {
5910 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5911 continue;
5912
5913 if( SCIPvarIsBinary(consdata->vars[v]) )
5914 {
5915 SCIP_Real absval;
5916
5917 absval = REALABS(consdata->vals[v]);
5918
5919 if( absminbincoef > absval )
5920 absminbincoef = absval;
5921 }
5922
5923 if( !SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v])
5924 || SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0) )
5925 {
5926 if( !SCIPvarIsIntegral(consdata->vars[v]) )
5927 ++ncontvars;
5928
5929 gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5930 possiblegcd = FALSE;
5931 infcheckvars[ninfcheckvars] = consdata->vars[v];
5932 infcheckvals[ninfcheckvars] = consdata->vals[v];
5933
5934 ++ninfcheckvars;
5935
5936 if( pos == -1 )
5937 pos = v;
5938 }
5939 else
5940 {
5941 assert(REALABS(consdata->vals[v]) > 1.5);
5942
5943 gcdtmp = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol));
5944 assert(gcdtmp >= 1);
5945
5946 if( gcdtmp == 1 )
5947 {
5948 infcheckvars[ninfcheckvars] = consdata->vars[v];
5949 infcheckvals[ninfcheckvars] = consdata->vals[v];
5950
5951 ++ninfcheckvars;
5952
5953 if( pos == -1 )
5954 pos = v;
5955 }
5956 else
5957 gcd = gcdtmp;
5958 }
5959 }
5960 assert(gcd >= 2);
5961
5962 /* it should not happen that all variables are of integral type and have a gcd >= 2, this should be done by
5963 * normalizeCons() */
5964 if( ninfcheckvars == 0 )
5965 goto TERMINATE;
5966
5967 assert(pos >= 0);
5968
5969 minactinfvarsinvalid = FALSE;
5970 maxactinfvarsinvalid = FALSE;
5971 maxactinfvars = 0.0;
5972 minactinfvars = 0.0;
5973
5974 /* calculate activities over all infcheckvars */
5975 for( v = ninfcheckvars - 1; v >= 0; --v )
5976 {
5977 lb = SCIPvarGetLbLocal(infcheckvars[v]);
5978 ub = SCIPvarGetUbLocal(infcheckvars[v]);
5979
5980 if( SCIPisInfinity(scip, -lb) )
5981 {
5982 if( infcheckvals[v] < 0.0 )
5983 maxactinfvarsinvalid = TRUE;
5984 else
5985 minactinfvarsinvalid = TRUE;
5986 }
5987 else
5988 {
5989 if( infcheckvals[v] < 0.0 )
5990 maxactinfvars += infcheckvals[v] * lb;
5991 else
5992 minactinfvars += infcheckvals[v] * lb;
5993 }
5994
5995 if( SCIPisInfinity(scip, ub) )
5996 {
5997 if( infcheckvals[v] > 0.0 )
5998 maxactinfvarsinvalid = TRUE;
5999 else
6000 minactinfvarsinvalid = TRUE;
6001 }
6002 else
6003 {
6004 if( infcheckvals[v] > 0.0 )
6005 maxactinfvars += infcheckvals[v] * ub;
6006 else
6007 minactinfvars += infcheckvals[v] * ub;
6008 }
6009
6010 /* better abort on to big values */
6011 if( SCIPisHugeValue(scip, -minactinfvars) )
6012 minactinfvarsinvalid = TRUE;
6013 if( SCIPisHugeValue(scip, maxactinfvars) )
6014 maxactinfvarsinvalid = TRUE;
6015
6016 if( minactinfvarsinvalid || maxactinfvarsinvalid )
6017 goto TERMINATE;
6018 }
6019 assert(!minactinfvarsinvalid && !maxactinfvarsinvalid);
6020
6021 SCIPdebugMsg(scip, "minactinfvarsinvalid = %u, minactinfvars = %g, maxactinfvarsinvalid = %u, maxactinfvars = %g, gcd = %lld, ninfcheckvars = %d, ncontvars = %d\n",
6022 minactinfvarsinvalid, minactinfvars, maxactinfvarsinvalid, maxactinfvars, gcd, ninfcheckvars, ncontvars);
6023
6024 /* @todo maybe we took the wrong variables as infcheckvars - we could try to exchange integer variables */
6025 /* @todo if minactinfvarsinvalid or maxactinfvarsinvalid are true, try to exchange both partitions to maybe get valid
6026 * activities */
6027 /* @todo calculate minactivity and maxactivity for all non-intcheckvars, and use this for better bounding,
6028 * !!!note!!!
6029 * that therefore the conflict variables in addConflictFixedVars() need to be extended by all variables which
6030 * are not at their global bound
6031 */
6032
6033 /* check if between left hand side and right hand side there exists a feasible point, if not, the constraint leads to
6034 * infeasibility */
6035 if( !SCIPisIntegral(scip, (lhs - maxactinfvars) / gcd) &&
6036 SCIPisGT(scip, SCIPceil(scip, (lhs - maxactinfvars) / gcd) * gcd, rhs - minactinfvars) )
6037 {
6038 SCIPdebugMsg(scip, "no feasible value exists, constraint <%s> leads to infeasibility", SCIPconsGetName(cons));
6040
6041 /* start conflict analysis */
6042 /* @todo improve conflict analysis by adding relaxed bounds */
6043 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6044
6045 *cutoff = TRUE;
6046 }
6047 else if( ncontvars == 0 )
6048 {
6049 SCIP_Longint gcdinfvars = -1;
6050
6051 /* check for gcd over all infcheckvars */
6052 if( possiblegcd )
6053 {
6054 v = ninfcheckvars - 1;
6055 gcdinfvars = (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol);
6056 assert(gcdinfvars >= 2);
6057
6058 for( ; v >= 0 && gcdinfvars >= 2; --v )
6059 {
6060 gcdinfvars = SCIPcalcGreComDiv(gcdinfvars, (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol));
6061 }
6062 }
6063 else if( gcdisone )
6064 gcdinfvars = 1;
6065
6066 SCIPdebugMsg(scip, "gcdinfvars =%lld, possiblegcd = %u\n", gcdinfvars, possiblegcd);
6067
6068 /* compute solutions for this ranged row, if all variables are of integral type with integral coefficients */
6069 if( gcdinfvars >= 1 )
6070 {
6071 SCIP_Real value;
6072 SCIP_Real value2;
6073 SCIP_Real minvalue = SCIP_INVALID;
6074 SCIP_Real maxvalue = SCIP_INVALID;
6075 int nsols = 0;
6076
6077 value = SCIPceil(scip, minactinfvars - SCIPfeastol(scip));
6078
6079 /* check how many possible solutions exist */
6080 while( SCIPisLE(scip, value, maxactinfvars) )
6081 {
6082 value2 = value + gcd * (SCIPceil(scip, (lhs - value) / gcd));
6083
6084 /* value2 might violate lhs due to numerics, in this case take the next divisible number */
6085 if( !SCIPisGE(scip, value2, lhs) )
6086 {
6087 value2 += gcd;
6088 }
6089
6090 if( SCIPisLE(scip, value2, rhs) )
6091 {
6092 ++nsols;
6093
6094 /* early termination if we found more than two solutions */
6095 if( nsols == 3 )
6096 break;
6097
6098 if( minvalue == SCIP_INVALID ) /*lint !e777*/
6099 minvalue = value;
6100
6101 maxvalue = value;
6102 }
6103 value += gcdinfvars;
6104 }
6105 assert(nsols < 2 || minvalue <= maxvalue);
6106
6107 /* determine last possible solution for better bounding */
6108 if( nsols == 3 )
6109 {
6110#ifndef NDEBUG
6111 SCIP_Real secondsolval = maxvalue;
6112#endif
6113 value = SCIPfloor(scip, maxactinfvars + SCIPfeastol(scip));
6114
6115 /* check how many possible solutions exist */
6116 while( SCIPisGE(scip, value, minactinfvars) )
6117 {
6118 value2 = value + gcd * (SCIPfloor(scip, (rhs - value) / gcd));
6119
6120 /* value2 might violate rhs due to numerics, in this case take the next divisible number */
6121 if( !SCIPisLE(scip, value2, rhs) )
6122 {
6123 value2 -= gcd;
6124 }
6125
6126 if( SCIPisGE(scip, value2, lhs) )
6127 {
6128 maxvalue = value;
6129 assert(maxvalue > minvalue);
6130 break;
6131 }
6132 value -= gcdinfvars;
6133 }
6134 assert(maxvalue > secondsolval);
6135 }
6136
6137 SCIPdebugMsg(scip, "here nsols %s %d, minsolvalue = %g, maxsolvalue = %g, ninfcheckvars = %d, nunfixedvars = %d\n",
6138 nsols > 2 ? ">=" : "=", nsols, minvalue, maxvalue, ninfcheckvars, nunfixedvars);
6139
6140 /* no possible solution found */
6141 if( nsols == 0 )
6142 {
6143 SCIPdebugMsg(scip, "gcdinfvars = %lld, gcd = %lld, correctedlhs = %g, correctedrhs = %g\n",
6144 gcdinfvars, gcd, lhs, rhs);
6145 SCIPdebugMsg(scip, "no solution found; constraint <%s> leads to infeasibility\n", SCIPconsGetName(cons));
6147
6148 /* start conflict analysis */
6149 /* @todo improve conflict analysis by adding relaxed bounds */
6150 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6151
6152 *cutoff = TRUE;
6153 }
6154 /* if only one solution exists, we can extract a new constraint or fix variables */
6155 else if( nsols == 1 )
6156 {
6157 assert(minvalue == maxvalue); /*lint !e777*/
6158
6159 /* we can fix the only variable in our second set of variables */
6160 if( ninfcheckvars == 1 )
6161 {
6162 SCIP_Bool fixed;
6163
6164 assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6165
6166 SCIPdebugMsg(scip, "fixing single variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6167 SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]),
6168 SCIPvarGetUbLocal(infcheckvars[0]), maxvalue/infcheckvals[0]);
6169
6170 /* fix variable to only possible value */
6171 SCIP_CALL( SCIPinferVarFixCons(scip, infcheckvars[0], maxvalue/infcheckvals[0], cons,
6172 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &fixed) );
6173
6174 if( *cutoff )
6175 {
6176 /* start conflict analysis */
6177 /* @todo improve conflict analysis by adding relaxed bounds */
6178 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6179 }
6180
6181 if( fixed )
6182 ++(*nfixedvars);
6183 }
6184 else
6185 {
6186 /* check for exactly one unfixed variable which is not part of the infcheckvars */
6187 if( ninfcheckvars == nunfixedvars - 1 )
6188 {
6190 SCIP_Bool foundvar = FALSE;
6191 SCIP_Bool fixed;
6192 int w = 0;
6193
6194 assert(ninfcheckvars > 0);
6195
6196 /* find variable which is not an infcheckvar and fix it */
6197 for( v = 0; v < consdata->nvars - 1; ++v )
6198 {
6199 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6200 {
6201 if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6202 {
6203#ifndef NDEBUG
6204 int v2 = v + 1;
6205 int w2 = w;
6206
6207 assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6208
6209 for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6210 {
6211 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6212 continue;
6213
6214 assert(consdata->vars[v2] == infcheckvars[w2]);
6215 ++w2;
6216 }
6217 assert(w2 == ninfcheckvars);
6218#endif
6219 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6220
6221 foundvar = TRUE;
6222
6223 if( consdata->vals[v] < 0 )
6224 {
6225 bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6226 }
6227 else
6228 {
6229 bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6230 }
6231
6232 SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6233 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6234 SCIPvarGetUbLocal(consdata->vars[v]), bound);
6235
6236 /* fix variable to only possible value */
6237 SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6239
6240 if( *cutoff )
6241 {
6242 /* start conflict analysis */
6243 /* @todo improve conflict analysis by adding relaxed bounds */
6244 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6245 consdata->vars[v], bound) );
6246 }
6247
6248 if( fixed )
6249 ++(*nfixedvars);
6250
6251 break;
6252 }
6253
6254 ++w;
6255 }
6256 }
6257
6258 /* maybe last variable was the not infcheckvar */
6259 if( !foundvar )
6260 {
6261 assert(v == consdata->nvars - 1);
6262 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6263
6264 if( consdata->vals[v] < 0 )
6265 {
6266 bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6267 }
6268 else
6269 {
6270 bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6271 }
6272
6273 SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6274 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6275 SCIPvarGetUbLocal(consdata->vars[v]), bound);
6276
6277 /* fix variable to only possible value */
6278 SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6280
6281 if( *cutoff )
6282 {
6283 /* start conflict analysis */
6284 /* @todo improve conflict analysis by adding relaxed bounds */
6285 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6286 consdata->vars[v], bound) );
6287 }
6288
6289 if( fixed )
6290 ++(*nfixedvars);
6291 }
6292 }
6293 else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6294 {
6295 /* aggregation possible if we have two variables, but this will be done later on */
6296 SCIP_CONS* newcons;
6297 char name[SCIP_MAXSTRLEN];
6298
6299 /* create, add, and release new artificial constraint */
6300 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6301 ++conshdlrdata->naddconss;
6302
6303 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6304
6305 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals,
6306 maxvalue, maxvalue, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6307 SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6308
6309 SCIPdebugPrintCons(scip, newcons, NULL);
6310
6311 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6312
6313 ++(*naddconss);
6314 }
6315 }
6316 }
6317 /* at least two solutions */
6318 else
6319 {
6320 /* @todo If we found more than one solution, can we reduce domains due to dualpresolving? */
6321
6322 /* only one variable in the second set, so we can bound this variables */
6323 if( ninfcheckvars == 1 )
6324 {
6325 SCIP_Bool tightened;
6326 SCIP_Real newlb;
6327 SCIP_Real newub;
6328
6329 assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6330
6331 if( infcheckvals[0] < 0 )
6332 {
6333 newlb = maxvalue/infcheckvals[0];
6334 newub = minvalue/infcheckvals[0];
6335 }
6336 else
6337 {
6338 newlb = minvalue/infcheckvals[0];
6339 newub = maxvalue/infcheckvals[0];
6340 }
6341 assert(newlb < newub);
6342
6343 if( newlb > SCIPvarGetLbLocal(infcheckvars[0]) )
6344 {
6345 /* update lower bound of variable */
6346 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6347 SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]), newlb);
6348
6349 /* tighten variable lower bound to minimal possible value */
6350 SCIP_CALL( SCIPinferVarLbCons(scip, infcheckvars[0], newlb, cons,
6351 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6352
6353 if( *cutoff )
6354 {
6355 /* start conflict analysis */
6356 /* @todo improve conflict analysis by adding relaxed bounds */
6357 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6358 }
6359
6360 if( tightened )
6361 ++(*nchgbds);
6362 }
6363
6364 if( newub < SCIPvarGetUbLocal(infcheckvars[0]) )
6365 {
6366 /* update upper bound of variable */
6367 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6368 SCIPvarGetName(infcheckvars[0]), SCIPvarGetUbLocal(infcheckvars[0]), newub);
6369
6370 /* tighten variable upper bound to maximal possible value */
6371 SCIP_CALL( SCIPinferVarUbCons(scip, infcheckvars[0], newub, cons,
6372 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6373
6374 if( *cutoff )
6375 {
6376 /* start conflict analysis */
6377 /* @todo improve conflict analysis by adding relaxed bounds */
6378 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6379 }
6380
6381 if( tightened )
6382 ++(*nchgbds);
6383 }
6384 }
6385 /* check if we have only one variable not in infcheckvars, if so we can tighten this variable */
6386 else if( ninfcheckvars == nunfixedvars - 1 )
6387 {
6388 SCIP_Bool foundvar = FALSE;
6389 SCIP_Bool tightened;
6390 SCIP_Real newlb;
6391 SCIP_Real newub;
6392 int w = 0;
6393
6394 assert(ninfcheckvars > 0);
6395 assert(minvalue < maxvalue);
6396
6397 /* find variable which is not an infcheckvar and fix it */
6398 for( v = 0; v < consdata->nvars - 1; ++v )
6399 {
6400 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6401 {
6402 if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6403 {
6404#ifndef NDEBUG
6405 int v2 = v + 1;
6406 int w2 = w;
6407
6408 assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6409
6410 for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6411 {
6412 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6413 continue;
6414
6415 assert(consdata->vars[v2] == infcheckvars[w2]);
6416 ++w2;
6417 }
6418 assert(w2 == ninfcheckvars);
6419#endif
6420
6421 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6422 foundvar = TRUE;
6423
6424 if( consdata->vals[v] < 0 )
6425 {
6426 newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6427 newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6428 }
6429 else
6430 {
6431 newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6432 newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6433 }
6434 assert(SCIPisLE(scip, newlb, newub));
6435
6436 if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6437 {
6438 /* update lower bound of variable */
6439 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6440 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6441
6442 /* tighten variable lower bound to minimal possible value */
6443 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6444 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6445
6446 if( *cutoff )
6447 {
6448 /* start conflict analysis */
6449 /* @todo improve conflict analysis by adding relaxed bounds */
6450 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6451 consdata->vars[v], newlb) );
6452 }
6453
6454 if( tightened )
6455 ++(*nchgbds);
6456 }
6457
6458 if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6459 {
6460 /* update upper bound of variable */
6461 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6462 SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6463
6464 /* tighten variable upper bound to maximal possible value */
6465 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6466 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6467
6468 if( *cutoff )
6469 {
6470 /* start conflict analysis */
6471 /* @todo improve conflict analysis by adding relaxed bounds */
6472 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6473 consdata->vars[v], newub) );
6474 }
6475
6476 if( tightened )
6477 ++(*nchgbds);
6478 }
6479
6480 break;
6481 }
6482
6483 ++w;
6484 }
6485 }
6486
6487 /* maybe last variable was the not infcheckvar */
6488 if( !foundvar )
6489 {
6490 assert(v == consdata->nvars - 1);
6491 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6492
6493 if( consdata->vals[v] < 0 )
6494 {
6495 newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6496 newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6497 }
6498 else
6499 {
6500 newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6501 newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6502 }
6503 assert(SCIPisLE(scip, newlb, newub));
6504
6505 if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6506 {
6507 /* update lower bound of variable */
6508 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6509 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6510
6511 /* tighten variable lower bound to minimal possible value */
6512 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6513 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6514
6515 if( *cutoff )
6516 {
6517 /* start conflict analysis */
6518 /* @todo improve conflict analysis by adding relaxed bounds */
6519 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newlb) );
6520 }
6521
6522 if( tightened )
6523 ++(*nchgbds);
6524 }
6525
6526 if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6527 {
6528 /* update upper bound of variable */
6529 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6530 SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6531
6532 /* tighten variable upper bound to maximal possible value */
6533 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6534 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6535
6536 if( *cutoff )
6537 {
6538 /* start conflict analysis */
6539 /* @todo improve conflict analysis by adding relaxed bounds */
6540 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newub) );
6541 }
6542
6543 if( tightened )
6544 ++(*nchgbds);
6545 }
6546 }
6547 }
6548 /* at least two solutions and more than one variable, so we add a new constraint which bounds the feasible
6549 * region for our infcheckvars, if possible
6550 */
6551 else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6552 {
6553 SCIP_CONS* newcons;
6554 char name[SCIP_MAXSTRLEN];
6555 SCIP_Real newlhs;
6556 SCIP_Real newrhs;
6557
6558 assert(maxvalue > minvalue);
6559
6560 if( SCIPisGT(scip, minvalue, minactinfvars) )
6561 newlhs = minvalue;
6562 else
6563 newlhs = -SCIPinfinity(scip);
6564
6565 if( SCIPisLT(scip, maxvalue, maxactinfvars) )
6566 newrhs = maxvalue;
6567 else
6568 newrhs = SCIPinfinity(scip);
6569
6570 if( !SCIPisInfinity(scip, -newlhs) || !SCIPisInfinity(scip, newrhs) )
6571 {
6572 /* create, add, and release new artificial constraint */
6573 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons1_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6574 ++conshdlrdata->naddconss;
6575
6576 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6577
6578 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6580 SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6581
6582 SCIPdebugPrintCons(scip, newcons, NULL);
6583 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6584
6585 ++(*naddconss);
6586 }
6587 /* @todo maybe add constraint for all variables which are not infcheckvars, lhs should be minvalue, rhs
6588 * should be maxvalue */
6589 }
6590 }
6591 }
6592 }
6593 else if( addartconss && ncontvars < ninfcheckvars )
6594 {
6595 SCIP_Real maxact = 0.0;
6596 SCIP_Real minact = 0.0;
6597 int w = 0;
6598
6599 /* compute activities of non-infcheckvars */
6600 for( v = 0; v < consdata->nvars; ++v )
6601 {
6602 if( w < ninfcheckvars && consdata->vars[v] == infcheckvars[w] )
6603 {
6604 ++w;
6605 continue;
6606 }
6607
6608 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6609 {
6610 if( SCIPvarIsBinary(consdata->vars[v]) )
6611 {
6612 if( consdata->vals[v] > 0.0 )
6613 maxact += consdata->vals[v];
6614 else
6615 minact += consdata->vals[v];
6616 }
6617 else
6618 {
6619 SCIP_Real tmpval;
6620
6621 assert(SCIPvarIsIntegral(consdata->vars[v]));
6622
6623 if( consdata->vals[v] > 0.0 )
6624 {
6625 tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6626
6627 if( SCIPisHugeValue(scip, -tmpval) )
6628 break;
6629
6630 minact += tmpval;
6631
6632 tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6633
6634 if( SCIPisHugeValue(scip, tmpval) )
6635 break;
6636
6637 maxact += tmpval;
6638 }
6639 else
6640 {
6641 tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6642
6643 if( SCIPisHugeValue(scip, -tmpval) )
6644 break;
6645
6646 minact += tmpval;
6647
6648 tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6649
6650 if( SCIPisHugeValue(scip, tmpval) )
6651 break;
6652
6653 maxact += tmpval;
6654 }
6655 }
6656 }
6657 }
6658
6659 if( v == consdata->nvars && !SCIPisHugeValue(scip, -minact) && !SCIPisHugeValue(scip, maxact) )
6660 {
6661 SCIP_CONS* newcons;
6662 char name[SCIP_MAXSTRLEN];
6663 SCIP_Real newlhs;
6664 SCIP_Real newrhs;
6665
6666 assert(maxact > minact);
6667 assert(w == ninfcheckvars);
6668
6669 newlhs = lhs - maxact;
6670 newrhs = rhs - minact;
6671 assert(newlhs < newrhs);
6672
6673 /* create, add, and release new artificial constraint */
6674 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons2_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6675 ++conshdlrdata->naddconss;
6676
6677 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6678
6679 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6681 SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6682
6683 SCIPdebugPrintCons(scip, newcons, NULL);
6684 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6685
6686 ++(*naddconss);
6687 }
6688 }
6689
6690 TERMINATE:
6691 SCIPfreeBufferArray(scip, &infcheckvals);
6692 SCIPfreeBufferArray(scip, &infcheckvars);
6693
6694 return SCIP_OKAY;
6695}
6696
6697/** tightens bounds of a single variable due to activity bounds */
6698static
6700 SCIP* scip, /**< SCIP data structure */
6701 SCIP_CONS* cons, /**< linear constraint */
6702 int pos, /**< position of the variable in the vars array */
6703 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6704 int* nchgbds, /**< pointer to count the total number of tightened bounds */
6705 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
6706 )
6707{
6708 SCIP_CONSDATA* consdata;
6709 SCIP_VAR* var;
6710 SCIP_Real val;
6711 SCIP_Real lb;
6712 SCIP_Real ub;
6713 SCIP_Real minresactivity;
6714 SCIP_Real maxresactivity;
6715 SCIP_Real lhs;
6716 SCIP_Real rhs;
6717 SCIP_Bool infeasible;
6718 SCIP_Bool tightened;
6719 SCIP_Bool ismintight;
6720 SCIP_Bool ismaxtight;
6721 SCIP_Bool isminsettoinfinity;
6722 SCIP_Bool ismaxsettoinfinity;
6723
6724 assert(scip != NULL);
6725 assert(cons != NULL);
6726 assert(cutoff != NULL);
6727 assert(nchgbds != NULL);
6728
6729 /* we cannot tighten variables' bounds, if the constraint may be not complete */
6730 if( SCIPconsIsModifiable(cons) )
6731 return SCIP_OKAY;
6732
6733 consdata = SCIPconsGetData(cons);
6734 assert(consdata != NULL);
6735 assert(0 <= pos && pos < consdata->nvars);
6736
6737 *cutoff = FALSE;
6738
6739 var = consdata->vars[pos];
6740
6741 /* we cannot tighten bounds of multi-aggregated variables */
6743 return SCIP_OKAY;
6744
6745 val = consdata->vals[pos];
6746 lhs = consdata->lhs;
6747 rhs = consdata->rhs;
6748 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
6749 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
6750 assert(var != NULL);
6751 assert(!SCIPisZero(scip, val));
6752 assert(!SCIPisInfinity(scip, lhs));
6753 assert(!SCIPisInfinity(scip, -rhs));
6754
6755 lb = SCIPvarGetLbLocal(var);
6756 ub = SCIPvarGetUbLocal(var);
6757 assert(SCIPisLE(scip, lb, ub));
6758
6759 if( val > 0.0 )
6760 {
6761 /* check, if we can tighten the variable's bounds reliably, therefore only consider sides which are small or
6762 * relatively different to the residual activity bound to avoid cancellation leading to numerical difficulties
6763 */
6764 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && ismintight
6765 && ( SCIPisLT(scip, ABS(rhs), 1.0) || !SCIPisEQ(scip, minresactivity / rhs, 1.0) ) )
6766 {
6767 SCIP_Real newub;
6768
6769 newub = (rhs - minresactivity)/val;
6770
6771 if( !SCIPisInfinity(scip, newub) &&
6772 ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6773 {
6774 SCIP_Bool activityunreliable;
6775 activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6776
6777 /* check minresactivities for reliability */
6778 if( activityunreliable )
6779 {
6780 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6781 newub = (rhs - minresactivity)/val;
6782 activityunreliable = SCIPisInfinity(scip, -minresactivity) ||
6783 (!SCIPisUbBetter(scip, newub, lb, ub) && (!SCIPisFeasLT(scip, newub, ub) || !SCIPvarIsIntegral(var))
6784 && (!force || !SCIPisLT(scip, newub, ub)));
6785 }
6786
6787 if( !activityunreliable )
6788 {
6789 /* tighten upper bound */
6790 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
6791 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6792 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6793 &infeasible, &tightened) );
6794 if( infeasible )
6795 {
6796 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6797 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6798
6799 /* analyze conflict */
6801
6802 *cutoff = TRUE;
6803 return SCIP_OKAY;
6804 }
6805 if( tightened )
6806 {
6807 ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6808 assert(SCIPisFeasLE(scip, ub, newub));
6809 (*nchgbds)++;
6810
6811 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6812 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6813 }
6814 }
6815 }
6816 }
6817
6818 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && ismaxtight
6819 && ( SCIPisLT(scip, ABS(lhs), 1.0) || !SCIPisEQ(scip, maxresactivity / lhs, 1.0) ) )
6820 {
6821 SCIP_Real newlb;
6822
6823 newlb = (lhs - maxresactivity)/val;
6824 if( !SCIPisInfinity(scip, -newlb) &&
6825 ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6826 {
6827 /* check maxresactivities for reliability */
6828 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6829 {
6830 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6831 newlb = (lhs - maxresactivity)/val;
6832
6833 if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisLbBetter(scip, newlb, lb, ub)
6834 && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6835 && (!force || !SCIPisGT(scip, newlb, lb))) )
6836 return SCIP_OKAY;
6837 }
6838
6839 /* tighten lower bound */
6840 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6841 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6842 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6843 &infeasible, &tightened) );
6844 if( infeasible )
6845 {
6846 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6847 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6848
6849 /* analyze conflict */
6851
6852 *cutoff = TRUE;
6853 return SCIP_OKAY;
6854 }
6855 if( tightened )
6856 {
6857 lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6858 assert(SCIPisFeasGE(scip, lb, newlb));
6859 (*nchgbds)++;
6860 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6861 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6862 }
6863 }
6864 }
6865 }
6866 else
6867 {
6868 /* check, if we can tighten the variable's bounds reliably, therefore only consider sides which are small or
6869 * relatively different to the residual activity bound to avoid cancellation leading to numerical difficulties
6870 */
6871 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && ismintight
6872 && ( SCIPisLT(scip, ABS(rhs), 1.0) || !SCIPisEQ(scip, minresactivity / rhs, 1.0) ) )
6873 {
6874 SCIP_Real newlb;
6875
6876 newlb = (rhs - minresactivity)/val;
6877 if( !SCIPisInfinity(scip, -newlb) &&
6878 ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6879 {
6880 SCIP_Bool activityunreliable;
6881 activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6882 /* check minresactivities for reliability */
6883 if( activityunreliable )
6884 {
6885 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6886 newlb = (rhs - minresactivity)/val;
6887
6888 activityunreliable = SCIPisInfinity(scip, -minresactivity)
6889 || (!SCIPisLbBetter(scip, newlb, lb, ub) && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6890 && (!force || !SCIPisGT(scip, newlb, lb)));
6891 }
6892
6893 if( !activityunreliable )
6894 {
6895 /* tighten lower bound */
6896 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6897 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6898 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6899 &infeasible, &tightened) );
6900 if( infeasible )
6901 {
6902 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6903 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6904
6905 /* analyze conflict */
6907
6908 *cutoff = TRUE;
6909 return SCIP_OKAY;
6910 }
6911 if( tightened )
6912 {
6913 lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6914 assert(SCIPisFeasGE(scip, lb, newlb));
6915 (*nchgbds)++;
6916 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6917 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6918 }
6919 }
6920 }
6921 }
6922
6923 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && ismaxtight
6924 && ( SCIPisLT(scip, ABS(lhs), 1.0) || !SCIPisEQ(scip, maxresactivity / lhs, 1.0) ) )
6925 {
6926 SCIP_Real newub;
6927
6928 newub = (lhs - maxresactivity)/val;
6929 if( !SCIPisInfinity(scip, newub) &&
6930 ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6931 {
6932 /* check maxresactivities for reliability */
6933 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6934 {
6935 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6936 newub = (lhs - maxresactivity)/val;
6937
6938 if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisUbBetter(scip, newub, lb, ub)
6939 && (!SCIPisFeasLT(scip, newub, ub) && !SCIPvarIsIntegral(var))
6940 && (!force || !SCIPisLT(scip, newub, ub))) )
6941 return SCIP_OKAY;
6942 }
6943
6944 /* tighten upper bound */
6945 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g], newub=%.15g\n",
6946 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6947 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6948 &infeasible, &tightened) );
6949 if( infeasible )
6950 {
6951 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6952 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6953
6954 /* analyze conflict */
6956
6957 *cutoff = TRUE;
6958 return SCIP_OKAY;
6959 }
6960 if( tightened )
6961 {
6962 ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6963 assert(SCIPisFeasLE(scip, ub, newub));
6964 (*nchgbds)++;
6965 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6966 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6967 }
6968 }
6969 }
6970 }
6971
6972 return SCIP_OKAY;
6973}
6974
6975#define MAXTIGHTENROUNDS 10
6976
6977/** tightens bounds of variables in constraint due to activity bounds */
6978static
6980 SCIP* scip, /**< SCIP data structure */
6981 SCIP_CONS* cons, /**< linear constraint */
6982 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
6983 SCIP_Bool sortvars, /**< should variables be used in sorted order? */
6984 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6985 int* nchgbds /**< pointer to count the total number of tightened bounds */
6986 )
6987{
6988 SCIP_CONSDATA* consdata;
6989 unsigned int tightenmode;
6990 int nvars;
6991 int nrounds;
6992 int lastchange;
6993 int oldnchgbds;
6994#ifndef SCIP_DEBUG
6995 int oldnchgbdstotal;
6996#endif
6997 int v;
6998 SCIP_Bool force;
6999 SCIP_Bool easycase;
7000
7001 assert(scip != NULL);
7002 assert(cons != NULL);
7003 assert(nchgbds != NULL);
7004 assert(cutoff != NULL);
7005
7006 *cutoff = FALSE;
7007
7008 /* we cannot tighten variables' bounds, if the constraint may be not complete */
7009 if( SCIPconsIsModifiable(cons) )
7010 return SCIP_OKAY;
7011
7012 /* if a constraint was created after presolve, then it may hold fixed variables
7013 * if there are even multi-aggregated variables, then we cannot do bound tightening on these
7014 * thus, ensure here again that variable fixings have been applied
7015 */
7016 SCIP_CALL( applyFixings(scip, cons, cutoff) );
7017 if( *cutoff )
7018 return SCIP_OKAY;
7019
7020 /* check if constraint has any chances of tightening bounds */
7021 if( !canTightenBounds(cons) )
7022 return SCIP_OKAY;
7023
7024 consdata = SCIPconsGetData(cons);
7025 assert(consdata != NULL);
7026
7027 nvars = consdata->nvars;
7028 force = (nvars == 1) && !SCIPconsIsModifiable(cons);
7029
7030 /* we are at the root node or during presolving */
7031 if( SCIPgetDepth(scip) < 1 )
7032 tightenmode = 2;
7033 else
7034 tightenmode = 1;
7035
7036 /* stop if we already tightened the constraint and the tightening is not forced */
7037 if( !force && (consdata->boundstightened >= tightenmode) ) /*lint !e574*/
7038 return SCIP_OKAY;
7039
7040 /* ensure that the variables are properly sorted */
7041 if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7042 {
7043 SCIP_CALL( consdataSort(scip, consdata) );
7044 assert(consdata->coefsorted);
7045 }
7046
7047 /* update maximal activity delta if necessary */
7048 if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
7050
7051 assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
7052 assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
7053 checkMaxActivityDelta(scip, consdata);
7054
7055 /* this may happen if all variables are fixed */
7056 if( SCIPisFeasZero(scip, consdata->maxactdelta) )
7057 return SCIP_OKAY;
7058
7059 if( !SCIPisInfinity(scip, consdata->maxactdelta) )
7060 {
7061 SCIP_Real slack;
7062 SCIP_Real surplus;
7063 SCIP_Real minactivity;
7064 SCIP_Real maxactivity;
7065 SCIP_Bool ismintight;
7066 SCIP_Bool ismaxtight;
7067 SCIP_Bool isminsettoinfinity;
7068 SCIP_Bool ismaxsettoinfinity;
7069
7070 /* use maximal activity delta to skip propagation (cannot deduce anything) */
7071 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &ismintight, &ismaxtight,
7072 &isminsettoinfinity, &ismaxsettoinfinity);
7073 assert(!SCIPisInfinity(scip, minactivity));
7074 assert(!SCIPisInfinity(scip, -maxactivity));
7075
7076 slack = (SCIPisInfinity(scip, consdata->rhs) || isminsettoinfinity) ? SCIPinfinity(scip) : (consdata->rhs - minactivity);
7077 surplus = (SCIPisInfinity(scip, -consdata->lhs) || ismaxsettoinfinity) ? SCIPinfinity(scip) : (maxactivity - consdata->lhs);
7078
7079 /* check if the constraint will propagate */
7080 if( SCIPisLE(scip, consdata->maxactdelta, MIN(slack, surplus)) )
7081 return SCIP_OKAY;
7082 }
7083
7084 /* check if we can use fast implementation for easy and numerically well behaved cases */
7085 easycase = SCIPisLT(scip, consdata->maxactdelta, maxeasyactivitydelta);
7086
7087 /* as long as the bounds might be tightened again, try to tighten them; abort after a maximal number of rounds */
7088 lastchange = -1;
7089
7090#ifndef SCIP_DEBUG
7091 oldnchgbds = 0;
7092 oldnchgbdstotal = *nchgbds;
7093#endif
7094
7095 for( nrounds = 0; (force || consdata->boundstightened < tightenmode) && nrounds < MAXTIGHTENROUNDS; ++nrounds ) /*lint !e574*/
7096 {
7097 /* ensure that the variables are properly sorted
7098 *
7099 * note: it might happen that integer variables become binary during bound tightening at the root node
7100 */
7101 if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7102 {
7103 SCIP_CALL( consdataSort(scip, consdata) );
7104 assert(consdata->coefsorted);
7105 }
7106
7107 /* mark the constraint to have the variables' bounds tightened */
7108 consdata->boundstightened = (unsigned int)tightenmode;
7109
7110 /* try to tighten the bounds of each variable in the constraint. During solving process, the binary variable
7111 * sorting enables skipping variables
7112 */
7113 v = 0;
7114 while( v < nvars && v != lastchange && !(*cutoff) )
7115 {
7116 oldnchgbds = *nchgbds;
7117
7118 if( easycase )
7119 {
7120 SCIP_CALL( tightenVarBoundsEasy(scip, cons, v, cutoff, nchgbds, force) );
7121 }
7122 else
7123 {
7124 SCIP_CALL( tightenVarBounds(scip, cons, v, cutoff, nchgbds, force) );
7125 }
7126
7127 /* if there was no progress, skip the rest of the binary variables */
7128 if( *nchgbds > oldnchgbds )
7129 {
7130 lastchange = v;
7131 ++v;
7132 }
7133 else if( consdata->coefsorted && v < consdata->nbinvars - 1
7134 && !SCIPisFeasEQ(scip, SCIPvarGetUbLocal(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v])) )
7135 v = consdata->nbinvars;
7136 else
7137 ++v;
7138 }
7139
7140#ifndef SCIP_DEBUG
7141 SCIPdebugMessage("linear constraint <%s> found %d bound changes in round %d\n", SCIPconsGetName(cons),
7142 *nchgbds - oldnchgbdstotal, nrounds);
7143 oldnchgbdstotal += oldnchgbds;
7144#endif
7145 }
7146
7147#ifndef NDEBUG
7148 if( force && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
7149 assert(*cutoff || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->vars[0]), SCIPvarGetUbLocal(consdata->vars[0])));
7150#endif
7151
7152 return SCIP_OKAY;
7153}
7154
7155/** checks linear constraint for feasibility of given solution or current solution */
7156static
7158 SCIP* scip, /**< SCIP data structure */
7159 SCIP_CONS* cons, /**< linear constraint */
7160 SCIP_SOL* sol, /**< solution to be checked, or NULL for current solution */
7161 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
7162 SCIP_Bool checkrelmaxabs, /**< Should the violation for a constraint with side 0.0 be checked relative
7163 * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
7164 SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
7165 )
7166{
7167 SCIP_CONSDATA* consdata;
7168 SCIP_Real activity;
7169 SCIP_Real absviol;
7170 SCIP_Real relviol;
7171 SCIP_Real lhsviol;
7172 SCIP_Real rhsviol;
7173
7174 assert(scip != NULL);
7175 assert(cons != NULL);
7176 assert(violated != NULL);
7177
7178 SCIPdebugMsg(scip, "checking linear constraint <%s>\n", SCIPconsGetName(cons));
7180
7181 consdata = SCIPconsGetData(cons);
7182 assert(consdata != NULL);
7183
7184 *violated = FALSE;
7185
7186 if( consdata->row != NULL )
7187 {
7188 if( !checklprows && SCIProwIsInLP(consdata->row) )
7189 return SCIP_OKAY;
7190 else if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
7191 activity = consdataComputePseudoActivity(scip, consdata);
7192 else
7193 activity = SCIPgetRowSolActivity(scip, consdata->row, sol);
7194 }
7195 else
7196 activity = consdataGetActivity(scip, consdata, sol);
7197
7198 SCIPdebugMsg(scip, " consdata activity=%.15g (lhs=%.15g, rhs=%.15g, row=%p, checklprows=%u, rowinlp=%u, sol=%p, hascurrentnodelp=%u)\n",
7199 activity, consdata->lhs, consdata->rhs, (void*)consdata->row, checklprows,
7200 consdata->row == NULL ? 0 : SCIProwIsInLP(consdata->row), (void*)sol,
7201 consdata->row == NULL ? FALSE : SCIPhasCurrentNodeLP(scip));
7202
7203 /* calculate absolute and relative bound violations */
7204 lhsviol = consdata->lhs - activity;
7205 rhsviol = activity - consdata->rhs;
7206
7207 absviol = 0.0;
7208 relviol = 0.0;
7209 if( (lhsviol > 0) && (lhsviol > rhsviol) )
7210 {
7211 absviol = lhsviol;
7212 relviol = SCIPrelDiff(consdata->lhs, activity);
7213 }
7214 else if( rhsviol > 0 )
7215 {
7216 absviol = rhsviol;
7217 relviol = SCIPrelDiff(activity, consdata->rhs);
7218 }
7219
7220 /* the activity of pseudo solutions may be invalid if it comprises positive and negative infinity contributions; we
7221 * return infeasible for safety
7222 */
7223 if( activity == SCIP_INVALID ) /*lint !e777*/
7224 {
7225 assert(sol == NULL);
7226 *violated = TRUE;
7227
7228 /* set violation of invalid pseudo solutions */
7229 absviol = SCIP_INVALID;
7230 relviol = SCIP_INVALID;
7231
7232 /* reset constraint age since we are in enforcement */
7234 }
7235 /* check with relative tolerances (the default) */
7236 else if( !consdata->checkabsolute && (SCIPisFeasLT(scip, activity, consdata->lhs) || SCIPisFeasGT(scip, activity, consdata->rhs)) )
7237 {
7238 /* the "normal" check: one of the two sides is violated */
7239 if( !checkrelmaxabs )
7240 {
7241 *violated = TRUE;
7242
7243 /* only reset constraint age if we are in enforcement */
7244 if( sol == NULL )
7245 {
7247 }
7248 }
7249 /* the (much) more complicated check: we try to disregard random noise and violations of a 0.0 side which are
7250 * small compared to the absolute values occurring in the activity
7251 */
7252 else
7253 {
7254 SCIP_Real maxabs;
7255 SCIP_Real coef;
7256 SCIP_Real absval;
7257 SCIP_Real solval;
7258 int v;
7259
7260 maxabs = 1.0;
7261
7262 /* compute maximum absolute value */
7263 for( v = 0; v < consdata->nvars; ++v )
7264 {
7265 if( consdata->vals != NULL )
7266 {
7267 coef = consdata->vals[v];
7268 }
7269 else
7270 coef = 1.0;
7271
7272 solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
7273 absval = REALABS( coef * solval );
7274 maxabs = MAX( maxabs, absval );
7275 }
7276
7277 /* regard left hand side, first */
7278 if( SCIPisFeasLT(scip, activity, consdata->lhs) )
7279 {
7280 /* check whether violation is random noise */
7281 if( (consdata->lhs - activity) <= (1e-15 * maxabs) )
7282 {
7283 SCIPdebugMsg(scip, " lhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7284 consdata->lhs - activity, maxabs);
7286
7287 /* only increase constraint age if we are in enforcement */
7288 if( sol == NULL )
7289 {
7290 SCIP_CALL( SCIPincConsAge(scip, cons) );
7291 }
7292 }
7293 /* lhs is violated and lhs is 0.0: use relative tolerance w.r.t. largest absolute value */
7294 else if( SCIPisZero(scip, consdata->lhs) )
7295 {
7296 if( (consdata->lhs - activity) <= (SCIPfeastol(scip) * maxabs) )
7297 {
7298 SCIPdebugMsg(scip, " lhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7299 consdata->lhs - activity, maxabs);
7301
7302 /* only increase constraint age if we are in enforcement */
7303 if( sol == NULL )
7304 {
7305 SCIP_CALL( SCIPincConsAge(scip, cons) );
7306 }
7307 }
7308 else
7309 {
7310 *violated = TRUE;
7311
7312 /* only reset constraint age if we are in enforcement */
7313 if( sol == NULL )
7314 {
7316 }
7317 }
7318 }
7319 else
7320 {
7321 *violated = TRUE;
7322
7323 /* only reset constraint age if we are in enforcement */
7324 if( sol == NULL )
7325 {
7327 }
7328 }
7329 }
7330
7331 /* now regard right hand side */
7332 if( SCIPisFeasGT(scip, activity, consdata->rhs) )
7333 {
7334 /* check whether violation is random noise */
7335 if( (activity - consdata->rhs) <= (1e-15 * maxabs) )
7336 {
7337 SCIPdebugMsg(scip, " rhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7338 activity - consdata->rhs, maxabs);
7340
7341 /* only increase constraint age if we are in enforcement */
7342 if( sol == NULL )
7343 {
7344 SCIP_CALL( SCIPincConsAge(scip, cons) );
7345 }
7346 }
7347 /* rhs is violated and rhs is 0.0, use relative tolerance w.r.t. largest absolute value */
7348 else if( SCIPisZero(scip, consdata->rhs) )
7349 {
7350 if( (activity - consdata->rhs) <= (SCIPfeastol(scip) * maxabs) )
7351 {
7352 SCIPdebugMsg(scip, " rhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7353 activity - consdata->rhs, maxabs);
7355
7356 /* only increase constraint age if we are in enforcement */
7357 if( sol == NULL )
7358 {
7359 SCIP_CALL( SCIPincConsAge(scip, cons) );
7360 }
7361 }
7362 else
7363 {
7364 *violated = TRUE;
7365
7366 /* only reset constraint age if we are in enforcement */
7367 if( sol == NULL )
7368 {
7370 }
7371 }
7372 }
7373 else
7374 {
7375 *violated = TRUE;
7376
7377 /* only reset constraint age if we are in enforcement */
7378 if( sol == NULL )
7379 {
7381 }
7382 }
7383 }
7384 }
7385 }
7386 /* check with absolute tolerances */
7387 else if( consdata->checkabsolute &&
7388 ((!SCIPisInfinity(scip, -consdata->lhs) && SCIPisGT(scip, consdata->lhs-activity, SCIPfeastol(scip))) ||
7389 (!SCIPisInfinity(scip, consdata->rhs) && SCIPisGT(scip, activity-consdata->rhs, SCIPfeastol(scip)))) )
7390 {
7391 *violated = TRUE;
7392
7393 /* only reset constraint age if we are in enforcement */
7394 if( sol == NULL )
7395 {
7397 }
7398 }
7399 else
7400 {
7401 /* only increase constraint age if we are in enforcement */
7402 if( sol == NULL )
7403 {
7404 SCIP_CALL( SCIPincConsAge(scip, cons) );
7405 }
7406 }
7407
7408 /* update absolute and relative violation of the solution */
7409 if( sol != NULL )
7410 SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
7411
7412 return SCIP_OKAY;
7413}
7414
7415/** creates an LP row in a linear constraint data */
7416static
7418 SCIP* scip, /**< SCIP data structure */
7419 SCIP_CONS* cons /**< linear constraint */
7420 )
7421{
7422 SCIP_CONSDATA* consdata;
7423
7424 assert(scip != NULL);
7425 assert(cons != NULL);
7426
7427 consdata = SCIPconsGetData(cons);
7428 assert(consdata != NULL);
7429 assert(consdata->row == NULL);
7430
7431 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
7433
7434 SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) );
7435
7436 return SCIP_OKAY;
7437}
7438
7439/** adds linear constraint as cut to the LP */
7440static
7442 SCIP* scip, /**< SCIP data structure */
7443 SCIP_CONS* cons, /**< linear constraint */
7444 SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7445 )
7446{
7447 SCIP_CONSDATA* consdata;
7448
7449 assert(scip != NULL);
7450 assert(cons != NULL);
7451
7452 consdata = SCIPconsGetData(cons);
7453 assert(consdata != NULL);
7454
7455 if( consdata->row == NULL )
7456 {
7457 if( !SCIPconsIsModifiable(cons) )
7458 {
7459 /* 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
7460 * removing this here will make test cons/linear/fixedvar.c fail (as of 2018-12-03)
7461 */
7462 SCIP_CALL( applyFixings(scip, cons, cutoff) );
7463 if( *cutoff )
7464 return SCIP_OKAY;
7465 }
7466
7467 /* convert consdata object into LP row */
7468 SCIP_CALL( createRow(scip, cons) );
7469 }
7470 assert(consdata->row != NULL);
7471
7472 if( consdata->nvars == 0 )
7473 {
7474 SCIPdebugMsg(scip, "Empty linear constraint enters LP: <%s>\n", SCIPconsGetName(cons));
7475 }
7476
7477 /* insert LP row as cut */
7478 if( !SCIProwIsInLP(consdata->row) )
7479 {
7480 SCIPdebugMsg(scip, "adding relaxation of linear constraint <%s>: ", SCIPconsGetName(cons));
7481 SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL)) );
7482 /* if presolving is turned off, the row might be trivial */
7483 if ( ! SCIPisInfinity(scip, -consdata->lhs) || ! SCIPisInfinity(scip, consdata->rhs) )
7484 {
7485 SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, cutoff) );
7486 }
7487 }
7488
7489 return SCIP_OKAY;
7490}
7491
7492/** adds linear constraint as row to the NLP, if not added yet */
7493static
7495 SCIP* scip, /**< SCIP data structure */
7496 SCIP_CONS* cons /**< linear constraint */
7497 )
7498{
7499 SCIP_CONSDATA* consdata;
7500
7502
7503 /* skip deactivated, redundant, or local linear constraints (the NLP does not allow for local rows at the moment) */
7504 if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsLocal(cons) )
7505 return SCIP_OKAY;
7506
7507 consdata = SCIPconsGetData(cons);
7508 assert(consdata != NULL);
7509
7510 if( consdata->nlrow == NULL )
7511 {
7512 assert(consdata->lhs <= consdata->rhs);
7513
7514 SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons),
7515 0.0, consdata->nvars, consdata->vars, consdata->vals, NULL, consdata->lhs, consdata->rhs, SCIP_EXPRCURV_LINEAR) );
7516
7517 assert(consdata->nlrow != NULL);
7518 }
7519
7520 if( !SCIPnlrowIsInNLP(consdata->nlrow) )
7521 {
7522 SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow) );
7523 }
7524
7525 return SCIP_OKAY;
7526}
7527
7528/** separates linear constraint: adds linear constraint as cut, if violated by given solution */
7529static
7531 SCIP* scip, /**< SCIP data structure */
7532 SCIP_CONS* cons, /**< linear constraint */
7533 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
7534 SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
7535 SCIP_Bool separatecards, /**< should knapsack cardinality cuts be generated? */
7536 SCIP_Bool separateall, /**< should all constraints be subject to cardinality cut generation instead of only
7537 * the ones with non-zero dual value? */
7538 int* ncuts, /**< pointer to add up the number of found cuts */
7539 SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7540 )
7541{
7542 SCIP_CONSDATA* consdata;
7543 SCIP_Bool violated;
7544 int oldncuts;
7545
7546 assert(scip != NULL);
7547 assert(conshdlrdata != NULL);
7548 assert(cons != NULL);
7549 assert(cutoff != NULL);
7550
7551 consdata = SCIPconsGetData(cons);
7552 assert(ncuts != NULL);
7553 assert(consdata != NULL);
7554
7555 oldncuts = *ncuts;
7556 *cutoff = FALSE;
7557
7558 SCIP_CALL( checkCons(scip, cons, sol, (sol != NULL), conshdlrdata->checkrelmaxabs, &violated) );
7559
7560 if( violated )
7561 {
7562 /* insert LP row as cut */
7564 (*ncuts)++;
7565 }
7566 else if( !SCIPconsIsModifiable(cons) && separatecards && consdata->nvars > 0 )
7567 {
7568 /* relax linear constraint into knapsack constraint and separate lifted cardinality cuts */
7569 if( !separateall && sol == NULL )
7570 {
7571 /* we only want to call the knapsack cardinality cut separator for rows that have a non-zero dual solution */
7572 if( consdata->row != NULL && SCIProwIsInLP(consdata->row) )
7573 {
7574 SCIP_Real dualsol;
7575
7576 dualsol = SCIProwGetDualsol(consdata->row);
7577 if( SCIPisFeasNegative(scip, dualsol) )
7578 {
7579 if( !SCIPisInfinity(scip, consdata->rhs) )
7580 {
7581 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7582 consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7583 }
7584 }
7585 else if( SCIPisFeasPositive(scip, dualsol) )
7586 {
7587 if( !SCIPisInfinity(scip, -consdata->lhs) )
7588 {
7589 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7590 consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7591 }
7592 }
7593 }
7594 }
7595 else
7596 {
7597 if( !SCIPisInfinity(scip, consdata->rhs) )
7598 {
7599 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7600 consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7601 }
7602 if( !SCIPisInfinity(scip, -consdata->lhs) )
7603 {
7604 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7605 consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7606 }
7607 }
7608 }
7609
7610 if( *ncuts > oldncuts )
7611 {
7613 }
7614
7615 return SCIP_OKAY;
7616}
7617
7618/** propagation method for linear constraints */
7619static
7621 SCIP* scip, /**< SCIP data structure */
7622 SCIP_CONS* cons, /**< linear constraint */
7623 SCIP_Bool tightenbounds, /**< should the variable's bounds be tightened? */
7624 SCIP_Bool rangedrowpropagation,/**< should ranged row propagation be performed? */
7625 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7626 SCIP_Bool sortvars, /**< should variable sorting for faster propagation be used? */
7627 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7628 int* nchgbds, /**< pointer to count the number of bound changes */
7629 int* naddconss /**< pointer to count number of added constraints */
7630 )
7631{
7632 SCIP_CONSDATA* consdata;
7633 SCIP_Real minactivity;
7634 SCIP_Real maxactivity;
7635 SCIP_Bool isminacttight;
7636 SCIP_Bool ismaxacttight;
7637 SCIP_Bool isminsettoinfinity;
7638 SCIP_Bool ismaxsettoinfinity;
7639
7640 assert(scip != NULL);
7641 assert(cons != NULL);
7642 assert(cutoff != NULL);
7643 assert(nchgbds != NULL);
7644
7645 /*SCIPdebugMsg(scip, "propagating linear constraint <%s>\n", SCIPconsGetName(cons));*/
7646
7647 consdata = SCIPconsGetData(cons);
7648 assert(consdata != NULL);
7649
7650 if( consdata->eventdata == NULL )
7651 {
7652 SCIP_CONSHDLR* conshdlr;
7653 SCIP_CONSHDLRDATA* conshdlrdata;
7654
7655 conshdlr = SCIPconsGetHdlr(cons);
7656 assert(conshdlr != NULL);
7657
7658 conshdlrdata = SCIPconshdlrGetData(conshdlr);
7659 assert(conshdlrdata != NULL);
7660
7661 /* catch bound change events of variables */
7662 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
7663 assert(consdata->eventdata != NULL);
7664 }
7665
7666 *cutoff = FALSE;
7667
7668 /* we can only infer activity bounds of the linear constraint, if it is not modifiable */
7669 if( !SCIPconsIsModifiable(cons) )
7670 {
7671 /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
7673 {
7674 SCIP_CALL( SCIPincConsAge(scip, cons) );
7675 }
7676
7677 /* tighten the variable's bounds */
7678 if( tightenbounds )
7679 {
7680 int oldnchgbds;
7681
7682 oldnchgbds = *nchgbds;
7683
7684 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
7685
7686 if( *nchgbds > oldnchgbds )
7687 {
7689 }
7690 }
7691
7692 /* propagate ranged rows */
7693 if( rangedrowpropagation && tightenbounds && !(*cutoff) )
7694 {
7695 int nfixedvars = 0;
7696
7697 SCIPdebug( int oldnchgbds = *nchgbds; )
7698
7699 SCIP_CALL( rangedRowPropagation(scip, cons, cutoff, &nfixedvars, nchgbds, naddconss) );
7700
7701 if( *cutoff )
7702 {
7703 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible\n", SCIPconsGetName(cons));
7704 }
7705 else
7706 {
7707 SCIPdebug( SCIPdebugMsg(scip, "linear constraint <%s> found %d bound changes and %d fixings\n", SCIPconsGetName(cons), *nchgbds - oldnchgbds, nfixedvars); )
7708 }
7709
7710 if( nfixedvars > 0 )
7711 *nchgbds += 2 * nfixedvars;
7712 } /*lint !e438*/
7713
7714 /* check constraint for infeasibility and redundancy */
7715 if( !(*cutoff) )
7716 {
7717 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
7718 &isminsettoinfinity, &ismaxsettoinfinity);
7719
7720 if( SCIPisFeasGT(scip, minactivity, consdata->rhs) )
7721 {
7722 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (rhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7723 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7724
7725 /* analyze conflict */
7727
7729 *cutoff = TRUE;
7730 }
7731 else if( SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
7732 {
7733 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (lhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7734 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7735
7736 /* analyze conflict */
7738
7740 *cutoff = TRUE;
7741 }
7742 else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
7743 {
7744 SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7745 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7746
7747 /* remove the constraint locally unless it has become empty, in which case it is removed globally */
7748 if( consdata->nvars > 0 )
7750 else
7751 SCIP_CALL( SCIPdelCons(scip, cons) );
7752 }
7753 }
7754 }
7755
7756 return SCIP_OKAY;
7757}
7758
7759
7760/*
7761 * Presolving methods
7762 */
7763
7764/** converts all variables with fixed domain into FIXED variables */
7765static
7767 SCIP* scip, /**< SCIP data structure */
7768 SCIP_CONS* cons, /**< linear constraint */
7769 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
7770 int* nfixedvars /**< pointer to count the total number of fixed variables */
7771 )
7772{
7773 SCIP_CONSDATA* consdata;
7774 SCIP_VAR* var;
7775 SCIP_VARSTATUS varstatus;
7776 SCIP_Real lb;
7777 SCIP_Real ub;
7778 SCIP_Bool fixed;
7779 SCIP_Bool infeasible;
7780 int v;
7781
7782 assert(scip != NULL);
7783 assert(cons != NULL);
7784 assert(cutoff != NULL);
7785 assert(nfixedvars != NULL);
7786
7787 consdata = SCIPconsGetData(cons);
7788 assert(consdata != NULL);
7789
7790 for( v = 0; v < consdata->nvars; ++v )
7791 {
7792 assert(consdata->vars != NULL);
7793 var = consdata->vars[v];
7794 varstatus = SCIPvarGetStatus(var);
7795
7796 if( varstatus != SCIP_VARSTATUS_FIXED )
7797 {
7798 lb = SCIPvarGetLbGlobal(var);
7799 ub = SCIPvarGetUbGlobal(var);
7800 if( SCIPisEQ(scip, lb, ub) )
7801 {
7802 SCIP_Real fixval;
7803
7804 fixval = SCIPselectSimpleValue(lb, ub, MAXDNOM);
7805 SCIPdebugMsg(scip, "converting variable <%s> with fixed bounds [%.15g,%.15g] into fixed variable fixed at %.15g\n",
7806 SCIPvarGetName(var), lb, ub, fixval);
7807 SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
7808 if( infeasible )
7809 {
7810 SCIPdebugMsg(scip, " -> infeasible fixing\n");
7811 *cutoff = TRUE;
7812 return SCIP_OKAY;
7813 }
7814 if( fixed )
7815 (*nfixedvars)++;
7816 }
7817 }
7818 }
7819
7820 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
7821
7822 if( infeasible )
7823 {
7824 SCIPdebugMsg(scip, " -> infeasible fixing\n");
7825 *cutoff = TRUE;
7826 return SCIP_OKAY;
7827 }
7828
7829 assert(consdata->removedfixings);
7830
7831 return SCIP_OKAY;
7832}
7833
7834#define MAX_CLIQUE_NONZEROS_PER_CONS 1000000
7835
7836/** extracts cliques of the constraint and adds them to SCIP
7837 *
7838 * The following clique extraction mechanism are implemeneted
7839 *
7840 * 1. collect binary variables and sort them in non increasing order, then
7841 *
7842 * a) if the constraint has a finite right hand side and the negative infinity counters for the minactivity are zero
7843 * then add the variables as a clique for which all successive pairs of coefficients fullfill the following
7844 * condition
7845 *
7846 * minactivity + vals[i] + vals[i+1] > rhs
7847 *
7848 * and also add the binary to binary implication also for non-successive variables for which the same argument
7849 * holds
7850 *
7851 * minactivity + vals[i] + vals[j] > rhs
7852 *
7853 * 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
7854 * binary to binary implications x1 = 1 => x4 = 0 and x2 = 1 => x4 = 0
7855 *
7856 * b) if the constraint has a finite left hand side and the positive infinity counters for the maxactivity are zero
7857 * then add the variables as a clique for which all successive pairs of coefficients fullfill the follwoing
7858 * condition
7859 *
7860 * maxactivity + vals[i] + vals[i-1] < lhs
7861 *
7862 * and also add the binary to binary implication also for non-successive variables for which the same argument
7863 * holds
7864 *
7865 * maxactivity + vals[i] + vals[j] < lhs
7866 *
7867 * e.g. you could multiply the above example by -1
7868 *
7869 * c) the constraint has a finite right hand side and a finite minactivity then add the variables as a negated
7870 * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7871 * condition
7872 *
7873 * minactivity - vals[i] - vals[i-1] > rhs
7874 *
7875 * and also add the binary to binary implication also for non-successive variables for which the
7876 * same argument holds
7877 *
7878 * minactivity - vals[i] - vals[j] > rhs
7879 *
7880 * e.g. -4 x1 -3 x2 - 2 x3 + 2 x4 <= -4 would lead to the (negated) clique (~x1, ~x2) and the binary to binary
7881 * implication x1 = 0 => x3 = 1
7882 *
7883 * d) the constraint has a finite left hand side and a finite maxactivity then add the variables as a negated
7884 * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7885 * condition
7886 *
7887 * maxactivity - vals[i] - vals[i+1] < lhs
7888 *
7889 * and also add the binary to binary implication also for non-successive variables for which the same argument
7890 * holds
7891 *
7892 * maxactivity - vals[i] - vals[j] < lhs
7893 *
7894 * e.g. you could multiply the above example by -1
7895 *
7896 * 2. if the linear constraint represents a set-packing or set-partitioning constraint, the whole constraint is added
7897 * as clique, (this part is done at the end of the method)
7898 *
7899 */
7900static
7902 SCIP* scip, /**< SCIP data structure */
7903 SCIP_CONS* cons, /**< linear constraint */
7904 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7905 SCIP_Bool sortvars, /**< should variables be used in sorted order? */
7906 int* nfixedvars, /**< pointer to count number of fixed variables */
7907 int* nchgbds, /**< pointer to count the total number of tightened bounds */
7908 SCIP_Bool* cutoff /**< pointer to store TRUE, if a cutoff was found */
7909 )
7910{
7911 SCIP_VAR** vars;
7912 SCIP_Real* vals;
7913 SCIP_CONSDATA* consdata;
7914 SCIP_Bool lhsclique;
7915 SCIP_Bool rhsclique;
7916 SCIP_Bool finitelhs;
7917 SCIP_Bool finiterhs;
7918 SCIP_Bool finiteminact;
7919 SCIP_Bool finitemaxact;
7920 SCIP_Bool finitenegminact;
7921 SCIP_Bool finitenegmaxact;
7922 SCIP_Bool finiteposminact;
7923 SCIP_Bool finiteposmaxact;
7924 SCIP_Bool infeasible;
7925 SCIP_Bool stopped;
7926 int cliquenonzerosadded;
7927 int v;
7928 int i;
7929 int nposcoefs;
7930 int nnegcoefs;
7931 int nvars;
7932
7933 assert(scip != NULL);
7934 assert(cons != NULL);
7935 assert(nfixedvars != NULL);
7936 assert(nchgbds != NULL);
7937 assert(cutoff != NULL);
7938 assert(!SCIPconsIsDeleted(cons));
7939
7940 consdata = SCIPconsGetData(cons);
7941 assert(consdata != NULL);
7942
7943 if( consdata->nvars < 2 )
7944 return SCIP_OKAY;
7945
7946 /* add implications if possible
7947 *
7948 * for now we only add binary to non-binary implications, and this is only done for the binary variable with the
7949 * maximal absolute contribution and also only if this variable would force all other variables to their bound
7950 * corresponding to the global minimal activity of the constraint
7951 */
7952 if( !consdata->implsadded )
7953 {
7954 /* sort variables by variable type */
7955 SCIP_CALL( consdataSort(scip, consdata) );
7956
7957 /* @todo we might extract implications/cliques if SCIPvarIsBinary() variables exist and we have integer variables
7958 * up front, might change sorting correspondingly
7959 */
7960 /* fast abort if no binaries seem to exist
7961 * "seem to", because there are rare situations in which variables may actually not be sorted by type, even though consdataSort has been called
7962 * this situation can occur if, e.g., the type of consdata->vars[1] has been changed to binary, but the corresponding variable event has
7963 * not been executed yet, because it is the eventExecLinear() which marks the variables array as unsorted (set consdata->indexsorted to FALSE),
7964 * which is the requirement for consdataSort() to actually resort the variables
7965 * we assume that in this situation the below code may be executed in a future presolve round, after the variable events have been executed
7966 */
7967 if( !SCIPvarIsBinary(consdata->vars[0]) )
7968 return SCIP_OKAY;
7969
7970 nvars = consdata->nvars;
7971 vars = consdata->vars;
7972 vals = consdata->vals;
7973
7974 /* recompute activities if needed */
7975 if( !consdata->validactivities )
7976 consdataCalcActivities(scip, consdata);
7977 assert(consdata->validactivities);
7978
7979 finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
7980 finiterhs = !SCIPisInfinity(scip, consdata->rhs);
7981 finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
7982 finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
7983 finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
7984 finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
7985 finiteminact = (finitenegminact && finiteposminact);
7986 finitemaxact = (finitenegmaxact && finiteposmaxact);
7987
7988 if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
7989 {
7990 SCIP_Real maxabscontrib = -1.0;
7991 SCIP_Bool posval = FALSE;
7992 SCIP_Bool allbinary = TRUE;
7993 int oldnchgbds = *nchgbds;
7994 int nbdchgs = 0;
7995 int nimpls = 0;
7996 int position = -1;
7997
7998 /* we need a valid minimal/maximal activity to add cliques */
7999 if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8000 {
8002 assert(consdata->validglbminact);
8003 }
8004
8005 if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8006 {
8008 assert(consdata->validglbmaxact);
8009 }
8010 assert(consdata->validglbminact || consdata->validglbmaxact);
8011
8012 /* @todo extend this to local/constraint probing */
8013
8014 /* determine maximal contribution to the activity */
8015 for( v = nvars - 1; v >= 0; --v )
8016 {
8017 if( SCIPvarIsBinary(vars[v]) )
8018 {
8019 if( vals[v] > 0 )
8020 {
8021 SCIP_Real value = vals[v] * SCIPvarGetUbGlobal(vars[v]);
8022
8023 if( value > maxabscontrib )
8024 {
8025 maxabscontrib = value;
8026 position = v;
8027 posval = TRUE;
8028 }
8029 }
8030 else
8031 {
8032 SCIP_Real value = vals[v] * SCIPvarGetLbGlobal(vars[v]);
8033
8034 value = REALABS(value);
8035
8036 if( value > maxabscontrib )
8037 {
8038 maxabscontrib = value;
8039 position = v;
8040 posval = FALSE;
8041 }
8042 }
8043 }
8044 else
8045 allbinary = FALSE;
8046 }
8047 assert(0 <= position && position < nvars);
8048
8049 if( !SCIPisEQ(scip, maxabscontrib, 1.0) && !allbinary )
8050 {
8051 /* if the right hand side and the minimal activity are finite and changing the variable with the biggest
8052 * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8053 * implications
8054 */
8055 if( finiterhs && finiteminact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbminactivity), consdata->rhs - maxabscontrib) )
8056 {
8057 for( v = nvars - 1; v >= 0; --v )
8058 {
8059 /* binary to binary implications will be collected when extrating cliques */
8060 if( !SCIPvarIsBinary(vars[v]) )
8061 {
8062 if( v != position )
8063 {
8064 if( vals[v] > 0 )
8065 {
8066 /* add implications */
8067 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8068 ++nimpls;
8069 *nchgbds += nbdchgs;
8070 }
8071 else
8072 {
8073 /* add implications */
8074 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8075 ++nimpls;
8076 *nchgbds += nbdchgs;
8077 }
8078
8079 if( infeasible )
8080 {
8081 *cutoff = TRUE;
8082 break;
8083 }
8084 }
8085 }
8086 /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8088 break;
8089 }
8090 }
8091
8092 /* if the left hand side and the maximal activity are finite and changing the variable with the biggest
8093 * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8094 * implications
8095 */
8096 if( finitelhs && finitemaxact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbmaxactivity), consdata->lhs - maxabscontrib) )
8097 {
8098 for( v = nvars - 1; v >= 0; --v )
8099 {
8100 /* binary to binary implications will be collected when extrating cliques */
8101 if( !SCIPvarIsBinary(vars[v]) )
8102 {
8103 if( v != position )
8104 {
8105 if( vals[v] > 0 )
8106 {
8107 /* add implications */
8108 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8109 ++nimpls;
8110 *nchgbds += nbdchgs;
8111 }
8112 else
8113 {
8114 /* add implications */
8115 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8116 ++nimpls;
8117 *nchgbds += nbdchgs;
8118 }
8119
8120 if( infeasible )
8121 {
8122 *cutoff = TRUE;
8123 break;
8124 }
8125 }
8126 }
8127 /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8128 else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8129 break;
8130 }
8131 }
8132
8133 /* did we find some implications */
8134 if( nimpls > 0 )
8135 {
8136 SCIPdebugMsg(scip, "extracted %d implications from constraint %s which led to %d bound changes, %scutoff detetcted\n", nimpls, SCIPconsGetName(cons), *nchgbds - oldnchgbds, *cutoff ? "" : "no ");
8137
8138 if( *cutoff )
8139 return SCIP_OKAY;
8140
8141 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8142 if( *nchgbds - oldnchgbds > 0 )
8143 {
8144 /* check for fixed variables */
8145 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8146 if( *cutoff )
8147 return SCIP_OKAY;
8148
8149 /* tighten variable's bounds */
8150 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8151 if( *cutoff )
8152 return SCIP_OKAY;
8153
8154 /* check for fixed variables */
8155 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8156 if( *cutoff )
8157 return SCIP_OKAY;
8158 }
8159 }
8160 }
8161 }
8162
8163 consdata->implsadded = TRUE;
8164 }
8165
8166 /* check if we already added the cliques of this constraint */
8167 if( consdata->cliquesadded )
8168 return SCIP_OKAY;
8169
8170 consdata->cliquesadded = TRUE;
8171 cliquenonzerosadded = 0;
8172 stopped = FALSE;
8173
8174 /* sort variables by variable type */
8175 SCIP_CALL( consdataSort(scip, consdata) );
8176
8177 nvars = consdata->nvars;
8178 vars = consdata->vars;
8179 vals = consdata->vals;
8180
8181 /**@todo extract more cliques, implications and variable bounds from linear constraints */
8182
8183 /* recompute activities if needed */
8184 if( !consdata->validactivities )
8185 consdataCalcActivities(scip, consdata);
8186 assert(consdata->validactivities);
8187
8188 finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8189 finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8190 finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8191 finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8192 finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8193 finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8194 finiteminact = (finitenegminact && finiteposminact);
8195 finitemaxact = (finitenegmaxact && finiteposmaxact);
8196
8197 /* 1. we wheck whether some variables do not fit together into this constraint and add the corresponding clique
8198 * information
8199 */
8200 if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
8201 {
8202 SCIP_VAR** binvars;
8203 SCIP_Real* binvarvals;
8204 int nposbinvars = 0;
8205 int nnegbinvars = 0;
8206 int allonebinary = 0;
8207
8209 SCIP_CALL( SCIPallocBufferArray(scip, &binvarvals, nvars) );
8210
8211 /* collect binary variables */
8212 for( i = 0; i < nvars; ++i )
8213 {
8214 if( SCIPvarIsBinary(vars[i]) )
8215 {
8216 assert(!SCIPisZero(scip, vals[i]));
8217
8218 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8219 ++allonebinary;
8220
8221 binvars[nposbinvars + nnegbinvars] = vars[i];
8222 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8223
8224 if( SCIPisPositive(scip, vals[i]) )
8225 ++nposbinvars;
8226 else
8227 ++nnegbinvars;
8228
8229 assert(nposbinvars + nnegbinvars <= nvars);
8230 }
8231 /* stop searching for binary variables, because the constraint data is sorted */
8232 else if( !SCIPvarIsIntegral(vars[i]) )
8233 break;
8234 }
8235 assert(nposbinvars + nnegbinvars <= nvars);
8236
8237 /* setppc constraints will be handled later; we need at least two binary variables with same sign to extract
8238 * cliques
8239 */
8240 if( allonebinary < nvars && (nposbinvars >= 2 || nnegbinvars >= 2) )
8241 {
8242 SCIP_Real threshold;
8243 int oldnchgbds = *nchgbds;
8244 int nbdchgs;
8245 int jstart;
8246 int j;
8247
8248 /* we need a valid minimal/maximal activity to add cliques */
8249 if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8250 {
8252 assert(consdata->validglbminact);
8253 }
8254
8255 if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8256 {
8258 assert(consdata->validglbmaxact);
8259 }
8260 assert(consdata->validglbminact || consdata->validglbmaxact);
8261
8262 /* sort coefficients non-increasing to be faster in the clique search */
8263 SCIPsortDownRealPtr(binvarvals, (void**) binvars, nposbinvars + nnegbinvars);
8264
8265 /* case a) */
8266 if( finiterhs && finitenegminact && nposbinvars >= 2 )
8267 {
8268 /* compute value that needs to be exceeded */
8269 threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
8270
8271 j = 1;
8272#ifdef SCIP_DISABLED_CODE /* assertion should only hold when constraints were fully propagated and boundstightened */
8273 /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8274 assert(SCIPisFeasLE(scip, binvarvals[0], threshold));
8275#endif
8276 /* check if at least two variables are in a clique */
8277 if( SCIPisFeasGT(scip, binvarvals[0] + binvarvals[j], threshold) )
8278 {
8279 ++j;
8280 /* check for extending the clique */
8281 while( j < nposbinvars )
8282 {
8283 if( !SCIPisFeasGT(scip, binvarvals[j-1] + binvarvals[j], threshold) )
8284 break;
8285 ++j;
8286 }
8287 assert(j >= 2);
8288
8289 /* add clique with at least two variables */
8290 SCIP_CALL( SCIPaddClique(scip, binvars, NULL, j, FALSE, &infeasible, &nbdchgs) );
8291
8292 if( infeasible )
8293 *cutoff = TRUE;
8294
8295 *nchgbds += nbdchgs;
8296
8297 cliquenonzerosadded += j;
8298 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8299 stopped = TRUE;
8300
8301 /* exchange the last variable in the clique if possible and add all new ones */
8302 if( !stopped && !(*cutoff) && j < nposbinvars )
8303 {
8304 SCIP_VAR** clqvars;
8305 int lastfit = j - 2;
8306 assert(lastfit >= 0);
8307
8308 /* copy all 'main'-clique variables */
8309 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
8310
8311 /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8312 while( lastfit >= 0 && j < nposbinvars )
8313 {
8314 /* check if two variables are in a clique */
8315 if( SCIPisFeasGT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8316 {
8317 clqvars[lastfit + 1] = binvars[j];
8318
8319 /* add clique with at least two variables */
8320 SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8321
8322 if( infeasible )
8323 {
8324 *cutoff = TRUE;
8325 break;
8326 }
8327
8328 *nchgbds += nbdchgs;
8329
8330 cliquenonzerosadded += (lastfit + 2);
8331 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8332 {
8333 stopped = TRUE;
8334 break;
8335 }
8336
8337 ++j;
8338 }
8339 else
8340 --lastfit;
8341 }
8342
8343 SCIPfreeBufferArray(scip, &clqvars);
8344 }
8345 }
8346 }
8347
8348 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8349 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8350 {
8351 /* check for fixed variables */
8352 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8353
8354 if( !*cutoff )
8355 {
8356 /* tighten variable's bounds */
8357 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8358
8359 if( !*cutoff )
8360 {
8361 /* check for fixed variables */
8362 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8363
8364 if( !*cutoff )
8365 {
8366 /* sort variables by variable type */
8367 SCIP_CALL( consdataSort(scip, consdata) );
8368
8369 /* recompute activities if needed */
8370 if( !consdata->validactivities )
8371 consdataCalcActivities(scip, consdata);
8372 assert(consdata->validactivities);
8373
8374 nvars = consdata->nvars;
8375 vars = consdata->vars;
8376 vals = consdata->vals;
8377 nposbinvars = 0;
8378 nnegbinvars = 0;
8379 allonebinary = 0;
8380
8381 /* update binary variables */
8382 for( i = 0; i < nvars; ++i )
8383 {
8384 if( SCIPvarIsBinary(vars[i]) )
8385 {
8386 assert(!SCIPisZero(scip, vals[i]));
8387
8388 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8389 ++allonebinary;
8390
8391 binvars[nposbinvars + nnegbinvars] = vars[i];
8392 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8393
8394 if( SCIPisPositive(scip, vals[i]) )
8395 ++nposbinvars;
8396 else
8397 ++nnegbinvars;
8398
8399 assert(nposbinvars + nnegbinvars <= nvars);
8400 }
8401 /* stop searching for binary variables, because the constraint data is sorted */
8402 else if( !SCIPvarIsIntegral(vars[i]) )
8403 break;
8404 }
8405 assert(nposbinvars + nnegbinvars <= nvars);
8406 }
8407 }
8408 }
8409
8410 oldnchgbds = *nchgbds;
8411 }
8412
8413 /* case b) */
8414 if( !stopped && !(*cutoff) && finitelhs && finiteposmaxact && nnegbinvars >= 2 )
8415 {
8416 /* compute value that needs to be deceeded */
8417 threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
8418
8419 i = nposbinvars + nnegbinvars - 1;
8420 j = i - 1;
8421#ifdef SCIP_DISABLED_CODE
8422 /* assertion should only hold when constraints were fully propagated and boundstightened */
8423 /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8424 assert(SCIPisFeasGE(scip, binvarvals[i], threshold));
8425#endif
8426 /* check if two variables are in a clique */
8427 if( SCIPisFeasLT(scip, binvarvals[i] + binvarvals[j], threshold) )
8428 {
8429 --j;
8430 /* check for extending the clique */
8431 while( j >= nposbinvars )
8432 {
8433 if( !SCIPisFeasLT(scip, binvarvals[j+1] + binvarvals[j], threshold) )
8434 break;
8435 --j;
8436 }
8437 jstart = j;
8438
8439 assert(i - j >= 2);
8440 /* add clique with at least two variables */
8441 SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), NULL, i - j, FALSE, &infeasible, &nbdchgs) );
8442
8443 if( infeasible )
8444 *cutoff = TRUE;
8445
8446 *nchgbds += nbdchgs;
8447
8448 cliquenonzerosadded += (i - j);
8449 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8450 stopped = TRUE;
8451
8452 /* exchange the last variable in the clique if possible and add all new ones */
8453 if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8454 {
8455 SCIP_VAR** clqvars;
8456 int lastfit = jstart + 1;
8457 assert(lastfit < i);
8458
8459 /* copy all 'main'-clique variables */
8460 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8461 ++lastfit;
8462
8463 /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8464 while( lastfit <= i && j >= nposbinvars )
8465 {
8466 /* check if two variables are in a clique */
8467 if( SCIPisFeasLT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8468 {
8469 assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8470 clqvars[lastfit - jstart - 2] = binvars[j];
8471
8472 assert(i - lastfit + 2 >= 2);
8473 /* add clique with at least two variables */
8474 SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), NULL, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8475
8476 if( infeasible )
8477 {
8478 *cutoff = TRUE;
8479 break;
8480 }
8481
8482 *nchgbds += nbdchgs;
8483
8484 cliquenonzerosadded += (i - lastfit + 2);
8485 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8486 {
8487 stopped = TRUE;
8488 break;
8489 }
8490
8491 --j;
8492 }
8493 else
8494 ++lastfit;
8495 }
8496
8497 SCIPfreeBufferArray(scip, &clqvars);
8498 }
8499 }
8500 }
8501
8502 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8503 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8504 {
8505 /* check for fixed variables */
8506 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8507
8508 if( !*cutoff )
8509 {
8510 /* tighten variable's bounds */
8511 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8512
8513 if( !*cutoff )
8514 {
8515 /* check for fixed variables */
8516 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8517
8518 if( !*cutoff )
8519 {
8520 /* sort variables by variable type */
8521 SCIP_CALL( consdataSort(scip, consdata) );
8522
8523 /* recompute activities if needed */
8524 if( !consdata->validactivities )
8525 consdataCalcActivities(scip, consdata);
8526 assert(consdata->validactivities);
8527
8528 nvars = consdata->nvars;
8529 vars = consdata->vars;
8530 vals = consdata->vals;
8531 nposbinvars = 0;
8532 nnegbinvars = 0;
8533 allonebinary = 0;
8534
8535 /* update binary variables */
8536 for( i = 0; i < nvars; ++i )
8537 {
8538 if( SCIPvarIsBinary(vars[i]) )
8539 {
8540 assert(!SCIPisZero(scip, vals[i]));
8541
8542 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8543 ++allonebinary;
8544
8545 binvars[nposbinvars + nnegbinvars] = vars[i];
8546 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8547
8548 if( SCIPisPositive(scip, vals[i]) )
8549 ++nposbinvars;
8550 else
8551 ++nnegbinvars;
8552
8553 assert(nposbinvars + nnegbinvars <= nvars);
8554 }
8555 /* stop searching for binary variables, because the constraint data is sorted */
8556 else if( !SCIPvarIsIntegral(vars[i]) )
8557 break;
8558 }
8559 assert(nposbinvars + nnegbinvars <= nvars);
8560 }
8561 }
8562 }
8563
8564 oldnchgbds = *nchgbds;
8565 }
8566
8567 /* case c) */
8568 if( !(*cutoff) && finiterhs && finiteminact && nnegbinvars >= 2 )
8569 {
8570 SCIP_Bool* values;
8571
8572 /* initialize clique values array for adding a negated clique */
8573 SCIP_CALL( SCIPallocBufferArray(scip, &values, nnegbinvars) );
8574 BMSclearMemoryArray(values, nnegbinvars);
8575
8576 /* compute value that needs to be exceeded */
8577 threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
8578
8579 i = nposbinvars + nnegbinvars - 1;
8580 j = i - 1;
8581
8582#ifdef SCIP_DISABLED_CODE
8583 /* assertion should only hold when constraints were fully propagated and boundstightened */
8584 /* check if the variable should not have already been fixed to one */
8585 assert(!SCIPisFeasGT(scip, binvarvals[i], threshold));
8586#endif
8587
8588 if( SCIPisFeasGT(scip, -binvarvals[i] - binvarvals[j], threshold) )
8589 {
8590 --j;
8591 /* check for extending the clique */
8592 while( j >= nposbinvars )
8593 {
8594 if( !SCIPisFeasGT(scip, -binvarvals[j+1] - binvarvals[j], threshold) )
8595 break;
8596 --j;
8597 }
8598 jstart = j;
8599
8600 assert(i - j >= 2);
8601 /* add negated clique with at least two variables */
8602 SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), values, i - j, FALSE, &infeasible, &nbdchgs) );
8603
8604 if( infeasible )
8605 *cutoff = TRUE;
8606
8607 *nchgbds += nbdchgs;
8608
8609 cliquenonzerosadded += (i - j);
8610 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8611 stopped = TRUE;
8612
8613 /* exchange the last variable in the clique if possible and add all new ones */
8614 if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8615 {
8616 SCIP_VAR** clqvars;
8617 int lastfit = j + 1;
8618 assert(lastfit < i);
8619
8620 /* copy all 'main'-clique variables */
8621 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8622 ++lastfit;
8623
8624 /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8625 while( lastfit <= i && j >= nposbinvars )
8626 {
8627 /* check if two variables are in a negated clique */
8628 if( SCIPisFeasGT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8629 {
8630 assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8631 clqvars[lastfit - jstart - 2] = binvars[j];
8632
8633 assert(i - lastfit + 2 >= 2);
8634 /* add clique with at least two variables */
8635 SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), values, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8636
8637 if( infeasible )
8638 {
8639 *cutoff = TRUE;
8640 break;
8641 }
8642
8643 *nchgbds += nbdchgs;
8644
8645 cliquenonzerosadded += (i - lastfit + 2);
8646 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8647 {
8648 stopped = TRUE;
8649 break;
8650 }
8651
8652 --j;
8653 }
8654 else
8655 ++lastfit;
8656 }
8657
8658 SCIPfreeBufferArray(scip, &clqvars);
8659 }
8660 }
8661
8662 SCIPfreeBufferArray(scip, &values);
8663 }
8664
8665 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8666 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8667 {
8668 /* check for fixed variables */
8669 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8670
8671 if( !*cutoff )
8672 {
8673 /* tighten variable's bounds */
8674 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8675
8676 if( !*cutoff )
8677 {
8678 /* check for fixed variables */
8679 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8680
8681 if( !*cutoff )
8682 {
8683 /* sort variables by variable type */
8684 SCIP_CALL( consdataSort(scip, consdata) );
8685
8686 /* recompute activities if needed */
8687 if( !consdata->validactivities )
8688 consdataCalcActivities(scip, consdata);
8689 assert(consdata->validactivities);
8690
8691 nvars = consdata->nvars;
8692 vars = consdata->vars;
8693 vals = consdata->vals;
8694 nposbinvars = 0;
8695 nnegbinvars = 0;
8696 allonebinary = 0;
8697
8698 /* update binary variables */
8699 for( i = 0; i < nvars; ++i )
8700 {
8701 if( SCIPvarIsBinary(vars[i]) )
8702 {
8703 assert(!SCIPisZero(scip, vals[i]));
8704
8705 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8706 ++allonebinary;
8707
8708 binvars[nposbinvars + nnegbinvars] = vars[i];
8709 binvarvals[nposbinvars + nnegbinvars] = vals[i];
8710
8711 if( SCIPisPositive(scip, vals[i]) )
8712 ++nposbinvars;
8713 else
8714 ++nnegbinvars;
8715
8716 assert(nposbinvars + nnegbinvars <= nvars);
8717 }
8718 /* stop searching for binary variables, because the constraint data is sorted */
8719 else if( !SCIPvarIsIntegral(vars[i]) )
8720 break;
8721 }
8722 assert(nposbinvars + nnegbinvars <= nvars);
8723 }
8724 }
8725 }
8726 }
8727
8728 /* case d) */
8729 if( !stopped && !(*cutoff) && finitelhs && finitemaxact && nposbinvars >= 2 )
8730 {
8731 SCIP_Bool* values;
8732
8733 /* initialize clique values array for adding a negated clique */
8734 SCIP_CALL( SCIPallocBufferArray(scip, &values, nposbinvars) );
8735 BMSclearMemoryArray(values, nposbinvars);
8736
8737 /* compute value that needs to be exceeded */
8738 threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
8739
8740 j = 1;
8741
8742#ifdef SCIP_DISABLED_CODE
8743 /* assertion should only hold when constraints were fully propagated and boundstightened */
8744 /* check if the variable should not have already been fixed to one */
8745 assert(!SCIPisFeasLT(scip, -binvarvals[0], threshold));
8746#endif
8747
8748 if( SCIPisFeasLT(scip, -binvarvals[0] - binvarvals[j], threshold) )
8749 {
8750 ++j;
8751 /* check for extending the clique */
8752 while( j < nposbinvars )
8753 {
8754 if( !SCIPisFeasLT(scip, -binvarvals[j-1] - binvarvals[j], threshold) )
8755 break;
8756 ++j;
8757 }
8758 assert(j >= 2);
8759
8760 /* add negated clique with at least two variables */
8761 SCIP_CALL( SCIPaddClique(scip, binvars, values, j, FALSE, &infeasible, &nbdchgs) );
8762
8763 if( infeasible )
8764 *cutoff = TRUE;
8765
8766 *nchgbds += nbdchgs;
8767
8768 cliquenonzerosadded += j;
8769 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8770 stopped = TRUE;
8771
8772 /* exchange the last variable in the clique if possible and add all new ones */
8773 if( !stopped && !(*cutoff) && j < nposbinvars )
8774 {
8775 SCIP_VAR** clqvars;
8776 int lastfit = j - 2;
8777 assert(lastfit >= 0);
8778
8779 /* copy all 'main'-clique variables */
8780 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
8781
8782 /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8783 while( lastfit >= 0 && j < nposbinvars )
8784 {
8785 /* check if two variables are in a negated clique */
8786 if( SCIPisFeasLT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8787 {
8788 clqvars[lastfit + 1] = binvars[j];
8789
8790 /* add clique with at least two variables */
8791 SCIP_CALL( SCIPaddClique(scip, clqvars, values, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8792
8793 if( infeasible )
8794 {
8795 *cutoff = TRUE;
8796 break;
8797 }
8798
8799 *nchgbds += nbdchgs;
8800
8801 cliquenonzerosadded += lastfit + 2;
8802 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8803 break;
8804
8805 ++j;
8806 }
8807 else
8808 --lastfit;
8809 }
8810
8811 SCIPfreeBufferArray(scip, &clqvars);
8812 }
8813 }
8814
8815 SCIPfreeBufferArray(scip, &values);
8816 }
8817 }
8818
8819 SCIPfreeBufferArray(scip, &binvarvals);
8820 SCIPfreeBufferArray(scip, &binvars);
8821
8822 if( *cutoff )
8823 return SCIP_OKAY;
8824 }
8825
8826 /* 2. we only check if the constraint is a set packing / partitioning constraint */
8827
8828 /* check if all variables are binary, if the coefficients are +1 or -1, and if the right hand side is equal
8829 * to 1 - number of negative coefficients, or if the left hand side is equal to number of positive coefficients - 1
8830 */
8831 nposcoefs = 0;
8832 nnegcoefs = 0;
8833 for( i = 0; i < nvars; ++i )
8834 {
8835 if( !SCIPvarIsBinary(vars[i]) )
8836 return SCIP_OKAY;
8837 else if( SCIPisEQ(scip, vals[i], +1.0) )
8838 nposcoefs++;
8839 else if( SCIPisEQ(scip, vals[i], -1.0) )
8840 nnegcoefs++;
8841 else
8842 return SCIP_OKAY;
8843 }
8844
8845 lhsclique = SCIPisEQ(scip, consdata->lhs, (SCIP_Real)nposcoefs - 1.0);
8846 rhsclique = SCIPisEQ(scip, consdata->rhs, 1.0 - (SCIP_Real)nnegcoefs);
8847
8848 if( lhsclique || rhsclique )
8849 {
8850 SCIP_Bool* values;
8851 int nbdchgs;
8852
8853 SCIPdebugMsg(scip, "linear constraint <%s>: adding clique with %d vars (%d pos, %d neg)\n",
8854 SCIPconsGetName(cons), nvars, nposcoefs, nnegcoefs);
8856
8857 for( i = 0; i < nvars; ++i )
8858 values[i] = (rhsclique == (vals[i] > 0.0));
8859
8860 SCIP_CALL( SCIPaddClique(scip, vars, values, nvars, SCIPisEQ(scip, consdata->lhs, consdata->rhs), &infeasible, &nbdchgs) );
8861
8862 if( infeasible )
8863 *cutoff = TRUE;
8864
8865 *nchgbds += nbdchgs;
8866 SCIPfreeBufferArray(scip, &values);
8867 }
8868
8869 return SCIP_OKAY;
8870}
8871
8872/** tightens left and right hand side of constraint due to integrality */
8873static
8875 SCIP* scip, /**< SCIP data structure */
8876 SCIP_CONS* cons, /**< linear constraint */
8877 int* nchgsides, /**< pointer to count number of side changes */
8878 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
8879 )
8880{
8881 SCIP_CONSDATA* consdata;
8882 SCIP_Real newlhs;
8883 SCIP_Real newrhs;
8884 SCIP_Bool chglhs;
8885 SCIP_Bool chgrhs;
8886 SCIP_Bool integral;
8887 int i;
8888
8889 assert(scip != NULL);
8890 assert(cons != NULL);
8891 assert(nchgsides != NULL);
8892 assert(infeasible != NULL);
8893
8894 consdata = SCIPconsGetData(cons);
8895 assert(consdata != NULL);
8896
8897 *infeasible = FALSE;
8898
8899 chglhs = FALSE;
8900 chgrhs = FALSE;
8901 newlhs = -SCIPinfinity(scip);
8902 newrhs = SCIPinfinity(scip);
8903
8904 if( !SCIPisIntegral(scip, consdata->lhs) || !SCIPisIntegral(scip, consdata->rhs) )
8905 {
8906 integral = TRUE;
8907 for( i = 0; i < consdata->nvars && integral; ++i )
8908 integral = SCIPvarIsIntegral(consdata->vars[i]) && SCIPisIntegral(scip, consdata->vals[i]);
8909 if( integral )
8910 {
8911 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisIntegral(scip, consdata->lhs) )
8912 {
8913 newlhs = SCIPfeasCeil(scip, consdata->lhs);
8914 chglhs = TRUE;
8915 }
8916 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisIntegral(scip, consdata->rhs) )
8917 {
8918 newrhs = SCIPfeasFloor(scip, consdata->rhs);
8919 chgrhs = TRUE;
8920 }
8921
8922 /* check whether rounding would lead to an unsatisfiable constraint */
8923 if( SCIPisGT(scip, newlhs, newrhs) )
8924 {
8925 SCIPdebugMsg(scip, "rounding sides=[%.15g,%.15g] of linear constraint <%s> with integral coefficients and variables only "
8926 "is infeasible\n", consdata->lhs, consdata->rhs, SCIPconsGetName(cons));
8927
8928 *infeasible = TRUE;
8929 return SCIP_OKAY;
8930 }
8931
8932 SCIPdebugMsg(scip, "linear constraint <%s>: make sides integral: sides=[%.15g,%.15g]\n",
8933 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
8934
8935 if( chglhs )
8936 {
8937 assert(!SCIPisInfinity(scip, -newlhs));
8938
8939 SCIP_CALL( chgLhs(scip, cons, newlhs) );
8940 if( !consdata->upgraded )
8941 (*nchgsides)++;
8942 }
8943 if( chgrhs )
8944 {
8945 assert(!SCIPisInfinity(scip, newrhs));
8946
8947 SCIP_CALL( chgRhs(scip, cons, newrhs) );
8948 if( !consdata->upgraded )
8949 (*nchgsides)++;
8950 }
8951 SCIPdebugMsg(scip, "linear constraint <%s>: new integral sides: sides=[%.15g,%.15g]\n",
8952 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
8953 }
8954 }
8955
8956 return SCIP_OKAY;
8957}
8958
8959/** tightens coefficients of binary, integer, and implied integral variables due to activity bounds in presolving:
8960 * given an inequality lhs <= a*x + ai*xi <= rhs, with a non-continuous variable li <= xi <= ui
8961 * let minact := min{a*x + ai*xi}, maxact := max{a*x + ai*xi}
8962 * (i) ai >= 0:
8963 * if minact + ai >= lhs and maxact - ai <= rhs: (**)
8964 * - a deviation from the lower/upper bound of xi would make the left/right hand side redundant
8965 * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
8966 * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
8967 * - change coefficients:
8968 * ai' := max(lhs - minact, maxact - rhs, 0)
8969 * lhs' := lhs - (ai - ai')*li
8970 * rhs' := rhs - (ai - ai')*ui
8971 * (ii) ai < 0:
8972 * if minact - ai >= lhs and maxact + ai <= rhs: (***)
8973 * - a deviation from the upper/lower bound of xi would make the left/right hand side redundant
8974 * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
8975 * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
8976 * - change coefficients:
8977 * ai' := min(rhs - maxact, minact - lhs, 0)
8978 * lhs' := lhs - (ai - ai')*ui
8979 * rhs' := rhs - (ai - ai')*li
8980 *
8981 * We further try to remove variables from the constraint;
8982 * Variables which fulfill conditions (**) or (***) are called relevant variables.
8983 * A deviation of only one from their bound makes the lhs/rhs feasible (i.e., redundant), even if all other
8984 * variables are set to their "worst" bound. If all variables which are not relevant cannot make the lhs/rhs
8985 * redundant, even if they are set to their "best" bound, they can be removed from the constraint. E.g., for binary
8986 * 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
8987 * inequality, whereas the x_i do not contribute to feasibility and can be removed.
8988 *
8989 * @todo use also some tightening procedures for (knapsack) constraints with non-integer coefficients, see
8990 * cons_knapsack.c the following methods detectRedundantVars() and tightenWeights()
8991 */
8992static
8994 SCIP* scip, /**< SCIP data structure */
8995 SCIP_CONS* cons, /**< linear constraint */
8996 int* nchgcoefs, /**< pointer to count total number of changed coefficients */
8997 int* nchgsides /**< pointer to count number of side changes */
8998 )
8999{
9000 SCIP_CONSDATA* consdata;
9001 SCIP_VAR* var;
9002 SCIP_Bool* isvarrelevant;
9003 SCIP_Real minactivity; /* minimal value w.r.t. the variable's local bounds for the constraint's
9004 * activity, ignoring the coefficients contributing with infinite value */
9005 SCIP_Real maxactivity; /* maximal value w.r.t. the variable's local bounds for the constraint's
9006 * activity, ignoring the coefficients contributing with infinite value */
9007 SCIP_Bool isminacttight; /* are all contributions to the minactivity non-huge or non-contradicting? */
9008 SCIP_Bool ismaxacttight; /* are all contributions to the maxactivity non-huge or non-contradicting? */
9009 SCIP_Bool isminsettoinfinity;
9010 SCIP_Bool ismaxsettoinfinity;
9011 SCIP_Real minleftactivity; /* minimal activity without relevant variables */
9012 SCIP_Real maxleftactivity; /* maximal activity without relevant variables */
9013 SCIP_Real aggrlhs; /* lhs without minimal activity of relevant variables */
9014 SCIP_Real aggrrhs; /* rhs without maximal activity of relevant variables */
9015 SCIP_Real lval; /* candidate for new value arising from considering the left hand side */
9016 SCIP_Real rval; /* candidate for new value arising from considering the left hand side */
9017 SCIP_Real val;
9018 SCIP_Real newval;
9019 SCIP_Real newlhs;
9020 SCIP_Real newrhs;
9021 SCIP_Real lb;
9022 SCIP_Real ub;
9023 int i;
9024
9025 assert(scip != NULL);
9026 assert(cons != NULL);
9027 assert(nchgcoefs != NULL);
9028 assert(nchgsides != NULL);
9029
9030 consdata = SCIPconsGetData(cons);
9031 assert(consdata != NULL);
9032
9033 /* allocate relevance flags */
9034 SCIP_CALL( SCIPallocBufferArray(scip, &isvarrelevant, consdata->nvars) );
9035
9036 /* get the minimal and maximal activity of the constraint */
9037 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
9038 &isminsettoinfinity, &ismaxsettoinfinity);
9039 assert(( isminsettoinfinity && !SCIPisInfinity(scip, -consdata->lhs) )
9040 || SCIPisLT(scip, minactivity, consdata->lhs)
9041 || ( ismaxsettoinfinity && !SCIPisInfinity(scip, consdata->rhs) )
9042 || SCIPisGT(scip, maxactivity, consdata->rhs));
9043
9044 minleftactivity = 0.0;
9045 maxleftactivity = 0.0;
9046
9047 /* try to tighten each coefficient */
9048 i = 0;
9049 while( i < consdata->nvars )
9050 {
9051 /* get coefficient and variable's bounds */
9052 var = consdata->vars[i];
9053 val = consdata->vals[i];
9054 assert(!SCIPisZero(scip, val));
9055 lb = SCIPvarGetLbLocal(var);
9056 ub = SCIPvarGetUbLocal(var);
9057
9058 /* check sign of coefficient */
9059 if( val >= 0.0 )
9060 {
9061 /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9062 isvarrelevant[i] = SCIPvarIsIntegral(var)
9063 && SCIPisGE(scip, minactivity + val, consdata->lhs) && SCIPisLE(scip, maxactivity - val, consdata->rhs);
9064
9065 if( isvarrelevant[i] )
9066 {
9067 /* change coefficients:
9068 * ai' := max(lhs - minact, maxact - rhs)
9069 * lhs' := lhs - (ai - ai')*li
9070 * rhs' := rhs - (ai - ai')*ui
9071 */
9072
9073 lval = consdata->lhs - minactivity;
9074 rval = maxactivity - consdata->rhs;
9075
9076 /* Try to avoid cancellation, if there are only two variables */
9077 if( consdata->nvars == 2 )
9078 {
9079 SCIP_Real otherval;
9080 otherval = consdata->vals[1-i];
9081
9082 if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9083 {
9084 lval = consdata->lhs - val*lb;
9085 lval -= otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9086 }
9087
9088 if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9089 {
9090 rval = val*ub - consdata->rhs;
9091 rval += otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9092 }
9093 }
9094
9095 newval = MAX3(lval, rval, 0.0);
9096 assert(SCIPisSumRelLE(scip, newval, val));
9097
9098 /* Try to avoid cancellation in computation of lhs/rhs */
9099 newlhs = consdata->lhs - val * lb;
9100 newlhs += newval * lb;
9101 newrhs = consdata->rhs - val * ub;
9102 newrhs += newval * ub;
9103
9104 if( !SCIPisSumRelEQ(scip, newval, val) )
9105 {
9106 SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9107 SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var), minactivity,
9108 maxactivity, consdata->lhs, consdata->rhs);
9109
9110 /* update the coefficient and the activity bounds */
9111 if( SCIPisZero(scip, newval) )
9112 {
9113 SCIP_CALL( delCoefPos(scip, cons, i) );
9114 --i;
9115 }
9116 else
9117 {
9118 SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9119 }
9120 ++(*nchgcoefs);
9121
9122 /* get the new minimal and maximal activity of the constraint */
9123 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight,
9124 &ismaxacttight, &isminsettoinfinity, &ismaxsettoinfinity);
9125
9126 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9127 {
9128 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons),
9129 consdata->lhs, newlhs);
9130
9131 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9132 (*nchgsides)++;
9133 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9134 }
9135
9136 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9137 {
9138 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons),
9139 consdata->rhs, newrhs);
9140
9141 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9142 (*nchgsides)++;
9143 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9144 }
9145 }
9146 }
9147 else
9148 {
9149 if( !SCIPisInfinity(scip, -minleftactivity) )
9150 {
9151 assert(!SCIPisInfinity(scip, val));
9152 assert(!SCIPisInfinity(scip, lb));
9153 if( SCIPisInfinity(scip, -lb) )
9154 minleftactivity = -SCIPinfinity(scip);
9155 else
9156 minleftactivity += val * lb;
9157 }
9158
9159 if( !SCIPisInfinity(scip, maxleftactivity) )
9160 {
9161 assert(!SCIPisInfinity(scip, val));
9162 assert(!SCIPisInfinity(scip, -ub));
9163 if( SCIPisInfinity(scip,ub) )
9164 maxleftactivity = SCIPinfinity(scip);
9165 else
9166 maxleftactivity += val * ub;
9167 }
9168 }
9169 }
9170 else
9171 {
9172 /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9173 isvarrelevant[i] = SCIPvarIsIntegral(var)
9174 && SCIPisGE(scip, minactivity - val, consdata->lhs) && SCIPisLE(scip, maxactivity + val, consdata->rhs);
9175
9176 if( isvarrelevant[i] )
9177 {
9178 /* change coefficients:
9179 * ai' := min(rhs - maxact, minact - lhs)
9180 * lhs' := lhs - (ai - ai')*ui
9181 * rhs' := rhs - (ai - ai')*li
9182 */
9183
9184 lval = minactivity - consdata->lhs;
9185 rval = consdata->rhs - maxactivity;
9186
9187 /* Try to avoid cancellation, if there are only two variables */
9188 if( consdata->nvars == 2 )
9189 {
9190 SCIP_Real otherval;
9191 otherval = consdata->vals[1-i];
9192
9193 if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9194 {
9195 lval = val*ub - consdata->lhs;
9196 lval += otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9197 }
9198
9199 if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9200 {
9201 rval = consdata->rhs - val*lb;
9202 rval -= otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9203 }
9204 }
9205
9206 newval = MIN3(lval, rval, 0.0);
9207 assert(SCIPisSumRelGE(scip, newval, val));
9208
9209 /* Try to avoid cancellation in computation of lhs/rhs */
9210 newlhs = consdata->lhs - val * ub;
9211 newlhs += newval * ub;
9212 newrhs = consdata->rhs - val * lb;
9213 newrhs += newval * lb;
9214
9215 if( !SCIPisSumRelEQ(scip, newval, val) )
9216 {
9217 SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9218 SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var), minactivity,
9219 maxactivity, consdata->lhs, consdata->rhs);
9220
9221 /* update the coefficient and the activity bounds */
9222 if( SCIPisZero(scip, newval) )
9223 {
9224 SCIP_CALL( delCoefPos(scip, cons, i) );
9225 --i;
9226 }
9227 else
9228 {
9229 SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9230 }
9231 ++(*nchgcoefs);
9232
9233 /* get the new minimal and maximal activity of the constraint */
9234 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight,
9235 &ismaxacttight, &isminsettoinfinity, &ismaxsettoinfinity);
9236
9237 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9238 {
9239 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons),
9240 consdata->lhs, newlhs);
9241
9242 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9243 (*nchgsides)++;
9244 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9245 }
9246
9247 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9248 {
9249 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons),
9250 consdata->rhs, newrhs);
9251
9252 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9253 (*nchgsides)++;
9254 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9255 }
9256 }
9257 }
9258 else
9259 {
9260 if( !SCIPisInfinity(scip, -minleftactivity) )
9261 {
9262 assert(!SCIPisInfinity(scip, -val));
9263 assert(!SCIPisInfinity(scip, -ub));
9264 if( SCIPisInfinity(scip, ub) )
9265 minleftactivity = -SCIPinfinity(scip);
9266 else
9267 minleftactivity += val * ub;
9268 }
9269
9270 if( !SCIPisInfinity(scip, maxleftactivity) )
9271 {
9272 assert(!SCIPisInfinity(scip, -val));
9273 assert(!SCIPisInfinity(scip, lb));
9274 if( SCIPisInfinity(scip, -lb) )
9275 maxleftactivity = SCIPinfinity(scip);
9276 else
9277 maxleftactivity += val * lb;
9278 }
9279 }
9280 }
9281
9282 ++i;
9283 }
9284
9285 SCIPdebugMsg(scip, "minleftactivity = %.15g, rhs = %.15g\n",
9286 minleftactivity, consdata->rhs);
9287 SCIPdebugMsg(scip, "maxleftactivity = %.15g, lhs = %.15g\n",
9288 maxleftactivity, consdata->lhs);
9289
9290 /* minleft == \infty ==> minactivity == \infty */
9291 assert(!SCIPisInfinity(scip, -minleftactivity) || SCIPisInfinity(scip, -minactivity));
9292 assert(!SCIPisInfinity(scip, maxleftactivity) || SCIPisInfinity(scip, maxactivity));
9293
9294 /* if the lhs is finite, we will check in the following whether the not relevant variables can make lhs feasible;
9295 * this is not valid, if the minactivity is -\infty (aggrlhs would be minus infinity in the following computation)
9296 * or if huge values contributed to the minactivity, because the minactivity is then just a relaxation
9297 * (<= the exact minactivity), and we might falsely remove coefficients in the following
9298 */
9299 assert(!SCIPisInfinity(scip, minactivity));
9300 if( !SCIPisInfinity(scip, -consdata->lhs) && (SCIPisInfinity(scip, -minactivity) || !isminacttight) )
9301 goto TERMINATE;
9302
9303 /* if the rhs is finite, we will check in the following whether the not relevant variables can make rhs feasible;
9304 * this is not valid, if the maxactivity is \infty (aggrrhs would be infinity in the following computation)
9305 * or if huge values contributed to the maxactivity, because the maxactivity is then just a relaxation
9306 * (>= the exact maxactivity), and we might falsely remove coefficients in the following
9307 */
9308 assert(!SCIPisInfinity(scip, -maxactivity));
9309 if( !SCIPisInfinity(scip, consdata->rhs) && (SCIPisInfinity(scip, maxactivity) || !ismaxacttight) )
9310 goto TERMINATE;
9311
9312 /* correct lhs and rhs by min/max activity of relevant variables
9313 * relevant variables are all those where a deviation from the bound makes the lhs/rhs redundant
9314 */
9315 aggrlhs = consdata->lhs - minactivity + minleftactivity;
9316 aggrrhs = consdata->rhs - maxactivity + maxleftactivity;
9317
9318 /* check if the constraint contains variables whose coefficient can be removed. The reasoning is the following:
9319 * Each relevant variable can make the lhs/rhs feasible with a deviation of only one in the bound. If _all_ not
9320 * relevant variables together cannot make lhs/rhs redundant, they can be removed from the constraint. aggrrhs may
9321 * contain some near-infinity value, but only if rhs is infinity.
9322 */
9323 if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasLT(scip, maxleftactivity, aggrlhs))
9324 && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasGT(scip, minleftactivity, aggrrhs)) )
9325 {
9326 SCIP_Real minleftactivitypart;
9327 SCIP_Real maxleftactivitypart;
9328
9329 assert(!SCIPisInfinity(scip, -consdata->lhs) || !SCIPisInfinity(scip, consdata->rhs));
9330
9331 /* remove redundant variables from constraint */
9332 i = 0;
9333 while( i < consdata->nvars )
9334 {
9335 /* consider redundant variable */
9336 if( !isvarrelevant[i] )
9337 {
9338 /* get coefficient and variable's bounds */
9339 var = consdata->vars[i];
9340 val = consdata->vals[i];
9341 assert(!SCIPisZero(scip, val));
9342 lb = SCIPvarGetLbLocal(var);
9343 ub = SCIPvarGetUbLocal(var);
9344
9345 SCIPdebugMsg(scip, "val = %g\tlhs = %g\trhs = %g\n", val, consdata->lhs, consdata->rhs);
9346 SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> from constraint since it is redundant\n",
9347 SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]));
9348
9349 /* check sign of coefficient */
9350 if( val >= 0.0 )
9351 {
9352 minleftactivitypart = val * lb;
9353 maxleftactivitypart = val * ub;
9354 }
9355 else
9356 {
9357 minleftactivitypart = val * ub;
9358 maxleftactivitypart = val * lb;
9359 }
9360
9361 /* remove redundant variable */
9362 isvarrelevant[i] = isvarrelevant[consdata->nvars - 1];
9363 SCIP_CALL( delCoefPos(scip, cons, i) );
9364 --i;
9365
9366 /* adjust lhs and right hand side */
9367 newlhs = consdata->lhs - minleftactivitypart;
9368 newrhs = consdata->rhs - maxleftactivitypart;
9369
9370 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9371 {
9372 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons),
9373 consdata->lhs, newlhs);
9374
9375 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9376 ++(*nchgsides);
9377 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9378 }
9379
9380 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9381 {
9382 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons),
9383 consdata->rhs, newrhs);
9384
9385 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9386 ++(*nchgsides);
9387 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9388 }
9389 }
9390
9391 ++i;
9392 }
9393 }
9394
9395TERMINATE:
9396 /* free relevance flags */
9397 SCIPfreeBufferArray(scip, &isvarrelevant);
9398
9399 return SCIP_OKAY;
9400}
9401
9402/** processes equality with only one variable by fixing the variable and deleting the constraint */
9403static
9405 SCIP* scip, /**< SCIP data structure */
9406 SCIP_CONS* cons, /**< linear constraint */
9407 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9408 int* nfixedvars, /**< pointer to count number of fixed variables */
9409 int* ndelconss /**< pointer to count number of deleted constraints */
9410 )
9411{
9412 SCIP_CONSDATA* consdata;
9413 SCIP_VAR* var;
9414 SCIP_Real val;
9415 SCIP_Real fixval;
9416 SCIP_Bool infeasible;
9417 SCIP_Bool fixed;
9418
9419 assert(scip != NULL);
9420 assert(cons != NULL);
9421 assert(cutoff != NULL);
9422 assert(nfixedvars != NULL);
9423 assert(ndelconss != NULL);
9424
9425 consdata = SCIPconsGetData(cons);
9426 assert(consdata != NULL);
9427 assert(consdata->nvars == 1);
9428 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9429
9430 /* calculate the value to fix the variable to */
9431 var = consdata->vars[0];
9432 val = consdata->vals[0];
9433 assert(!SCIPisZero(scip, val));
9434 fixval = SCIPselectSimpleValue(consdata->lhs/val - 0.9 * SCIPepsilon(scip),
9435 consdata->rhs/val + 0.9 * SCIPepsilon(scip), MAXDNOM);
9436 SCIPdebugMsg(scip, "linear equality <%s>: fix <%s> == %.15g\n",
9437 SCIPconsGetName(cons), SCIPvarGetName(var), fixval);
9438
9439 /* fix variable */
9440 SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
9441 if( infeasible )
9442 {
9443 SCIPdebugMsg(scip, " -> infeasible fixing\n");
9444 *cutoff = TRUE;
9445 return SCIP_OKAY;
9446 }
9447 if( fixed )
9448 (*nfixedvars)++;
9449
9450 /* disable constraint */
9451 SCIP_CALL( SCIPdelCons(scip, cons) );
9452 if( !consdata->upgraded )
9453 (*ndelconss)++;
9454
9455 return SCIP_OKAY;
9456}
9457
9458/** processes equality with exactly two variables by aggregating one of the variables and deleting the constraint */
9459static
9461 SCIP* scip, /**< SCIP data structure */
9462 SCIP_CONS* cons, /**< linear constraint */
9463 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9464 int* naggrvars, /**< pointer to count number of aggregated variables */
9465 int* ndelconss /**< pointer to count number of deleted constraints */
9466 )
9467{
9468 SCIP_CONSDATA* consdata;
9469 SCIP_Bool infeasible;
9470 SCIP_Bool redundant;
9471 SCIP_Bool aggregated;
9472
9473 assert(scip != NULL);
9474 assert(cons != NULL);
9475 assert(cutoff != NULL);
9476 assert(naggrvars != NULL);
9477 assert(ndelconss != NULL);
9478
9479 consdata = SCIPconsGetData(cons);
9480 assert(consdata != NULL);
9481 assert(consdata->nvars == 2);
9482 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9483
9484 SCIPdebugMsg(scip, "linear constraint <%s>: aggregate %.15g<%s> + %.15g<%s> == %.15g\n",
9485 SCIPconsGetName(cons), consdata->vals[0], SCIPvarGetName(consdata->vars[0]),
9486 consdata->vals[1], SCIPvarGetName(consdata->vars[1]), consdata->rhs);
9487
9488 /* aggregate the equality */
9489 SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], consdata->vals[0], consdata->vals[1],
9490 consdata->rhs, &infeasible, &redundant, &aggregated) );
9491
9492 /* check for infeasibility of aggregation */
9493 if( infeasible )
9494 {
9495 SCIPdebugMsg(scip, " -> infeasible aggregation\n");
9496 *cutoff = TRUE;
9497 return SCIP_OKAY;
9498 }
9499
9500 /* count the aggregation */
9501 if( aggregated )
9502 (*naggrvars)++;
9503
9504 /* delete the constraint, if it is redundant */
9505 if( redundant )
9506 {
9507 SCIP_CALL( SCIPdelCons(scip, cons) );
9508
9509 if( !consdata->upgraded )
9510 (*ndelconss)++;
9511 }
9512
9513 return SCIP_OKAY;
9514}
9515
9516/** calculates the new lhs and rhs of the constraint after the given variable is aggregated out */
9517static
9519 SCIP* scip, /**< SCIP data structure */
9520 SCIP_CONSDATA* consdata, /**< linear constraint data */
9521 SCIP_VAR* slackvar, /**< variable to be aggregated out */
9522 SCIP_Real slackcoef, /**< coefficient of variable in constraint */
9523 SCIP_Real* newlhs, /**< pointer to store new lhs of constraint */
9524 SCIP_Real* newrhs /**< pointer to store new rhs of constraint */
9525 )
9526{
9527 SCIP_Real slackvarlb;
9528 SCIP_Real slackvarub;
9529
9530 assert(scip != NULL);
9531 assert(consdata != NULL);
9532 assert(newlhs != NULL);
9533 assert(newrhs != NULL);
9534 assert(!SCIPisInfinity(scip, -consdata->lhs));
9535 assert(!SCIPisInfinity(scip, consdata->rhs));
9536
9537 slackvarlb = SCIPvarGetLbGlobal(slackvar);
9538 slackvarub = SCIPvarGetUbGlobal(slackvar);
9539 if( slackcoef > 0.0 )
9540 {
9541 if( SCIPisInfinity(scip, -slackvarlb) )
9542 *newrhs = SCIPinfinity(scip);
9543 else
9544 *newrhs = consdata->rhs - slackcoef * slackvarlb;
9545 if( SCIPisInfinity(scip, slackvarub) )
9546 *newlhs = -SCIPinfinity(scip);
9547 else
9548 *newlhs = consdata->lhs - slackcoef * slackvarub;
9549 }
9550 else
9551 {
9552 if( SCIPisInfinity(scip, -slackvarlb) )
9553 *newlhs = -SCIPinfinity(scip);
9554 else
9555 *newlhs = consdata->rhs - slackcoef * slackvarlb;
9556 if( SCIPisInfinity(scip, slackvarub) )
9557 *newrhs = SCIPinfinity(scip);
9558 else
9559 *newrhs = consdata->lhs - slackcoef * slackvarub;
9560 }
9561 assert(SCIPisLE(scip, *newlhs, *newrhs));
9562}
9563
9564/** processes equality with more than two variables by multi-aggregating one of the variables and converting the equality
9565 * into an inequality; if multi-aggregation is not possible, tries to identify one continuous or integer variable that
9566 * is implied integral by this constraint
9567 *
9568 * @todo Check whether a more clever way of avoiding aggregation of variables containing implied integral variables
9569 * can help.
9570 */
9571static
9573 SCIP* scip, /**< SCIP data structure */
9574 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
9575 SCIP_CONS* cons, /**< linear constraint */
9576 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9577 int* naggrvars, /**< pointer to count number of aggregated variables */
9578 int* ndelconss, /**< pointer to count number of deleted constraints */
9579 int* nchgvartypes /**< pointer to count number of changed variable types */
9580 )
9581{
9582 SCIP_CONSDATA* consdata;
9583 SCIP_VAR** vars;
9584 SCIP_Real* vals;
9585 SCIP_VARTYPE bestslacktype;
9586 SCIP_VARTYPE slacktype;
9587 SCIP_IMPLINTTYPE impltype;
9588 SCIP_Real lhs;
9589 SCIP_Real rhs;
9590 SCIP_Real bestslackdomrng;
9591 SCIP_Real minabsval;
9592 SCIP_Real maxabsval;
9593 SCIP_Bool bestremovescons;
9594 SCIP_Bool coefszeroone;
9595 SCIP_Bool coefsintegral;
9596 SCIP_Bool varsintegral;
9597 SCIP_Bool infeasible;
9598 int maxnlocksstay;
9599 int maxnlocksremove;
9600 int bestslackpos;
9601 int bestnlocks;
9602 int ncontvars;
9603 int contvarpos;
9604 int nintvars;
9605 int nweakimplvars;
9606 int nimplvars;
9607 int intvarpos;
9608 int v;
9609
9610 assert(scip != NULL);
9611 assert(cons != NULL);
9612 assert(cutoff != NULL);
9613 assert(naggrvars != NULL);
9614
9615 consdata = SCIPconsGetData(cons);
9616 assert(consdata != NULL);
9617 assert(consdata->nvars > 2);
9618 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9619
9620 SCIPdebugMsg(scip, "linear constraint <%s>: try to multi-aggregate equality\n", SCIPconsGetName(cons));
9621
9622 /* We do not want to increase the total number of non-zeros due to the multi-aggregation.
9623 * Therefore, we have to restrict the number of locks of a variable that is aggregated out.
9624 * maxnlocksstay: maximal sum of lock numbers if the constraint does not become redundant after the aggregation
9625 * maxnlocksremove: maximal sum of lock numbers if the constraint can be deleted after the aggregation
9626 */
9627 lhs = consdata->lhs;
9628 rhs = consdata->rhs;
9629 maxnlocksstay = 0;
9630 if( consdata->nvars == 3 )
9631 {
9632 /* If the constraint becomes redundant, 3 non-zeros are removed, and we get 1 additional non-zero for each
9633 * constraint the variable appears in. Thus, the variable must appear in at most 3 other constraints.
9634 */
9635 maxnlocksremove = 3;
9636 }
9637 else if( consdata->nvars == 4 )
9638 {
9639 /* If the constraint becomes redundant, 4 non-zeros are removed, and we get 2 additional non-zeros for each
9640 * constraint the variable appears in. Thus, the variable must appear in at most 2 other constraints.
9641 */
9642 maxnlocksremove = 2;
9643 }
9644 else
9645 {
9646 /* If the constraint is redundant but has more than 4 variables, we can only accept one other constraint. */
9647 maxnlocksremove = 1;
9648 }
9649
9650 /* the locks on this constraint can be ignored */
9651 if( SCIPconsIsChecked(cons) )
9652 {
9653 if( !SCIPisInfinity(scip, -lhs) )
9654 {
9655 maxnlocksstay++;
9656 maxnlocksremove++;
9657 }
9658 if( !SCIPisInfinity(scip, rhs) )
9659 {
9660 maxnlocksstay++;
9661 maxnlocksremove++;
9662 }
9663 }
9664
9665 /* look for a slack variable s to convert a*x + s == b into lhs <= a*x <= rhs */
9666 vars = consdata->vars;
9667 vals = consdata->vals;
9668 bestslackpos = -1;
9669 bestslacktype = SCIP_VARTYPE_BINARY;
9670 bestnlocks = INT_MAX;
9671 bestremovescons = FALSE;
9672 bestslackdomrng = 0.0;
9673 coefszeroone = TRUE;
9674 coefsintegral = TRUE;
9675 varsintegral = TRUE;
9676 ncontvars = 0;
9677 contvarpos = -1;
9678 nintvars = 0;
9679 nweakimplvars = 0;
9680 nimplvars = 0;
9681 intvarpos = -1;
9682 minabsval = SCIPinfinity(scip);
9683 maxabsval = -1.0;
9684 for( v = 0; v < consdata->nvars; ++v )
9685 {
9686 SCIP_VAR* var;
9687 SCIP_Real val;
9688 SCIP_Real absval;
9689 SCIP_Real varlb;
9690 SCIP_Real varub;
9691 SCIP_Bool iscont;
9692 int nlocks;
9693
9694 assert(vars != NULL);
9695 assert(vals != NULL);
9696
9697 var = vars[v];
9698 assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= 1); /* because variable is locked in this equality */
9700 varlb = SCIPvarGetLbGlobal(var);
9701 varub = SCIPvarGetUbGlobal(var);
9702
9703 val = vals[v];
9704 absval = REALABS(val);
9705 assert(SCIPisPositive(scip, absval));
9706
9707 /* calculate minimal and maximal absolute value */
9708 if( absval < minabsval )
9709 minabsval = absval;
9710 if( absval > maxabsval )
9711 maxabsval = absval;
9712
9713 /** @todo Do not exit here, but continue if we may still detect implied integrality. */
9714 /* do not try to multi aggregate, when numerical bad */
9715 if( maxabsval / minabsval > conshdlrdata->maxmultaggrquot )
9716 return SCIP_OKAY;
9717
9718 impltype = SCIPvarGetImplType(var);
9720 coefszeroone = coefszeroone && SCIPisEQ(scip, absval, 1.0);
9721 coefsintegral = coefsintegral && SCIPisIntegral(scip, val);
9722 varsintegral = varsintegral && (slacktype != SCIP_VARTYPE_CONTINUOUS);
9723 iscont = (slacktype == SCIP_VARTYPE_CONTINUOUS || slacktype == SCIP_DEPRECATED_VARTYPE_IMPLINT);
9724
9725 /* update candidates for continuous -> implint and integer -> implint conversion */
9726 if( slacktype == SCIP_VARTYPE_CONTINUOUS )
9727 {
9728 ncontvars++;
9729 contvarpos = v;
9730 }
9731 else if( slacktype == SCIP_DEPRECATED_VARTYPE_IMPLINT )
9732 {
9733 ++nimplvars;
9734 assert(impltype != SCIP_IMPLINTTYPE_NONE);
9735 if( impltype == SCIP_IMPLINTTYPE_WEAK )
9736 ++nweakimplvars;
9737 }
9738 else if( slacktype == SCIP_VARTYPE_INTEGER )
9739 {
9740 nintvars++;
9741 intvarpos = v;
9742 }
9743
9744 /* check, if variable is already fixed or aggregated */
9745 if( !SCIPvarIsActive(var) )
9746 continue;
9747
9748 /* check, if variable is used in too many other constraints, even if this constraint could be deleted */
9750
9751 if( nlocks > maxnlocksremove )
9752 continue;
9753
9754 /* check, if variable can be used as a slack variable */
9755 if( (iscont || (coefsintegral && varsintegral && SCIPisEQ(scip, absval, 1.0))) &&
9757 {
9758 SCIP_Bool better;
9759 SCIP_Bool equal;
9760 SCIP_Real slackdomrng;
9761
9762 if( SCIPisInfinity(scip, varub) || SCIPisInfinity(scip, -varlb) )
9763 slackdomrng = SCIPinfinity(scip);
9764 /* we do not want to perform multi-aggregation due to numerics, if the bounds are huge */
9765 else if( SCIPisHugeValue(scip, varub) || SCIPisHugeValue(scip, -varlb) )
9766 return SCIP_OKAY;
9767 else
9768 {
9769 slackdomrng = (varub - varlb)*absval;
9770 assert(!SCIPisInfinity(scip, slackdomrng));
9771 }
9772 equal = FALSE;
9773
9774 /* continuous > implied > integer > binary */
9775 better = (slacktype > bestslacktype) || (bestslackpos == -1);
9776 if( !better && slacktype == bestslacktype )
9777 {
9778 better = (nlocks < bestnlocks);
9779 if( nlocks == bestnlocks && !bestremovescons )
9780 {
9781 better = SCIPisGT(scip, slackdomrng, bestslackdomrng);
9782 equal = !better && SCIPisGE(scip, slackdomrng, bestslackdomrng);
9783 }
9784 }
9785
9786 if( better || equal )
9787 {
9788 SCIP_Real minresactivity;
9789 SCIP_Real maxresactivity;
9790 SCIP_Real newlhs;
9791 SCIP_Real newrhs;
9792 SCIP_Bool removescons;
9793 SCIP_Bool ismintight;
9794 SCIP_Bool ismaxtight;
9795 SCIP_Bool isminsettoinfinity;
9796 SCIP_Bool ismaxsettoinfinity;
9797
9798 /* check if the constraint becomes redundant after multi-aggregation */
9799 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
9800 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
9801
9802 /* do not perform the multi-aggregation due to numerics, if we have huge contributions in the residual
9803 * activity
9804 */
9805 if( !ismintight || !ismaxtight )
9806 continue;
9807
9808 getNewSidesAfterAggregation(scip, consdata, var, val, &newlhs, &newrhs);
9809 removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9810
9811 /* check resactivities for reliability */
9812 if( removescons )
9813 {
9814 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
9815 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
9816
9817 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity)
9818 && SCIPisFeasLE(scip, newlhs, minresactivity))
9819 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
9820
9821 removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9822 }
9823
9824 /* if parameter multaggrremove is set to TRUE, only aggregate when this removes constraint */
9825 if( conshdlrdata->multaggrremove && !removescons )
9826 continue;
9827
9828 /* if the constraint does not become redundant, only accept the variable if it does not appear in
9829 * other constraints
9830 */
9831 if( !removescons && nlocks > maxnlocksstay )
9832 continue;
9833
9834 /* prefer variables that make the constraints redundant
9835 * unless there is a continuous better slack
9836 */
9837 if( !bestremovescons && removescons )
9838 better = TRUE;
9839 else if( bestremovescons && !removescons && (bestslacktype > SCIP_VARTYPE_INTEGER || slacktype <= SCIP_VARTYPE_INTEGER) )
9840 better = FALSE;
9841 if( better )
9842 {
9843 bestslackpos = v;
9844 bestslacktype = slacktype;
9845 bestnlocks = nlocks;
9846 bestslackdomrng = slackdomrng;
9847 bestremovescons = removescons;
9848 }
9849 }
9850 }
9851 }
9852
9853 /* if all coefficients and variables are integral, the right hand side must also be integral */
9854 if( coefsintegral && varsintegral && !SCIPisFeasIntegral(scip, consdata->rhs) )
9855 {
9856 SCIPdebugMsg(scip, "linear equality <%s> is integer infeasible\n", SCIPconsGetName(cons));
9858 *cutoff = TRUE;
9859 return SCIP_OKAY;
9860 }
9861
9862 /* if the slack variable is of integer type, and the constraint itself may take fractional values,
9863 * we cannot aggregate the variable, because the integrality condition would get lost
9864 * Similarly, if there are implied integral variables, we cannot aggregate since we might
9865 * loose the integrality condition for this variable.
9866 */
9867 if( bestslackpos >= 0
9868 && (bestslacktype == SCIP_VARTYPE_CONTINUOUS || bestslacktype == SCIP_DEPRECATED_VARTYPE_IMPLINT
9869 || (coefsintegral && varsintegral && nimplvars == 0)) )
9870 {
9871 SCIP_VAR** aggrvars;
9872 SCIP_VAR* slackvar;
9874 SCIP_Real slackcoef;
9875 SCIP_Real aggrconst;
9876 SCIP_Real newlhs;
9877 SCIP_Real newrhs;
9878 SCIP_Bool aggregated;
9879
9880 /* we found a slack variable that only occurs in at most one other constraint:
9881 * a_1*x_1 + ... + a_k*x_k + a'*s == rhs -> s == rhs - a_1/a'*x_1 - ... - a_k/a'*x_k
9882 */
9883 assert(bestslackpos < consdata->nvars);
9884
9885 /* do not multi aggregate binary variables */
9886 if( SCIPvarIsBinary(vars[bestslackpos]) )
9887 return SCIP_OKAY;
9888
9889 /* convert equality into inequality by deleting the slack variable:
9890 * x + a*s == b, l <= s <= u -> b - a*u <= x <= b - a*l
9891 */
9892 slackvar = vars[bestslackpos];
9893 slackcoef = vals[bestslackpos];
9894 assert(!SCIPisZero(scip, slackcoef));
9895 aggrconst = consdata->rhs/slackcoef;
9896
9897 /* allocate temporary memory */
9898 SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars - 1) );
9899 SCIP_CALL( SCIPallocBufferArray(scip, &scalars, consdata->nvars - 1) );
9900
9901 /* set up the multi-aggregation */
9902 SCIPdebugMsg(scip, "linear constraint <%s>: multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(slackvar));
9903 for( v = 0; v < consdata->nvars - 1; ++v )
9904 {
9905 if( v == bestslackpos )
9906 {
9907 aggrvars[v] = vars[consdata->nvars - 1];
9908 scalars[v] = -consdata->vals[consdata->nvars - 1] / slackcoef;
9909 }
9910 else
9911 {
9912 aggrvars[v] = vars[v];
9913 scalars[v] = -consdata->vals[v] / slackcoef;
9914 }
9915 SCIPdebugMsgPrint(scip, " %+.15g<%s>", scalars[v], SCIPvarGetName(aggrvars[v]));
9916 }
9917 SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g], nlocks=%d, maxnlocks=%d, removescons=%u\n",
9918 aggrconst, SCIPvarGetName(slackvar), SCIPvarGetLbGlobal(slackvar), SCIPvarGetUbGlobal(slackvar),
9919 bestnlocks, bestremovescons ? maxnlocksremove : maxnlocksstay, bestremovescons);
9920
9921 /* perform the multi-aggregation */
9922 SCIP_CALL( SCIPmultiaggregateVar(scip, slackvar, consdata->nvars - 1, aggrvars, scalars, aggrconst,
9923 &infeasible, &aggregated) );
9924
9925 /* free temporary memory */
9927 SCIPfreeBufferArray(scip, &aggrvars);
9928
9929 /* check for infeasible aggregation */
9930 if( infeasible )
9931 {
9932 SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
9933 *cutoff = TRUE;
9934 return SCIP_OKAY;
9935 }
9936
9937 /* check for applied aggregation */
9938 if( !aggregated )
9939 {
9940 SCIPdebugMsg(scip, "linear constraint <%s>: multi-aggregation not applicable\n", SCIPconsGetName(cons));
9941 return SCIP_OKAY;
9942 }
9943
9944 ++(*naggrvars);
9945
9946 getNewSidesAfterAggregation(scip, consdata, slackvar, slackcoef, &newlhs, &newrhs);
9947 assert(SCIPisLE(scip, newlhs, newrhs));
9948 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9949 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9950 SCIP_CALL( delCoefPos(scip, cons, bestslackpos) );
9951
9952 /* delete the constraint if it became redundant */
9953 if( bestremovescons )
9954 {
9955 SCIPdebugMsg(scip, "linear constraint <%s>: redundant after multi-aggregation\n", SCIPconsGetName(cons));
9956 SCIP_CALL( SCIPdelCons(scip, cons) );
9957
9958 if( !consdata->upgraded )
9959 (*ndelconss)++;
9960 }
9961 }
9962 else if( ncontvars == 1 )
9963 {
9964 SCIP_VAR* var;
9965
9966 assert(0 <= contvarpos && contvarpos < consdata->nvars);
9967 var = vars[contvarpos];
9969
9970 if( coefsintegral && SCIPisFeasIntegral(scip, consdata->rhs) )
9971 {
9972 /* upgrade continuous variable to an implied integral one, if the absolute value of the coefficient is one */
9973 if( SCIPisEQ(scip, REALABS(vals[contvarpos]), 1.0) )
9974 {
9975 /* convert the continuous variable with coefficient 1.0 into an implied integral variable */
9976 SCIPdebugMsg(scip, "linear constraint <%s>: converting continuous variable <%s> to implied integral variable\n",
9978 /* if the integrality does not depend on weak implied integrality, the variable becomes strongly implied integral */
9979 impltype = nweakimplvars == 0 ? SCIP_IMPLINTTYPE_STRONG : SCIP_IMPLINTTYPE_WEAK;
9980 SCIP_CALL( SCIPchgVarImplType(scip, var, impltype, &infeasible) );
9981 (*nchgvartypes)++;
9982 if( infeasible )
9983 {
9984 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
9985 *cutoff = TRUE;
9986
9987 return SCIP_OKAY;
9988 }
9989 }
9990 /* aggregate continuous variable to an implied integral one if the absolute coefficient is unequal to one */
9991 /* @todo check if the aggregation coefficient should be in some range(, which is not too big) */
9992 else if( !SCIPdoNotAggr(scip) )
9993 {
9994 SCIP_VAR* newvar;
9995 SCIP_Real absval;
9996 char newvarname[SCIP_MAXSTRLEN];
9997 SCIP_Bool redundant;
9998 SCIP_Bool aggregated;
9999
10000 absval = REALABS(vals[contvarpos]);
10001
10002 (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_impl", SCIPvarGetName(var));
10003
10004 /* create new implied integral variable for aggregation */
10005 SCIP_CALL( SCIPcreateVarImpl(scip, &newvar, newvarname, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0,
10008
10009 /* add new variable to problem */
10010 SCIP_CALL( SCIPaddVar(scip, newvar) );
10011
10012#ifdef WITH_DEBUG_SOLUTION
10013 if( SCIPdebugIsMainscip(scip) )
10014 {
10015 SCIP_Real varval;
10016 SCIP_CALL( SCIPdebugGetSolVal(scip, var, &varval) );
10017 SCIP_CALL( SCIPdebugAddSolVal(scip, newvar, absval * varval) );
10018 }
10019#endif
10020
10021 /* convert the continuous variable with coefficient 1.0 into an implied integral variable */
10022 SCIPdebugMsg(scip, "linear constraint <%s>: aggregating continuous variable <%s> to newly created implied integral variable <%s>, aggregation factor = %g\n",
10023 SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(newvar), absval);
10024
10025 /* aggregate continuous and implied integral variable */
10026 SCIP_CALL( SCIPaggregateVars(scip, var, newvar, absval, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
10027
10028 if( infeasible )
10029 {
10030 SCIPdebugMsg(scip, "infeasible aggregation of variable <%s> to implied integral variable <%s>, domain is empty\n",
10032 *cutoff = TRUE;
10033
10034 /* release implied integral variable */
10035 SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10036
10037 return SCIP_OKAY;
10038 }
10039
10040 /* release implied integral variable */
10041 SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10042
10043 if( aggregated )
10044 (*naggrvars)++;
10045 else
10046 return SCIP_OKAY;
10047 }
10048
10049 /* we do not have any event on vartype changes, so we need to manually force this constraint to be presolved
10050 * again
10051 */
10052 consdata->boundstightened = 0;
10053 consdata->rangedrowpropagated = 0;
10054 consdata->presolved = FALSE;
10055 }
10056 }
10057 else if( ncontvars == 0 && nimplvars == 0 && nintvars == 1 && !coefszeroone )
10058 {
10059 SCIP_VAR* var;
10060
10061 /* this seems to help for rococo instances, but does not for rout (where all coefficients are +/- 1.0)
10062 * -> we don't convert integers into implints if the row is a 0/1-row
10063 */
10064 assert(varsintegral);
10065 assert(0 <= intvarpos && intvarpos < consdata->nvars);
10066 var = vars[intvarpos];
10068
10069 if( coefsintegral
10070 && SCIPisEQ(scip, REALABS(vals[intvarpos]), 1.0)
10071 && SCIPisFeasIntegral(scip, consdata->rhs) )
10072 {
10073 /* convert the integer variable with coefficient 1.0 into an implied integral variable */
10074 SCIPdebugMsg(scip, "linear constraint <%s>: converting integer variable <%s> to implied integral variable\n",
10077 (*nchgvartypes)++;
10078 if( infeasible )
10079 {
10080 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10081 *cutoff = TRUE;
10082
10083 return SCIP_OKAY;
10084 }
10085 }
10086 }
10087
10088 return SCIP_OKAY;
10089}
10090
10091/** checks if the given variables and their coefficient are equal (w.r.t. scaling factor) to the objective function */
10092static
10094 SCIP* scip, /**< SCIP data structure */
10095 SCIP_CONSDATA* consdata, /**< linear constraint data */
10096 SCIP_Real* scale, /**< pointer to store the scaling factor between the constraint and the
10097 * objective function */
10098 SCIP_Real* offset /**< pointer to store the offset of the objective function resulting by
10099 * this constraint */
10100 )
10101{
10102 SCIP_VAR** vars;
10103 SCIP_VAR* var;
10105 SCIP_Bool negated;
10106 int nvars;
10107 int v;
10108
10109 vars = consdata->vars;
10110 nvars = consdata->nvars;
10111
10112 assert(vars != NULL);
10113
10114 for( v = 0; v < nvars; ++v )
10115 {
10116 negated = FALSE;
10117 var = vars[v];
10118 assert(var != NULL);
10119
10120 if( SCIPvarIsNegated(var) )
10121 {
10122 negated = TRUE;
10124 assert(var != NULL);
10125 }
10126
10128
10129 /* if a variable has a zero objective coefficient the linear constraint is not a subset of the objective
10130 * function
10131 */
10132 if( SCIPisZero(scip, objval) )
10133 return FALSE;
10134 else
10135 {
10136 SCIP_Real val;
10137
10138 val = consdata->vals[v];
10139
10140 if( negated )
10141 {
10142 if( v == 0 )
10143 {
10144 /* the first variable defines the scale */
10145 (*scale) = val / -objval;
10146
10147 (*offset) += val;
10148 }
10149 else if( SCIPisEQ(scip, -objval * (*scale), val) )
10150 (*offset) += val;
10151 else
10152 return FALSE;
10153 }
10154 else if( v == 0 )
10155 {
10156 /* the first variable defines the scale */
10157 (*scale) = val / objval;
10158 }
10159 else if( !SCIPisEQ(scip, objval * (*scale), val) )
10160 return FALSE;
10161 }
10162 }
10163
10164 return TRUE;
10165}
10166
10167/** check if the linear equality constraint is equal to a subset of the objective function; if so we can remove the
10168 * objective coefficients and add an objective offset
10169 */
10170static
10172 SCIP* scip, /**< SCIP data structure */
10173 SCIP_CONS* cons, /**< linear equation constraint */
10174 SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10175 )
10176{
10177 SCIP_CONSDATA* consdata;
10178 SCIP_Real offset;
10179 SCIP_Real scale;
10180 SCIP_Bool applicable;
10181 int nobjvars;
10182 int nvars;
10183 int v;
10184
10185 assert(scip != NULL);
10186 assert(cons != NULL);
10187 assert(conshdlrdata != NULL);
10188
10189 consdata = SCIPconsGetData(cons);
10190 assert(consdata != NULL);
10191 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
10192
10193 nvars = consdata->nvars;
10194 nobjvars = SCIPgetNObjVars(scip);
10195
10196 /* check if the linear equality constraints does not have more variables than the objective function */
10197 if( nvars > nobjvars || nvars == 0 )
10198 return SCIP_OKAY;
10199
10200 /* check for allowance of algorithm */
10201 if( (nvars < nobjvars && !conshdlrdata->detectpartialobjective) ||
10202 (nvars == nobjvars && (!conshdlrdata->detectcutoffbound || !conshdlrdata->detectlowerbound)) )
10203 return SCIP_OKAY;
10204
10205 offset = consdata->rhs;
10206 scale = 1.0;
10207
10208 /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10209 applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10210
10211 if( applicable )
10212 {
10213 SCIP_VAR** vars;
10214
10215 vars = consdata->vars;
10216 assert(vars != NULL);
10217
10218 offset /= scale;
10219
10220 SCIPdebugMsg(scip, "linear equality constraint <%s> == %g (offset %g) is a subset of the objective function\n",
10221 SCIPconsGetName(cons), consdata->rhs, offset);
10222
10223 /* make equality a model constraint to ensure optimality in this direction */
10226
10227 /* set all objective coefficient to zero */
10228 for( v = 0; v < nvars; ++v )
10229 {
10230 SCIP_CALL( SCIPchgVarObj(scip, vars[v], 0.0) );
10231 }
10232
10233 /* add an objective offset */
10234 SCIP_CALL( SCIPaddObjoffset(scip, offset) );
10235 }
10236
10237 return SCIP_OKAY;
10238}
10239
10240/** updates the cutoff if the given primal bound (which is implied by the given constraint) is better */
10241static
10243 SCIP* scip, /**< SCIP data structure */
10244 SCIP_CONS* cons, /**< constraint */
10245 SCIP_Real primalbound /**< feasible primal bound */
10246 )
10247{
10248 SCIP_Real cutoffbound;
10249
10250 /* increase the cutoff bound value by an epsilon to ensue that solution with the value of the cutoff bound are still
10251 * accepted
10252 */
10253 cutoffbound = primalbound + SCIPcutoffbounddelta(scip);
10254
10255 if( cutoffbound < SCIPgetCutoffbound(scip) )
10256 {
10257 SCIPdebugMsg(scip, "update cutoff bound <%g>\n", cutoffbound);
10258
10259 SCIP_CALL( SCIPupdateCutoffbound(scip, cutoffbound) );
10260 }
10261 else
10262 {
10263 SCIP_CONSDATA* consdata;
10264
10265 consdata = SCIPconsGetData(cons);
10266 assert(consdata != NULL);
10267
10268 /* we cannot disable the enforcement and propagation on ranged rows, because the cutoffbound could only have
10269 * resulted from one side
10270 */
10271 if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
10272 {
10273 /* in case the cutoff bound is worse then the currently known one, we additionally avoid enforcement and
10274 * propagation
10275 */
10278 }
10279 }
10280
10281 return SCIP_OKAY;
10282}
10283
10284/** check if the linear constraint is parallel to objective function; if so update the cutoff bound and avoid that the
10285 * constraint enters the LP by setting the initial and separated flag to FALSE
10286 */
10287static
10289 SCIP* scip, /**< SCIP data structure */
10290 SCIP_CONS* cons, /**< linear constraint */
10291 SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10292 )
10293{
10294 SCIP_CONSDATA* consdata;
10295 SCIP_Real offset;
10296 SCIP_Real scale;
10297 SCIP_Bool applicable;
10298 int nobjvars;
10299 int nvars;
10300
10301 assert(scip != NULL);
10302 assert(cons != NULL);
10303 assert(conshdlrdata != NULL);
10304
10305 consdata = SCIPconsGetData(cons);
10306 assert(consdata != NULL);
10307
10308 /* ignore equalities since these are covered by the method checkPartialObjective() */
10309 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10310 return SCIP_OKAY;
10311
10312 nvars = consdata->nvars;
10313 nobjvars = SCIPgetNObjVars(scip);
10314
10315 /* check if the linear inequality constraints has the same number of variables as the objective function and if the
10316 * initial and/or separated flag is set to FALSE
10317 */
10318 if( nvars != nobjvars || (!SCIPconsIsInitial(cons) && !SCIPconsIsSeparated(cons)) )
10319 return SCIP_OKAY;
10320
10321 offset = 0.0;
10322 scale = 1.0;
10323
10324 /* There are no variables in the objective function and in the constraint. Thus, the constraint is redundant or proves
10325 * infeasibility. Since we have a pure feasibility problem, we do not want to set a cutoff or lower bound.
10326 */
10327 if( nobjvars == 0 )
10328 return SCIP_OKAY;
10329
10330 /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10331 applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10332
10333 if( applicable )
10334 {
10335 SCIP_Bool rhsfinite = !SCIPisInfinity(scip, consdata->rhs);
10336 SCIP_Bool lhsfinite = !SCIPisInfinity(scip, -consdata->lhs);
10337
10338 assert(scale != 0.0);
10339
10340 if( scale > 0.0 )
10341 {
10342 if( conshdlrdata->detectcutoffbound && rhsfinite )
10343 {
10344 SCIP_Real primalbound;
10345
10346 primalbound = (consdata->rhs - offset) / scale;
10347
10348 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10349 SCIPconsGetName(cons), primalbound);
10350
10351 SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10352 }
10353
10354 if( conshdlrdata->detectlowerbound && lhsfinite )
10355 {
10356 SCIP_Real lowerbound;
10357
10358 lowerbound = (consdata->lhs - offset) / scale;
10359
10360 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10361 SCIPconsGetName(cons), lowerbound);
10362
10364 }
10365
10366 if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !lhsfinite)) ||
10367 (conshdlrdata->detectlowerbound && !rhsfinite) )
10368 {
10369 /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10372 }
10373 }
10374 else
10375 {
10376 if( conshdlrdata->detectlowerbound && rhsfinite )
10377 {
10378 SCIP_Real lowerbound;
10379
10380 lowerbound = (consdata->rhs - offset) / scale;
10381
10382 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10383 SCIPconsGetName(cons), lowerbound);
10384
10386 }
10387
10388 if( conshdlrdata->detectcutoffbound && lhsfinite )
10389 {
10390 SCIP_Real primalbound;
10391
10392 primalbound = (consdata->lhs - offset) / scale;
10393
10394 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10395 SCIPconsGetName(cons), primalbound);
10396
10397 SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10398 }
10399
10400 if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !rhsfinite)) ||
10401 (conshdlrdata->detectlowerbound && !lhsfinite) )
10402 {
10403 /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10406 }
10407 }
10408 }
10409
10410 return SCIP_OKAY;
10411}
10412
10413/** converts special equalities */
10414static
10416 SCIP* scip, /**< SCIP data structure */
10417 SCIP_CONS* cons, /**< linear constraint */
10418 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10419 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10420 int* nfixedvars, /**< pointer to count number of fixed variables */
10421 int* naggrvars, /**< pointer to count number of aggregated variables */
10422 int* ndelconss, /**< pointer to count number of deleted constraints */
10423 int* nchgvartypes /**< pointer to count number of changed variable types */
10424 )
10425{
10426 SCIP_CONSDATA* consdata;
10427
10428 assert(scip != NULL);
10429 assert(cons != NULL);
10430 assert(conshdlrdata != NULL);
10431 assert(cutoff != NULL);
10432 assert(nfixedvars != NULL);
10433 assert(naggrvars != NULL);
10434 assert(ndelconss != NULL);
10435
10436 consdata = SCIPconsGetData(cons);
10437 assert(consdata != NULL);
10438 assert(consdata->removedfixings);
10439
10440 /* do nothing on inequalities */
10441 if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10442 return SCIP_OKAY;
10443
10444 /* depending on the number of variables, call a special conversion method */
10445 if( consdata->nvars == 1 )
10446 {
10447 /* fix variable */
10448 SCIP_CALL( convertUnaryEquality(scip, cons, cutoff, nfixedvars, ndelconss) );
10449 }
10450 else if( consdata->nvars == 2 )
10451 {
10452 /* aggregate one of the variables */
10453 SCIP_CALL( convertBinaryEquality(scip, cons, cutoff, naggrvars, ndelconss) );
10454 }
10455 else
10456 {
10457 /* check if the equality is part of the objective function */
10458 SCIP_CALL( checkPartialObjective(scip, cons, conshdlrdata) );
10459
10460 /* try to multi-aggregate one of the variables */
10461 SCIP_CALL( convertLongEquality(scip, conshdlrdata, cons, cutoff, naggrvars, ndelconss, nchgvartypes) );
10462 }
10463
10464 return SCIP_OKAY;
10465}
10466
10467/** returns whether the linear sum of all variables/coefficients except the given one divided by the given value is always
10468 * integral
10469 */
10470static
10472 SCIP* scip, /**< SCIP data structure */
10473 SCIP_CONSDATA* consdata, /**< linear constraint */
10474 int pos, /**< position of variable to be left out */
10475 SCIP_Real val /**< value to divide the coefficients by */
10476 )
10477{
10478 int v;
10479
10480 assert(scip != NULL);
10481 assert(consdata != NULL);
10482 assert(0 <= pos && pos < consdata->nvars);
10483
10484 for( v = 0; v < consdata->nvars; ++v )
10485 {
10486 if( v != pos && (!SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v]/val)) )
10487 return FALSE;
10488 }
10489
10490 return TRUE;
10491}
10492
10493/** 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$,
10494 * 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$
10495 */
10496static
10498 SCIP* scip, /**< SCIP data structure */
10499 SCIP_Real side, /**< lhs or rhs */
10500 SCIP_Real val, /**< coefficient */
10501 SCIP_Real minresactivity, /**< minimal residual activity */
10502 SCIP_Real maxresactivity, /**< maximal residual activity */
10503 SCIP_Real* minval, /**< pointer to store calculated minval */
10504 SCIP_Real* maxval /**< pointer to store calculated maxval */
10505 )
10506{
10507 assert(scip != NULL);
10508 assert(minval != NULL);
10509 assert(maxval != NULL);
10510
10511 if( val > 0.0 )
10512 {
10513 if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10514 *minval = -maxresactivity;
10515 else
10516 *minval = (side - maxresactivity)/val;
10517
10518 if( SCIPisInfinity(scip, ABS(minresactivity)) )
10519 *maxval = -minresactivity;
10520 else
10521 *maxval = (side - minresactivity)/val;
10522 }
10523 else
10524 {
10525 if( SCIPisInfinity(scip, ABS(minresactivity)) )
10526 *minval = minresactivity;
10527 else
10528 *minval = (side - minresactivity)/val;
10529
10530 if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10531 *maxval = maxresactivity;
10532 else
10533 *maxval = (side - maxresactivity)/val;
10534 }
10535}
10536
10537
10538/** applies dual presolving for variables that are locked only once in a direction, and this locking is due to a
10539 * linear inequality
10540 */
10541static
10543 SCIP* scip, /**< SCIP data structure */
10544 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10545 SCIP_CONS* cons, /**< linear constraint */
10546 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10547 int* nfixedvars, /**< pointer to count number of fixed variables */
10548 int* naggrvars, /**< pointer to count number of aggregated variables */
10549 int* ndelconss, /**< pointer to count number of deleted constraints */
10550 int* nchgvartypes /**< pointer to count number of changed variable types */
10551 )
10552{
10553 SCIP_CONSDATA* consdata;
10554 SCIP_Bool lhsexists;
10555 SCIP_Bool rhsexists;
10556 SCIP_Bool bestisint;
10557 SCIP_Bool bestislhs;
10558 SCIP_Real minabsval;
10559 SCIP_Real maxabsval;
10560 int bestpos;
10561 int i;
10562 int maxotherlocks;
10563
10564 assert(scip != NULL);
10565 assert(cons != NULL);
10566 assert(cutoff != NULL);
10567 assert(nfixedvars != NULL);
10568 assert(naggrvars != NULL);
10569 assert(ndelconss != NULL);
10570
10571 /* only process checked constraints (for which the locks are increased);
10572 * otherwise we would have to check for variables with nlocks == 0, and these are already processed by the
10573 * dualfix presolver
10574 */
10575 if( !SCIPconsIsChecked(cons) )
10576 return SCIP_OKAY;
10577
10578 consdata = SCIPconsGetData(cons);
10579 assert(consdata != NULL);
10580
10581 lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
10582 rhsexists = !SCIPisInfinity(scip, consdata->rhs);
10583
10584 /* search for a single-locked variable which can be multi-aggregated; if a valid continuous variable was found, we
10585 * can use it safely for aggregation and break the search loop
10586 */
10587 bestpos = -1;
10588 bestisint = TRUE;
10589 bestislhs = FALSE;
10590
10591 /* We only want to multi-aggregate variables, if they appear in maximal one additional constraint,
10592 * everything else would produce fill-in. Exceptions:
10593 * - If there are only two variables in the constraint from which the multi-aggregation arises, no fill-in will be
10594 * produced.
10595 * - If there are three variables in the constraint, multi-aggregation in three additional constraints will remove
10596 * six nonzeros (three from the constraint and the three entries of the multi-aggregated variable) and add
10597 * six nonzeros (two variables per substitution).
10598 * - If there at most four variables in the constraint, multi-aggregation in two additional constraints will remove
10599 * six nonzeros (four from the constraint and the two entries of the multi-aggregated variable) and add
10600 * six nonzeros (three variables per substitution). God exists!
10601 */
10602 if( consdata->nvars <= 2 )
10603 maxotherlocks = INT_MAX;
10604 else if( consdata->nvars == 3 )
10605 maxotherlocks = 3;
10606 else if( consdata->nvars == 4 )
10607 maxotherlocks = 2;
10608 else
10609 maxotherlocks = 1;
10610
10611 /* if this constraint has both sides, it also provides a lock for the other side and thus we can allow one more lock */
10612 if( lhsexists && rhsexists && maxotherlocks < INT_MAX )
10613 maxotherlocks++;
10614
10615 minabsval = SCIPinfinity(scip);
10616 maxabsval = -1.0;
10617 for( i = 0; i < consdata->nvars && bestisint; ++i )
10618 {
10619 SCIP_VAR* var;
10620 SCIP_Bool isint;
10621 SCIP_Real val;
10622 SCIP_Real absval;
10623 SCIP_Real obj;
10624 SCIP_Real lb;
10625 SCIP_Real ub;
10626 SCIP_Bool agglhs;
10627 SCIP_Bool aggrhs;
10628
10629 val = consdata->vals[i];
10630 absval = REALABS(val);
10631
10632 /* calculate minimal and maximal absolute value */
10633 if( absval < minabsval )
10634 minabsval = absval;
10635 if( absval > maxabsval )
10636 maxabsval = absval;
10637
10638 /* do not try to multi aggregate, when numerical bad */
10639 if( maxabsval / minabsval > conshdlrdata->maxdualmultaggrquot )
10640 return SCIP_OKAY;
10641
10642 var = consdata->vars[i];
10644
10645 /* if we already found a candidate, skip integers */
10646 if( bestpos >= 0 && isint )
10647 continue;
10648
10649 /* better do not multi-aggregate binary variables, since most plugins rely on their binary variables to be either
10650 * active, fixed, or single-aggregated with another binary variable
10651 */
10652 if( SCIPvarIsBinary(var) && consdata->nvars > 2 )
10653 continue;
10654
10656 continue;
10657
10658 val = consdata->vals[i];
10660 lb = SCIPvarGetLbGlobal(var);
10661 ub = SCIPvarGetUbGlobal(var);
10662
10663 /* lhs <= a_0 * x_0 + a_1 * x_1 + ... + a_{n-1} * x_{n-1} <= rhs
10664 *
10665 * a_i >= 0, c_i >= 0, lhs exists, nlocksdown(x_i) == 1:
10666 * - constraint is the only one that forbids fixing the variable to its lower bound
10667 * - 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
10668 *
10669 * a_i <= 0, c_i <= 0, lhs exists, nlocksup(x_i) == 1:
10670 * - constraint is the only one that forbids fixing the variable to its upper bound
10671 * - 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
10672 *
10673 * a_i >= 0, c_i <= 0, rhs exists, nlocksup(x_i) == 1:
10674 * - constraint is the only one that forbids fixing the variable to its upper bound
10675 * - 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
10676 *
10677 * a_i <= 0, c_i >= 0, rhs exists, nlocksdown(x_i) == 1:
10678 * - constraint is the only one that forbids fixing the variable to its lower bound
10679 * - 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
10680 *
10681 * but: all this is only applicable, if the aggregated value is inside x_i's bounds for all possible values
10682 * of all x_j
10683 * furthermore: we only want to apply this, if no fill-in will be produced
10684 */
10685 agglhs = lhsexists
10687 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10689 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10690 aggrhs = rhsexists
10692 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10694 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10695 if( agglhs || aggrhs )
10696 {
10697 SCIP_Real minresactivity;
10698 SCIP_Real maxresactivity;
10699 SCIP_Real minval;
10700 SCIP_Real maxval;
10701 SCIP_Bool ismintight;
10702 SCIP_Bool ismaxtight;
10703 SCIP_Bool isminsettoinfinity;
10704 SCIP_Bool ismaxsettoinfinity;
10705
10706 /* calculate bounds for \sum_{j \neq i} a_j * x_j */
10707 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
10708 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
10709 assert(SCIPisLE(scip, minresactivity, maxresactivity));
10710
10711 /* We called consdataGetActivityResiduals() saying that we do not need a good relaxation,
10712 * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
10713 * This is needed, because we do not want to rely on relaxed finite resactivities.
10714 */
10715 assert((ismintight || isminsettoinfinity) && (ismaxtight || ismaxsettoinfinity));
10716
10717 if( agglhs )
10718 {
10719 /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10720 calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10721
10722 assert(SCIPisLE(scip, minval, maxval));
10723 if( !SCIPisInfinity(scip, -minval) && SCIPisGE(scip, minval, lb)
10724 && !SCIPisInfinity(scip, maxval) && SCIPisLE(scip, maxval, ub) )
10725 {
10726 SCIP_Real oldmaxresactivity;
10727 SCIP_Real oldminresactivity;
10728 SCIP_Bool recalculated;
10729
10730 recalculated = FALSE;
10731 oldmaxresactivity = maxresactivity;
10732 oldminresactivity = minresactivity;
10733
10734 /* check minresactivity for reliability */
10735 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10736 {
10737 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10738 recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10739 isminsettoinfinity = TRUE; /* here it means only that it was even calculated */
10740 }
10741
10742 /* check maxresactivity for reliability */
10743 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10744 {
10745 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10746 recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10747 ismaxsettoinfinity = TRUE; /* here it means only that it was even calculated */
10748 }
10749
10750 /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10751 if( recalculated )
10752 {
10753 assert(SCIPisLE(scip, minresactivity, maxresactivity));
10754
10755 /* check again if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10756 calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10757
10758 assert(SCIPisLE(scip, minval, maxval));
10759 }
10760
10761 if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10762 {
10763 /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10764 * in the multi-aggregation
10765 */
10766 if( !isint || (SCIPisIntegral(scip, consdata->lhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10767 {
10768 bestpos = i;
10769 bestisint = isint;
10770 bestislhs = TRUE;
10771 continue; /* no need to also look at the right hand side */
10772 }
10773 }
10774 }
10775 }
10776
10777 if( aggrhs )
10778 {
10779 /* check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10780 calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10781
10782 assert(SCIPisLE(scip,minval,maxval));
10783 if( !SCIPisInfinity(scip, -minval) && SCIPisGE(scip, minval, lb)
10784 && !SCIPisInfinity(scip, maxval) && SCIPisLE(scip, maxval, ub) )
10785 {
10786 SCIP_Real oldmaxresactivity;
10787 SCIP_Real oldminresactivity;
10788 SCIP_Bool recalculated;
10789
10790 recalculated = FALSE;
10791 oldmaxresactivity = maxresactivity;
10792 oldminresactivity = minresactivity;
10793
10794 /* check minresactivity for reliability */
10795 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10796 {
10797 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10798 recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10799 }
10800
10801 /* check maxresactivity for reliability */
10802 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10803 {
10804 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10805 recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10806 }
10807
10808 /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10809 if( recalculated )
10810 {
10811 /* check again if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10812 calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10813 assert(SCIPisLE(scip,minval,maxval));
10814 }
10815
10816 if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10817 {
10818 /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10819 * in the multi-aggregation
10820 */
10821 if( !isint || (SCIPisIntegral(scip, consdata->rhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10822 {
10823 bestpos = i;
10824 bestisint = isint;
10825 bestislhs = FALSE;
10826 }
10827 }
10828 }
10829 }
10830 }
10831 }
10832
10833 if( bestpos >= 0 )
10834 {
10835 SCIP_VAR** aggrvars;
10836 SCIP_Real* aggrcoefs;
10837 SCIP_Real aggrconst;
10838 SCIP_VAR* bestvar;
10839 SCIP_Real bestval;
10840 int naggrs;
10841 int j;
10842 SCIP_Bool infeasible;
10843 SCIP_Bool aggregated;
10844
10845 assert(!bestislhs || lhsexists);
10846 assert(bestislhs || rhsexists);
10847
10848 bestvar = consdata->vars[bestpos];
10849 bestval = consdata->vals[bestpos];
10850 assert(bestisint == SCIPvarIsNonimpliedIntegral(bestvar));
10851
10852 /* allocate temporary memory */
10853 SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars-1) );
10854 SCIP_CALL( SCIPallocBufferArray(scip, &aggrcoefs, consdata->nvars-1) );
10855
10856 /* set up the multi-aggregation */
10858 SCIPdebugMsg(scip, "linear constraint <%s> (dual): multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(bestvar));
10859 naggrs = 0;
10860
10861 for( j = 0; j < consdata->nvars; ++j )
10862 {
10863 if( j != bestpos )
10864 {
10865 aggrvars[naggrs] = consdata->vars[j];
10866 aggrcoefs[naggrs] = -consdata->vals[j]/consdata->vals[bestpos];
10867
10868 SCIPdebugMsgPrint(scip, " %+.15g<%s>", aggrcoefs[naggrs], SCIPvarGetName(aggrvars[naggrs]));
10869
10870 /* do not try to multi aggregate, when numerical bad */
10871 if( SCIPisZero(scip, aggrcoefs[naggrs]) )
10872 {
10873 SCIPdebugMsg(scip, "do not perform multi-aggregation: too large aggregation coefficients\n");
10874
10875 /* free temporary memory */
10876 SCIPfreeBufferArray(scip, &aggrcoefs);
10877 SCIPfreeBufferArray(scip, &aggrvars);
10878
10879 return SCIP_OKAY;
10880 }
10881
10882 if( bestisint )
10883 {
10884 /* coefficient must be integral: round it to exact integral value */
10885 assert(SCIPisIntegral(scip, aggrcoefs[naggrs]));
10886 aggrcoefs[naggrs] = SCIPfloor(scip, aggrcoefs[naggrs]+0.5);
10887 }
10888
10889 naggrs++;
10890 }
10891 }
10892
10893 aggrconst = (bestislhs ? consdata->lhs/bestval : consdata->rhs/bestval);
10894 SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g]\n", aggrconst, SCIPvarGetName(bestvar),
10895 SCIPvarGetLbGlobal(bestvar), SCIPvarGetUbGlobal(bestvar));
10896 assert(naggrs == consdata->nvars-1);
10897
10898 /* right hand side must be integral: round it to exact integral value */
10899 if( bestisint )
10900 {
10901 assert(SCIPisIntegral(scip, aggrconst));
10902 aggrconst = SCIPfloor(scip, aggrconst+0.5);
10903 }
10904
10905 aggregated = FALSE;
10906 infeasible = FALSE;
10907
10908 /* perform the multi-aggregation */
10909 SCIP_CALL( SCIPmultiaggregateVar(scip, bestvar, naggrs, aggrvars, aggrcoefs, aggrconst, &infeasible, &aggregated) );
10910
10911 /** @todo handle this case properly with weak and strong implied integrality */
10912 /* if the multi-aggregated bestvar is enforced but not strongly implied integral, we need to convert implied
10913 * integral to integer variables because integrality of the multi-aggregated variable must hold
10914 */
10915 if( !infeasible && aggregated && SCIPvarGetType(bestvar) != SCIP_VARTYPE_CONTINUOUS && SCIPvarGetImplType(bestvar) != SCIP_IMPLINTTYPE_STRONG )
10916 {
10917 SCIP_Bool infeasiblevartypechg = FALSE;
10918
10919 for( j = 0; j < naggrs; ++j )
10920 {
10921 /* if the multi-aggregation was not infeasible, then setting implied integral to integer should not
10922 * lead to infeasibility
10923 */
10925 {
10926 if( SCIPvarGetType(aggrvars[j]) == SCIP_VARTYPE_CONTINUOUS )
10927 {
10928 SCIP_CALL( SCIPchgVarType(scip, aggrvars[j], SCIP_VARTYPE_INTEGER, &infeasiblevartypechg) );
10929 assert(!infeasiblevartypechg);
10930 }
10931 SCIP_CALL( SCIPchgVarImplType(scip, aggrvars[j], SCIP_IMPLINTTYPE_NONE, &infeasiblevartypechg) );
10932 assert(!infeasiblevartypechg);
10933 (*nchgvartypes)++;
10934 }
10935 }
10936 }
10937
10938 /* free temporary memory */
10939 SCIPfreeBufferArray(scip, &aggrcoefs);
10940 SCIPfreeBufferArray(scip, &aggrvars);
10941
10942 /* check for infeasible aggregation */
10943 if( infeasible )
10944 {
10945 SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
10946 *cutoff = TRUE;
10947 return SCIP_OKAY;
10948 }
10949
10950 /* delete the constraint, if the aggregation was successful */
10951 if( aggregated )
10952 {
10953 SCIP_CALL( SCIPdelCons(scip, cons) );
10954
10955 if( !consdata->upgraded )
10956 (*ndelconss)++;
10957 (*naggrvars)++;
10958 }
10959 else
10960 {
10961 SCIPdebugMsg(scip, "aggregation non successful!\n");
10962 }
10963 }
10964
10965 return SCIP_OKAY;
10966}
10967
10968#define BINWEIGHT 1
10969#define INTWEIGHT 4
10970#define CONTWEIGHT 8
10971
10972/** gets weight for variable in a "weighted number of variables" sum */
10973static
10975 SCIP_VAR* var /**< variable to get weight for */
10976 )
10977{
10979 return INTWEIGHT;
10980
10981 switch( SCIPvarGetType(var) )
10982 {
10984 return BINWEIGHT;
10986 return INTWEIGHT;
10988 return CONTWEIGHT;
10989 default:
10990 SCIPerrorMessage("unknown variable type\n");
10991 SCIPABORT();
10992 return 0; /*lint !e527*/
10993 } /*lint !e788*/
10994}
10995
10996/** tries to aggregate variables in equations a^Tx = lhs
10997 * in case there are at most two binary variables with an odd coefficient and all other
10998 * variables are not continuous and have an even coefficient then:
10999 * - exactly one odd binary variables
11000 * this binary variables y can be fixed to 0 if the lhs is even and to 1 if the lhs is odd
11001 * - lhs is odd -> y = 1
11002 * - lhs is even -> y = 0
11003 * - exactly two odd binary variables
11004 * aggregate the two binary variables with odd coefficient
11005 * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11006 * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11007 */
11008static
11010 SCIP* scip, /**< SCIP data structure */
11011 SCIP_CONS* cons, /**< linear constraint */
11012 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
11013 int* nfixedvars, /**< pointer to count number of fixed variables */
11014 int* naggrvars /**< pointer to count number of aggregated variables */
11015 )
11016{ /*lint --e{715}*/
11017 SCIP_CONSDATA* consdata;
11018 SCIP_Bool success;
11019
11020 assert( scip != NULL );
11021 assert( cons != NULL );
11022
11023 consdata = SCIPconsGetData(cons);
11024 assert( consdata != NULL );
11025
11026 /* check if the linear constraint is an equation with integral right hand side */
11027 if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) || !SCIPisIntegral(scip, consdata->lhs) )
11028 return SCIP_OKAY;
11029
11030 /* try to fix and aggregated variables until nothing is possible anymore */
11031 do
11032 {
11033 int v;
11034 int nvars;
11035 SCIP_VAR** vars;
11036 SCIP_Real* vals;
11037 SCIP_Real lhs;
11038 SCIP_Bool lhsodd;
11039
11040 SCIP_Bool infeasible;
11041 SCIP_Bool fixed;
11042 SCIP_Bool aggregated;
11043 SCIP_Bool redundant;
11044
11045 SCIP_VAR* var1;
11046 SCIP_VAR* var2;
11047 int noddvars;
11048
11049 success = FALSE;
11050
11051 lhs = consdata->lhs;
11052 vars = consdata->vars;
11053 vals = consdata->vals;
11054 nvars = consdata->nvars;
11055
11056 assert( !SCIPisInfinity(scip, ABS(lhs)) );
11057
11058 var1 = NULL;
11059 var2 = NULL;
11060 noddvars = 0;
11061
11062 /* search for binary variables with an odd coefficient */
11063 for( v = 0; v < nvars && noddvars < 3; ++v )
11064 {
11065 SCIP_Longint val;
11066
11067 /* all coefficients and variables have to be integral */
11068 if( !SCIPvarIsIntegral(vars[v]) || !SCIPisIntegral(scip, vals[v]) )
11069 return SCIP_OKAY;
11070
11071 val = (SCIP_Longint)SCIPfeasFloor(scip, vals[v]);
11072 if( val % 2 != 0 )
11073 {
11074 /* the odd values have to belong to binary variables */
11075 if( !SCIPvarIsBinary(vars[v]) )
11076 return SCIP_OKAY;
11077
11078 if( noddvars == 0 )
11079 var1 = vars[v];
11080 else
11081 var2 = vars[v];
11082
11083 noddvars++;
11084 }
11085 }
11086
11087 /* check lhs is odd or even */
11088 lhsodd = (((SCIP_Longint)SCIPfeasFloor(scip, lhs)) % 2 != 0);
11089
11090 if( noddvars == 1 )
11091 {
11092 assert( var1 != NULL );
11093
11094 SCIPdebugMsg(scip, "linear constraint <%s>: try fixing variable <%s> to <%g>\n",
11095 SCIPconsGetName(cons), SCIPvarGetName(var1), lhsodd ? 1.0 : 0.0);
11096
11097 SCIP_CALL( SCIPfixVar(scip, var1, lhsodd? 1.0 : 0.0, &infeasible, &fixed) );
11098
11099 /* check for infeasibility of fixing */
11100 if( infeasible )
11101 {
11102 SCIPdebugMsg(scip, " -> infeasible fixing\n");
11103 *cutoff = TRUE;
11104 return SCIP_OKAY;
11105 }
11106
11107 if( fixed )
11108 {
11109 SCIPdebugMsg(scip, " -> feasible fixing\n");
11110 (*nfixedvars)++;
11111 success = TRUE;
11112 }
11113 }
11114 else if( noddvars == 2 )
11115 {
11116 assert( var1 != NULL );
11117 assert( var2 != NULL );
11118
11119 /* aggregate the two variables with odd coefficient
11120 * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11121 * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11122 */
11123 SCIPdebugMsg(scip, "linear constraint <%s>: try aggregation of variables <%s> and <%s>\n",
11124 SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
11125
11126 SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, lhsodd ? 1.0 : -1.0,
11127 lhsodd ? 1.0 : 0.0, &infeasible, &redundant, &aggregated) );
11128
11129 /* check for infeasibility of aggregation */
11130 if( infeasible )
11131 {
11132 SCIPdebugMsg(scip, " -> infeasible aggregation\n");
11133 *cutoff = TRUE;
11134 return SCIP_OKAY;
11135 }
11136
11137 /* count the aggregation */
11138 if( aggregated )
11139 {
11140 SCIPdebugMsg(scip, " -> feasible aggregation\n");
11141 (*naggrvars)++;
11142 success = TRUE;
11143 }
11144 }
11145
11146 if( success )
11147 {
11148 /* apply fixings and aggregation to successfully rerun this presolving step */
11149 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
11150
11151 if( infeasible )
11152 {
11153 SCIPdebugMsg(scip, " -> infeasible fixing\n");
11154 *cutoff = TRUE;
11155 return SCIP_OKAY;
11156 }
11157
11158 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
11159
11160 if( infeasible )
11161 {
11162 SCIPdebugMsg(scip, " -> infeasible normalization\n");
11163 *cutoff = TRUE;
11164 return SCIP_OKAY;
11165 }
11166 }
11167 }
11168 while( success && consdata->nvars >= 1 );
11169
11170 return SCIP_OKAY;
11171}
11172
11173
11174
11175/** sorting method for constraint data, compares two variables on given indices, continuous variables will be sorted to
11176 * the end and for all other variables the sortation will be in non-increasing order of their absolute value of the
11177 * coefficients
11178 */
11179static
11181{ /*lint --e{715}*/
11182 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
11183 SCIP_Real value;
11184
11185 assert(consdata != NULL);
11186 assert(0 <= ind1 && ind1 < consdata->nvars);
11187 assert(0 <= ind2 && ind2 < consdata->nvars);
11188
11189 SCIP_Bool varcont1 = !SCIPvarIsIntegral(consdata->vars[ind1]);
11190 SCIP_Bool varcont2 = !SCIPvarIsIntegral(consdata->vars[ind2]);
11191
11192 if( varcont1 )
11193 {
11194 /* continuous variables will be sorted to the back */
11195 if( varcont1 != varcont2 )
11196 return +1;
11197 /* both variables are continuous */
11198 else
11199 return 0;
11200 }
11201 /* continuous variables will be sorted to the back */
11202 else if( varcont2 )
11203 return -1;
11204
11205 value = REALABS(consdata->vals[ind2]) - REALABS(consdata->vals[ind1]);
11206
11207 /* for all non-continuous variables, the variables are sorted after decreasing absolute coefficients */
11208 return (value > 0 ? +1 : (value < 0 ? -1 : 0));
11209}
11210
11211/** tries to simplify coefficients in ranged row of the form lhs <= a^Tx <= rhs
11212 *
11213 * 1. lhs <= a^Tx <= rhs, x binary, lhs > 0, forall a_i >= lhs, a_i <= rhs, and forall pairs a_i + a_j > rhs,
11214 * then we can change this constraint to 1^Tx = 1
11215 */
11216static
11218 SCIP* scip, /**< SCIP data structure */
11219 SCIP_CONS* cons, /**< linear constraint */
11220 int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11221 int* nchgsides /**< pointer to store the amount of changed sides */
11222 )
11223{
11224 SCIP_CONSDATA* consdata;
11225 SCIP_VAR** vars;
11226 SCIP_Real* vals;
11227 SCIP_Real minval;
11228 SCIP_Real secondminval;
11229 SCIP_Real maxval;
11230 SCIP_Real lhs;
11231 SCIP_Real rhs;
11232 int nvars;
11233 int v;
11234
11235 /* we must not change a modifiable constraint in any way */
11236 if( SCIPconsIsModifiable(cons) )
11237 return SCIP_OKAY;
11238
11239 if( SCIPconsIsDeleted(cons) )
11240 return SCIP_OKAY;
11241
11242 consdata = SCIPconsGetData(cons);
11243 assert(consdata != NULL);
11244
11245 nvars = consdata->nvars;
11246
11247 /* do not check empty or bound-constraints */
11248 if( nvars < 2 )
11249 return SCIP_OKAY;
11250
11251 lhs = consdata->lhs;
11252 rhs = consdata->rhs;
11253 assert(!SCIPisInfinity(scip, -lhs));
11254 assert(!SCIPisInfinity(scip, rhs));
11255 assert(!SCIPisNegative(scip, rhs));
11256
11257 /* sides must be positive and different to detect set partition */
11258 if( !SCIPisPositive(scip, lhs) || !SCIPisLT(scip, lhs, rhs) )
11259 return SCIP_OKAY;
11260
11261 vals = consdata->vals;
11262 vars = consdata->vars;
11263 assert(vars != NULL);
11264 assert(vals != NULL);
11265
11266 minval = SCIP_INVALID;
11267 secondminval = SCIP_INVALID;
11268 maxval = -SCIP_INVALID;
11269
11270 for( v = nvars - 1; v >= 0; --v )
11271 {
11272 if( SCIPvarIsBinary(vars[v]) )
11273 {
11274 if( minval > vals[v] || minval == SCIP_INVALID ) /*lint !e777*/
11275 {
11276 secondminval = minval;
11277 minval = vals[v];
11278 }
11279 else if( secondminval > vals[v] || secondminval == SCIP_INVALID ) /*lint !e777*/
11280 secondminval = vals[v];
11281
11282 if( maxval < vals[v] || maxval == -SCIP_INVALID ) /*lint !e777*/
11283 maxval = vals[v];
11284 }
11285 else
11286 break;
11287 }
11288
11289 /* check if all variables are binary, we can choose one, and need to choose at most one */
11290 if( v == -1 && SCIPisGE(scip, minval, lhs) && SCIPisLE(scip, maxval, rhs)
11291 && SCIPisGT(scip, minval + secondminval, rhs) )
11292 {
11293 /* change all coefficients to 1.0 */
11294 for( v = nvars - 1; v >= 0; --v )
11295 {
11296 SCIP_CALL( chgCoefPos(scip, cons, v, 1.0) );
11297 }
11298 (*nchgcoefs) += nvars;
11299
11300 /* replace old right and left hand side with 1.0 */
11301 SCIP_CALL( chgRhs(scip, cons, 1.0) );
11302 SCIP_CALL( chgLhs(scip, cons, 1.0) );
11303 (*nchgsides) += 2;
11304 }
11305
11306 return SCIP_OKAY;
11307}
11308
11309/** tries to simplify coefficients and delete variables in constraints of the form lhs <= a^Tx <= rhs
11310 *
11311 * for both-sided constraints only @see rangedRowSimplify() will be called
11312 *
11313 * for one-sided constraints there are several different coefficient reduction steps which will be applied
11314 *
11315 * 1. We try to determine parts of the constraint which will not change anything on (in-)feasibility of the constraint
11316 *
11317 * e.g. 5x1 + 5x2 + 3z1 <= 8 => 3z1 is redundant if all x are binary and -2 < 3z1 <= 3
11318 *
11319 * 2. We try to remove redundant fractional parts in a constraint
11320 *
11321 * e.g. 5.2x1 + 5.1x2 + 3x3 <= 8.3 => will be changed to 5x1 + 5x2 + 3x3 <= 8 if all x are binary
11322 *
11323 * 3. We are using the greatest common divisor for further reductions
11324 *
11325 * e.g. 10x1 + 5y2 + 5x3 + 3x4 <= 15 => will be changed to 2x1 + y2 + x3 + x4 <= 3 if all xi are binary and y2 is
11326 * integral
11327 */
11328static
11330 SCIP* scip, /**< SCIP data structure */
11331 SCIP_CONS* cons, /**< linear constraint */
11332 int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11333 int* nchgsides, /**< pointer to store the amount of changed sides */
11334 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
11335 )
11336{
11337 SCIP_CONSDATA* consdata;
11338 SCIP_VAR** vars;
11339 SCIP_Real* vals;
11340 int* perm;
11341 SCIP_Real minactsub;
11342 SCIP_Real maxactsub;
11343 SCIP_Real siderest;
11344 SCIP_Real feastol;
11345 SCIP_Real newcoef;
11346 SCIP_Real absval;
11347 SCIP_Real minact;
11348 SCIP_Real maxact;
11349 SCIP_Real side;
11350 SCIP_Real lhs;
11351 SCIP_Real rhs;
11352 SCIP_Real lb;
11353 SCIP_Real ub;
11354 SCIP_Longint restcoef;
11355 SCIP_Longint oldgcd;
11356 SCIP_Longint rest;
11357 SCIP_Longint gcd;
11358 SCIP_Bool isminsettoinfinity;
11359 SCIP_Bool ismaxsettoinfinity;
11360 SCIP_Bool ismintight;
11361 SCIP_Bool ismaxtight;
11362 SCIP_Bool allcoefintegral;
11363 SCIP_Bool onlybin;
11364 SCIP_Bool hasrhs;
11365 SCIP_Bool haslhs;
11366 int oldnchgcoefs; /* cppcheck-suppress unassignedVariable */
11367 int oldnchgsides; /* cppcheck-suppress unassignedVariable */
11368 int foundbin;
11369 int candpos;
11370 int candpos2;
11371 int offsetv;
11372 int nvars;
11373 int v;
11374 int w;
11375
11376 assert(scip != NULL);
11377 assert(cons != NULL);
11378 assert(nchgcoefs != NULL);
11379 assert(nchgsides != NULL);
11380
11381 *infeasible = FALSE;
11382
11383 /* we must not change a modifiable constraint in any way */
11384 if( SCIPconsIsModifiable(cons) )
11385 return SCIP_OKAY;
11386
11387 if( SCIPconsIsDeleted(cons) )
11388 return SCIP_OKAY;
11389
11390 consdata = SCIPconsGetData(cons);
11391 assert(consdata != NULL);
11392
11393 nvars = consdata->nvars;
11394
11395 /* do not check empty or bound-constraints */
11396 if( nvars <= 2 )
11397 return SCIP_OKAY;
11398
11399 /* update maximal activity delta if necessary */
11400 if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
11402
11403 assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
11404 assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
11405 checkMaxActivityDelta(scip, consdata);
11406
11407 /* @todo the following might be too hard, check which steps can be applied and what code must be corrected
11408 * accordingly
11409 */
11410 /* can only work with valid non-infinity activities per variable */
11411 if( SCIPisInfinity(scip, consdata->maxactdelta) )
11412 return SCIP_OKAY;
11413
11414 /* @todo: change the following: due to vartype changes, the status of the normalization can be wrong, need an event
11415 * but the eventsystem seems to be full
11416 */
11417 consdata->normalized = FALSE;
11418
11419 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11420 assert(nvars == consdata->nvars);
11421
11422 if( *infeasible )
11423 return SCIP_OKAY;
11424
11425 if( !consdata->normalized )
11426 return SCIP_OKAY;
11427
11428 lhs = consdata->lhs;
11429 rhs = consdata->rhs;
11430 assert(!SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs));
11431 assert(!SCIPisNegative(scip, rhs));
11432
11433 if( !SCIPisInfinity(scip, -lhs) )
11434 haslhs = TRUE;
11435 else
11436 haslhs = FALSE;
11437
11438 if( !SCIPisInfinity(scip, rhs) )
11439 hasrhs = TRUE;
11440 else
11441 hasrhs = FALSE;
11442
11443 /* @todo extend both-sided simplification */
11444 if( haslhs && hasrhs )
11445 {
11446 SCIP_CALL( rangedRowSimplify(scip, cons, nchgcoefs, nchgsides ) );
11447
11448 return SCIP_OKAY;
11449 }
11450 assert(haslhs != hasrhs);
11451
11452 /* if we have a normalized inequality (not ranged) the one side should be positive, @see normalizeCons() */
11453 assert(!hasrhs || !SCIPisNegative(scip, rhs));
11454 assert(!haslhs || !SCIPisNegative(scip, lhs));
11455
11456 /* get temporary memory to store the sorted permutation */
11458
11459 /* call sorting method, order continuous variables to the end and all other variables after non-increasing absolute
11460 * value of their coefficients
11461 */
11462 SCIPsort(perm, consdataCompSim, (void*)consdata, nvars);
11463
11464 /* perform sorting after permutation array */
11465 permSortConsdata(consdata, perm, nvars);
11466 consdata->indexsorted = FALSE;
11467 consdata->coefsorted = FALSE;
11468
11469 vars = consdata->vars;
11470 vals = consdata->vals;
11471 assert(vars != NULL);
11472 assert(vals != NULL);
11473 assert(!consdata->validmaxabsval || SCIPisFeasEQ(scip, consdata->maxabsval, REALABS(vals[0])) || !SCIPvarIsIntegral(vars[nvars - 1]));
11474
11475 /* free temporary memory */
11476 SCIPfreeBufferArray(scip, &perm);
11477
11478 /* only check constraints with at least two non continuous variables */
11479 if( !SCIPvarIsIntegral(vars[1]) )
11480 return SCIP_OKAY;
11481
11482 /* do not process constraints when all coefficients are 1.0 */
11483 if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) && ((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs))) )
11484 return SCIP_OKAY;
11485
11486 feastol = SCIPfeastol(scip);
11487
11488 SCIPdebugMsg(scip, "starting simplification of coefficients\n");
11490
11491 /* get global activities */
11492 consdataGetGlbActivityBounds(scip, consdata, FALSE, &minact, &maxact,
11493 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
11494
11495 /* cannot work with infinite activities */
11496 if( isminsettoinfinity || ismaxsettoinfinity )
11497 return SCIP_OKAY;
11498
11499 assert(ismintight);
11500 assert(ismaxtight);
11501 assert(maxact > minact);
11502 assert(!SCIPisInfinity(scip, -minact));
11503 assert(!SCIPisInfinity(scip, maxact));
11504
11505 v = 0;
11506 offsetv = -1;
11507 side = haslhs ? lhs : rhs;
11508 minactsub = minact;
11509 maxactsub = maxact;
11510
11511 /* we now determine coefficients as large as the side of the constraint to retrieve a better reduction where we
11512 * do not need to look at the large coefficients
11513 *
11514 * e.g. all x are binary, z are positive integer
11515 * c1: +5x1 + 5x2 + 3x3 + 3x4 + x5 >= 5 (x5 is redundant and does not change (in-)feasibility of this constraint)
11516 * c2: +4x1 + 4x2 + 3x3 + 3x4 + x5 >= 4 (gcd (without the coefficient of x5) after the large coefficients is 3
11517 * c3: +30x1 + 29x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 30 (gcd (without the coefficient of x2) after the large coefficients is 7
11518 *
11519 * can be changed to
11520 *
11521 * c1: +6x1 + 6x2 + 3x3 + 3x4 >= 6 (will be changed to c1: +2x1 + 2x2 + x3 + x4 >= 2)
11522 * c2: +6x1 + 6x2 + 3x3 + 3x4 + 3x5 >= 6 (will be changed to c2: +2x1 + 2x2 + x3 + x4 + x5 >= 2)
11523 * c3: +28x1 + 28x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 28 (will be changed to c3: +4x1 + 4x2 + 2x3 + 2z1 + x5 + x6 <= 4)
11524 */
11525
11526 /* if the minimal activity is negative and we found more than one variable with a coefficient bigger than the left
11527 * hand side, we cannot apply the extra reduction step and need to reset v
11528 *
11529 * 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
11530 * coefficients due to the gcd on the "small" coefficients we would get 8x1 + 8x2 - 4x3 - 4x4 >= 8 were xi = 1
11531 * for all i is a solution
11532 *
11533 * also redundancy of variables would not be correctly determined in such a case
11534 */
11535 if( nvars > 2 && SCIPisEQ(scip, vals[0], side) && !SCIPisNegative(scip, minactsub) )
11536 {
11537 v = 1;
11538
11539 while( v < nvars && SCIPisEQ(scip, side, vals[v]) )
11540 {
11541 /* if we have integer variable with "side"-coefficients but also with a lower bound greater than 0 we stop this
11542 * extra step, which might have worked
11543 */
11544 if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
11545 {
11546 v = 0;
11547 break;
11548 }
11549
11550 ++v;
11551 }
11552
11553 /* easy and quick fix: if all coefficients were equal to the side, we cannot apply further simplifications */
11554 /* todo find numerically stable normalization conditions to scale this cons to have coefficients almost equal to 1 */
11555 if( v == nvars )
11556 return SCIP_OKAY;
11557
11558 /* cannot work with continuous variables which have a big coefficient */
11559 if( v > 0 && !SCIPvarIsIntegral(vars[v - 1]) )
11560 return SCIP_OKAY;
11561
11562 /* big negative coefficient, do not try to use the extra coefficient reduction step */
11563 if( SCIPisEQ(scip, side, -vals[v]) )
11564 v = 0;
11565
11566 /* all but one variable are processed or the next variable is continuous we cannot perform the extra coefficient
11567 * reduction
11568 */
11569 if( v == nvars - 1 || !SCIPvarIsIntegral(vars[v]) )
11570 v = 0;
11571
11572 if( v > 0 )
11573 {
11574 assert(v < nvars);
11575
11576 offsetv = v - 1;
11577
11578 for( w = 0; w < v; ++w )
11579 {
11580 lb = SCIPvarGetLbGlobal(vars[w]);
11581 ub = SCIPvarGetUbGlobal(vars[w]);
11582
11583 assert(vals[w] > 0);
11584
11585 /* update residual activities */
11586 maxactsub -= ub * vals[w];
11587 minactsub -= lb * vals[w];
11588 assert(maxactsub > minactsub);
11589 }
11590 }
11591 }
11592
11593 /* find and remove redundant variables which do not interact with the (in-)feasibility of this constraint
11594 *
11595 * e.g. let all x are binary and y1 is continuous with bounds [-3,1] then we can reduce
11596 *
11597 * 15x1 + 15x2 + 7x3 + 3x4 + y1 <= 26
11598 * to
11599 * 15x1 + 15x2 <= 26 <=> x1 + x2 <= 1
11600 */
11601 if( nvars > 2 && SCIPisIntegral(scip, vals[v]) )
11602 {
11603 SCIP_Bool redundant = FALSE;
11604 SCIP_Bool numericsok;
11605 SCIP_Bool rredundant;
11606 SCIP_Bool lredundant;
11607
11608 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11609 assert(gcd >= 1);
11610
11611 if( v == 0 )
11612 {
11613 lb = SCIPvarGetLbGlobal(vars[0]);
11614 ub = SCIPvarGetUbGlobal(vars[0]);
11615
11616 /* update residual activities */
11617 if( vals[0] > 0 )
11618 {
11619 maxactsub -= ub * vals[0];
11620 minactsub -= lb * vals[0];
11621 }
11622 else
11623 {
11624 maxactsub -= lb * vals[0];
11625 minactsub -= ub * vals[0];
11626 }
11627 assert(maxactsub > minactsub);
11628 ++v;
11629 }
11630
11631 siderest = -SCIP_INVALID;
11632 allcoefintegral = TRUE;
11633
11634 /* check if some variables always fit into the given constraint */
11635 for( ; v < nvars - 1; ++v )
11636 {
11637 if( !SCIPvarIsIntegral(vars[v]) )
11638 break;
11639
11640 if( !SCIPisIntegral(scip, vals[v]) )
11641 {
11642 allcoefintegral = FALSE;
11643 break;
11644 }
11645
11646 /* calculate greatest common divisor for all general and binary variables */
11647 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11648
11649 if( gcd == 1 )
11650 break;
11651
11652 lb = SCIPvarGetLbGlobal(vars[v]);
11653 ub = SCIPvarGetUbGlobal(vars[v]);
11654
11655 assert(!SCIPisInfinity(scip, -lb));
11656 assert(!SCIPisInfinity(scip, ub));
11657
11658 /* update residual activities */
11659 if( vals[v] > 0 )
11660 {
11661 maxactsub -= ub * vals[v];
11662 minactsub -= lb * vals[v];
11663 }
11664 else
11665 {
11666 maxactsub -= lb * vals[v];
11667 minactsub -= ub * vals[v];
11668 }
11669 assert(SCIPisGE(scip, maxactsub, minactsub));
11670
11671 if( hasrhs )
11672 {
11673 /* determine the remainder of the right hand side and the gcd */
11674 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11675 }
11676 else
11677 {
11678 /* determine the remainder of the left hand side and the gcd */
11679 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11680 if( SCIPisZero(scip, siderest) )
11681 siderest = gcd;
11682 }
11683
11684 rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
11685 lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11686
11687 /* early termination if the activities deceed the gcd */
11688 if( offsetv == -1 && (rredundant || lredundant) )
11689 {
11690 redundant = TRUE;
11691 break;
11692 }
11693 }
11694 assert(v < nvars || (offsetv >= 0 && gcd > 1));
11695
11696 if( !redundant )
11697 {
11698 if( hasrhs )
11699 {
11700 /* determine the remainder of the right hand side and the gcd */
11701 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11702 }
11703 else
11704 {
11705 /* determine the remainder of the left hand side and the gcd */
11706 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11707 if( SCIPisZero(scip, siderest) )
11708 siderest = gcd;
11709 }
11710 }
11711 else
11712 ++v;
11713
11714 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",
11715 v, nvars, minactsub, maxactsub, redundant, hasrhs, siderest, gcd, offsetv);
11716
11717 /* to avoid inconsistencies due to numerics, check that the full and partial activities have
11718 * reasonable absolute values */
11719 numericsok = REALABS(maxact) < MAXACTVAL && REALABS(maxactsub) < MAXACTVAL && REALABS(minact) < MAXACTVAL &&
11720 REALABS(minactsub) < MAXACTVAL;
11721
11722 rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
11723 lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11724
11725 /* check if we can remove redundant variables */
11726 if( v < nvars && numericsok && (redundant || (offsetv == -1 && (rredundant || lredundant))) )
11727 {
11728 SCIP_Real oldcoef;
11729
11730 /* double check the redundancy */
11731#ifndef NDEBUG
11732 SCIP_Real tmpminactsub = 0.0;
11733 SCIP_Real tmpmaxactsub = 0.0;
11734
11735 /* recompute residual activities */
11736 for( w = v; w < nvars; ++w )
11737 {
11738 lb = SCIPvarGetLbGlobal(vars[w]);
11739 ub = SCIPvarGetUbGlobal(vars[w]);
11740
11741 assert(!SCIPisInfinity(scip, -lb));
11742 assert(!SCIPisInfinity(scip, ub));
11743
11744 /* update residual activities */
11745 if( vals[w] > 0 )
11746 {
11747 tmpmaxactsub += ub * vals[w];
11748 tmpminactsub += lb * vals[w];
11749 }
11750 else
11751 {
11752 tmpmaxactsub += lb * vals[w];
11753 tmpminactsub += ub * vals[w];
11754 }
11755 assert(tmpmaxactsub >= tmpminactsub);
11756 }
11757
11758 if( hasrhs )
11759 {
11760 assert(offsetv == -1);
11761
11762 /* determine the remainder of the right hand side and the gcd */
11763 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11764 }
11765 else
11766 {
11767 /* determine the remainder of the left hand side and the gcd */
11768 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11769 if( SCIPisZero(scip, siderest) )
11770 siderest = gcd;
11771 }
11772
11773 /* is the redundancy really fulfilled */
11774 assert((hasrhs && SCIPisFeasLE(scip, tmpmaxactsub, siderest) && tmpminactsub > siderest - gcd) ||
11775 (haslhs && tmpmaxactsub < siderest && SCIPisFeasGE(scip, tmpminactsub, siderest - gcd)));
11776#endif
11777
11778 SCIPdebugMsg(scip, "removing %d last variables from constraint <%s>, because they never change anything on the feasibility of this constraint\n",
11779 nvars - v, SCIPconsGetName(cons));
11780
11781 /* remove redundant variables */
11782 for( w = nvars - 1; w >= v; --w )
11783 {
11784 SCIP_CALL( delCoefPos(scip, cons, w) );
11785 }
11786 (*nchgcoefs) += (nvars - v);
11787
11788 assert(w >= 0);
11789
11790 oldcoef = vals[w];
11791
11792 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11793 assert(vars == consdata->vars);
11794 assert(vals == consdata->vals);
11796
11797 if( *infeasible )
11798 return SCIP_OKAY;
11799
11800 /* compute new greatest common divisor due to normalization */
11801 gcd = (SCIP_Longint)(gcd / (oldcoef/vals[w]) + feastol);
11802 assert(gcd >= 1);
11803
11804 /* update side */
11805 if( hasrhs )
11806 {
11807 /* replace old with new right hand side */
11808 SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
11809 rhs = consdata->rhs;
11810 }
11811 else
11812 {
11813 if( SCIPisFeasGT(scip, oldcoef/vals[w], 1.0) )
11814 {
11815 SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
11816 lhs = consdata->lhs;
11817 }
11818 else
11819 assert(offsetv == -1 || SCIPisEQ(scip, vals[offsetv], consdata->lhs));
11820 }
11821 ++(*nchgsides);
11822
11823 assert(!hasrhs || !SCIPisNegative(scip, rhs));
11824 assert(!haslhs || !SCIPisNegative(scip, lhs));
11825
11826 /* get new constraint data */
11827 nvars = consdata->nvars;
11828 assert(nvars > 0);
11829
11830 allcoefintegral = TRUE;
11831
11832#ifndef NDEBUG
11833 /* check integrality */
11834 for( w = offsetv + 1; w < nvars; ++w )
11835 {
11836 assert(SCIPisIntegral(scip, vals[w]));
11837 }
11838#endif
11840 }
11841
11842 /* try to find a better gcd, when having large coefficients */
11843 if( offsetv >= 0 && gcd == 1 )
11844 {
11845 /* calculate greatest common divisor for all general variables */
11846 gcd = (SCIP_Longint)(REALABS(vals[nvars - 1]) + feastol);
11847
11848 if( gcd > 1 )
11849 {
11850 gcd = -1;
11851 candpos = -1;
11852
11853 for( v = nvars - 1; v > offsetv; --v )
11854 {
11855 assert(!SCIPisZero(scip, vals[v]));
11856 if( !SCIPvarIsIntegral(vars[v]) )
11857 break;
11858
11859 if( !SCIPisIntegral(scip, vals[v]) )
11860 {
11861 allcoefintegral = FALSE;
11862 break;
11863 }
11864
11865 oldgcd = gcd;
11866
11867 if( gcd == -1 )
11868 {
11869 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11870 assert(gcd >= 1);
11871 }
11872 else
11873 {
11874 /* calculate greatest common divisor for all general and binary variables */
11875 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11876 }
11877
11878 /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
11879 * can stop searching
11880 */
11881 if( gcd == 1 )
11882 {
11883 if( !SCIPvarIsBinary(vars[v]) )
11884 break;
11885
11886 /* found candidate */
11887 if( candpos == -1 )
11888 {
11889 gcd = oldgcd;
11890 candpos = v;
11891 }
11892 /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
11893 else
11894 break;
11895 }
11896 }
11897 assert(v > offsetv || candpos > offsetv);
11898 }
11899 else
11900 candpos = -1;
11901 }
11902 else
11903 candpos = nvars - 1;
11904
11905 /* check last coefficient for integrality */
11906 if( gcd > 1 && allcoefintegral && !redundant )
11907 {
11908 if( !SCIPisIntegral(scip, vals[nvars - 1]) )
11909 allcoefintegral = FALSE;
11910 }
11911
11912 /* check for further necessary coefficient adjustments */
11913 if( offsetv >= 0 && gcd > 1 && allcoefintegral )
11914 {
11915 assert(offsetv + 1 < nvars);
11916 assert(0 <= candpos && candpos < nvars);
11917
11918 if( SCIPvarIsIntegral(vars[candpos]) )
11919 {
11920 SCIP_Bool notchangable = FALSE;
11921
11922#ifndef NDEBUG
11923 /* check integrality */
11924 for( w = offsetv + 1; w < nvars; ++w )
11925 {
11926 assert(SCIPisIntegral(scip, vals[w]));
11927 }
11928#endif
11929
11930 if( vals[candpos] > 0 && SCIPvarIsBinary(vars[candpos]) &&
11931 SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) < gcd )
11932 {
11933 /* determine the remainder of the side and the gcd */
11934 if( hasrhs )
11935 rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
11936 else
11937 rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
11938 assert(rest >= 0);
11939 assert(rest < gcd);
11940
11941 /* determine the remainder of the coefficient candidate and the gcd */
11942 restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
11943 assert(restcoef >= 1);
11944 assert(restcoef < gcd);
11945
11946 if( hasrhs )
11947 {
11948 /* calculate new coefficient */
11949 if( restcoef > rest )
11950 newcoef = vals[candpos] - restcoef + gcd;
11951 else
11952 newcoef = vals[candpos] - restcoef;
11953 }
11954 else
11955 {
11956 /* calculate new coefficient */
11957 if( rest == 0 || restcoef < rest )
11958 newcoef = vals[candpos] - restcoef;
11959 else
11960 newcoef = vals[candpos] - restcoef + gcd;
11961 }
11962
11963 /* done */
11964
11965 /* new coeffcient must not be zero if we would loose the implication that a variable needs to be 0 if
11966 * another with the big coefficient was set to 1
11967 */
11968 if( hasrhs && SCIPisZero(scip, newcoef) )
11969 {
11970 notchangable = TRUE;
11971 }
11972 else if( SCIPisZero(scip, newcoef) )
11973 {
11974 /* delete old redundant coefficient */
11975 SCIP_CALL( delCoefPos(scip, cons, candpos) );
11976 ++(*nchgcoefs);
11977 }
11978 else
11979 {
11980 /* replace old with new coefficient */
11981 SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
11982 ++(*nchgcoefs);
11983 }
11984 }
11985 else if( vals[candpos] < 0 || !SCIPvarIsBinary(vars[candpos]) )
11986 {
11987 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol));
11988 }
11989
11990 /* correct side and big coefficients */
11991 if( (!notchangable && hasrhs && ((!SCIPisFeasIntegral(scip, rhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(rhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd))) ||
11992 ( haslhs && (!SCIPisFeasIntegral(scip, lhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(lhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd)) )
11993 {
11994 if( haslhs )
11995 {
11996 newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasCeil(scip, lhs/gcd) * gcd + feastol));
11997
11998 SCIP_CALL( chgLhs(scip, cons, newcoef) );
11999 ++(*nchgsides);
12000 }
12001 else
12002 {
12003 assert(hasrhs);
12004 newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasFloor(scip, rhs/gcd) * gcd + feastol));
12005
12006 SCIP_CALL( chgRhs(scip, cons, newcoef) );
12007 ++(*nchgsides);
12008 }
12009
12010 /* correct coefficients up front */
12011 for( w = offsetv; w >= 0; --w )
12012 {
12013 assert(vals[w] > 0);
12014
12015 SCIP_CALL( chgCoefPos(scip, cons, w, newcoef) );
12016 }
12017 (*nchgcoefs) += (offsetv + 1);
12018 }
12019
12020 if( !notchangable )
12021 {
12022 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12023 assert(vars == consdata->vars);
12024 assert(vals == consdata->vals);
12025
12026 if( *infeasible )
12027 return SCIP_OKAY;
12028
12029 /* get new constraint data */
12030 nvars = consdata->nvars;
12031 assert(nvars >= 2);
12032
12034
12035 lhs = consdata->lhs;
12036 rhs = consdata->rhs;
12037 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12038 assert(!haslhs || !SCIPisNegative(scip, lhs));
12039 }
12040 }
12041 }
12042 }
12043
12044 /* @todo we still can remove continuous variables if they are redundant due to the non-integrality argument */
12045 /* no continuous variables are left over */
12046 if( !SCIPvarIsIntegral(vars[nvars - 1]) )
12047 return SCIP_OKAY;
12048
12049 onlybin = TRUE;
12050 allcoefintegral = TRUE;
12051 /* check if all variables are of binary type */
12052 for( v = nvars - 1; v >= 0; --v )
12053 {
12054 if( !SCIPvarIsBinary(vars[v]) )
12055 onlybin = FALSE;
12056 if( !SCIPisIntegral(scip, vals[v]) )
12057 allcoefintegral = FALSE;
12058 }
12059
12060 /* check if the non-integrality part of all integral variables is smaller than the non-inegrality part of the right
12061 * hand side or bigger than the left hand side respectively, so we can make all of them integral
12062 *
12063 * @todo there are some steps missing ....
12064 */
12065 if( (hasrhs && !SCIPisFeasIntegral(scip, rhs)) || (haslhs && !SCIPisFeasIntegral(scip, lhs)) )
12066 {
12067 SCIP_Real val;
12068 SCIP_Real newval;
12069 SCIP_Real frac = 0.0;
12070 SCIP_Bool found = FALSE;
12071
12072 if( hasrhs )
12073 {
12074 if( allcoefintegral )
12075 {
12076 /* replace old with new right hand side */
12077 SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12078 ++(*nchgsides);
12079 }
12080 else
12081 {
12082 siderest = rhs - SCIPfloor(scip, rhs);
12083
12084 /* try to round down all non-integral coefficients */
12085 for( v = nvars - 1; v >= 0; --v )
12086 {
12087 val = vals[v];
12088
12089 /* add up all possible fractional parts */
12090 if( !SCIPisIntegral(scip, val) )
12091 {
12092 lb = SCIPvarGetLbGlobal(vars[v]);
12093 ub = SCIPvarGetUbGlobal(vars[v]);
12094
12095 /* at least one bound need to be at zero */
12096 if( !onlybin && !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12097 return SCIP_OKAY;
12098
12099 /* swap bounds for 'standard' form */
12100 if( !SCIPisFeasZero(scip, lb) )
12101 {
12102 ub = -lb;
12103 val *= -1;
12104 }
12105
12106 found = TRUE;
12107
12108 frac += (val - SCIPfloor(scip, val)) * ub;
12109
12110 /* if we exceed the fractional part of the right hand side, we cannot tighten the coefficients
12111 *
12112 * e.g. 1.1x1 + 1.1x2 + 1.4x3 + 1.02x4 <= 2.4, here we cannot floor all fractionals because
12113 * x3, x4 set to 1 would be infeasible but feasible after flooring
12114 */
12115 if( SCIPisGT(scip, frac, siderest) )
12116 return SCIP_OKAY;
12117 }
12118 }
12119 assert(v == -1);
12120
12121 SCIPdebugMsg(scip, "rounding all non-integral coefficients and the right hand side down\n");
12122
12123 /* round rhs and coefficients to integral values */
12124 if( found )
12125 {
12126 for( v = nvars - 1; v >= 0; --v )
12127 {
12128 val = vals[v];
12129
12130 /* add the whole fractional part */
12131 if( !SCIPisIntegral(scip, val) )
12132 {
12133 lb = SCIPvarGetLbGlobal(vars[v]);
12134
12135 if( SCIPisFeasZero(scip, lb) )
12136 newval = SCIPfloor(scip, val);
12137 else
12138 newval = SCIPceil(scip, val);
12139
12140 if( SCIPisZero(scip, newval) )
12141 {
12142 /* delete old redundant coefficient */
12143 SCIP_CALL( delCoefPos(scip, cons, v) );
12144 ++(*nchgcoefs);
12145 }
12146 else
12147 {
12148 /* replace old with new coefficient */
12149 SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12150 ++(*nchgcoefs);
12151 }
12152 }
12153 }
12154 }
12155
12156 /* replace old with new right hand side */
12157 SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12158 ++(*nchgsides);
12159 }
12160 }
12161 else
12162 {
12163 if( allcoefintegral )
12164 {
12165 /* replace old with new left hand side */
12166 SCIP_CALL( chgLhs(scip, cons, SCIPceil(scip, lhs)) );
12167 ++(*nchgsides);
12168 }
12169 else
12170 {
12171 /* cannot floor left hand side to zero */
12172 if( SCIPisLT(scip, lhs, 1.0) )
12173 return SCIP_OKAY;
12174
12175 siderest = lhs - SCIPfloor(scip, lhs);
12176
12177 /* try to round down all non-integral coefficients */
12178 for( v = nvars - 1; v >= 0; --v )
12179 {
12180 val = vals[v];
12181
12182 /* add up all possible fractional parts */
12183 if( !SCIPisIntegral(scip, val) )
12184 {
12185 lb = SCIPvarGetLbGlobal(vars[v]);
12186 ub = SCIPvarGetUbGlobal(vars[v]);
12187
12188 /* at least one bound need to be at zero */
12189 if( !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12190 return SCIP_OKAY;
12191
12192 /* swap bounds for 'standard' form */
12193 if( !SCIPisFeasZero(scip, lb) )
12194 {
12195 ub = -lb;
12196 val *= -1;
12197 }
12198
12199 /* cannot floor to zero */
12200 if( SCIPisLT(scip, val, 1.0) )
12201 return SCIP_OKAY;
12202
12203 /* the fractional part on each variable need to exceed the fractional part on the left hand side */
12204 if( SCIPisLT(scip, val - SCIPfloor(scip, val), siderest) )
12205 return SCIP_OKAY;
12206
12207 found = TRUE;
12208
12209 frac += (val - SCIPfloor(scip, val)) * ub;
12210
12211 /* if we exceed the fractional part of the left hand side plus one by summing up all maximal
12212 * fractional parts of the variables, we cannot tighten the coefficients
12213 *
12214 * e.g. 4.3x1 + 1.3x2 + 1.3x3 + 1.6x4 >= 4.2, here we cannot floor all fractionals because
12215 * x2-x4 set to 1 would be feasible but not after flooring
12216 */
12217 if( SCIPisGE(scip, frac, 1 + siderest) )
12218 return SCIP_OKAY;
12219 }
12220 /* all coefficients need to be integral, otherwise we might do an invalid reduction */
12221 else
12222 return SCIP_OKAY;
12223 }
12224 assert(v == -1);
12225
12226 SCIPdebugMsg(scip, "rounding all non-integral coefficients and the left hand side down\n");
12227
12228 /* round lhs and coefficients to integral values */
12229 if( found )
12230 {
12231 for( v = nvars - 1; v >= 0; --v )
12232 {
12233 val = vals[v];
12234
12235 /* add the whole fractional part */
12236 if( !SCIPisIntegral(scip, val) )
12237 {
12238 lb = SCIPvarGetLbGlobal(vars[v]);
12239
12240 if( SCIPisFeasZero(scip, lb) )
12241 newval = SCIPfloor(scip, val);
12242 else
12243 newval = SCIPceil(scip, val);
12244
12245 if( SCIPisZero(scip, newval) )
12246 {
12247 /* delete old redundant coefficient */
12248 SCIP_CALL( delCoefPos(scip, cons, v) );
12249 ++(*nchgcoefs);
12250 }
12251 else
12252 {
12253 /* replace old with new coefficient */
12254 SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12255 ++(*nchgcoefs);
12256 }
12257 }
12258 }
12259 }
12260
12261 /* replace old with new left hand side */
12262 SCIP_CALL( chgLhs(scip, cons, SCIPfloor(scip, lhs)) );
12263 ++(*nchgsides);
12264 }
12265 }
12266
12267 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12268 assert(vars == consdata->vars);
12269 assert(vals == consdata->vals);
12270
12271 if( *infeasible )
12272 return SCIP_OKAY;
12273
12274 rhs = consdata->rhs;
12275 lhs = consdata->lhs;
12276
12277 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12278 assert(!haslhs || !SCIPisNegative(scip, lhs));
12279
12281
12282 nvars = consdata->nvars;
12283 if( nvars < 2 )
12284 return SCIP_OKAY;
12285
12286 allcoefintegral = TRUE;
12287#ifndef NDEBUG
12288 /* debug check if all coefficients are really integral */
12289 for( v = nvars - 1; v >= 0; --v )
12290 assert(SCIPisIntegral(scip, vals[v]));
12291#endif
12292 }
12293
12294 /* @todo following can also work on non integral coefficients, need more investigation */
12295 /* only check constraints with integral coefficients on all integral variables */
12296 if( !allcoefintegral )
12297 return SCIP_OKAY;
12298
12299 /* we want to avoid numerical troubles, therefore we do not change non-integral sides */
12300 if( (hasrhs && !SCIPisIntegral(scip, rhs)) || (haslhs && !SCIPisIntegral(scip, lhs)) )
12301 return SCIP_OKAY;
12302
12303 /* maximal absolute value of coefficients in constraint is one, so we cannot tighten it further */
12304 if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) )
12305 return SCIP_OKAY;
12306
12307 /* stop if the last coeffcients is one in absolute value and the variable is not binary */
12308 if( !SCIPvarIsBinary(vars[nvars - 1]) && SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) )
12309 return SCIP_OKAY;
12310
12311 assert(nvars >= 2);
12312
12313 /* start gcd procedure for all variables */
12314 do
12315 {
12316 SCIPdebug( oldnchgcoefs = *nchgcoefs; )
12317 SCIPdebug( oldnchgsides = *nchgsides; )
12318
12319 /* stop if we have two coeffcients which are one in absolute value */
12320 if( SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) && SCIPisEQ(scip, REALABS(vals[nvars - 2]), 1.0) )
12321 return SCIP_OKAY;
12322
12323 gcd = -1;
12324
12325 /* calculate greatest common divisor over all integer variables; note that the onlybin flag needs to be recomputed
12326 * because coefficients of non-binary variables might have changed to zero */
12327 if( !onlybin )
12328 {
12329 foundbin = -1;
12330 onlybin = TRUE;
12331
12332 for( v = nvars - 1; v >= 0; --v )
12333 {
12334 assert(!SCIPisZero(scip, vals[v]));
12336
12337 if( SCIPvarIsBinary(vars[v]) )
12338 {
12339 if( foundbin == -1 )
12340 foundbin = v;
12341 continue;
12342 }
12343 else
12344 onlybin = FALSE;
12345
12346 absval = REALABS(vals[v]);
12347 /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12348 * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12349 */
12350 assert(SCIPisFeasIntegral(scip, absval));
12351
12352 if( gcd == -1 )
12353 {
12354 gcd = (SCIP_Longint)(absval + feastol);
12355 assert(gcd >= 1);
12356 }
12357 else
12358 {
12359 /* calculate greatest common divisor for all general variables */
12360 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(absval + feastol));
12361 }
12362 if( gcd == 1 )
12363 break;
12364 }
12365 }
12366 else
12367 foundbin = nvars - 1;
12368
12369 /* we need at least one binary variable and a gcd greater than 1 to try to perform further coefficient changes */
12370 if( gcd == 1 || foundbin == -1)
12371 return SCIP_OKAY;
12372
12373 assert((onlybin && gcd == -1) || (!onlybin && gcd > 1));
12374
12375 candpos = -1;
12376 candpos2 = -1;
12377
12378 /* calculate greatest common divisor over all integer and binary variables and determine the candidate where we might
12379 * change the coefficient
12380 */
12381 for( v = foundbin; v >= 0; --v )
12382 {
12383 if( onlybin || SCIPvarIsBinary(vars[v]) )
12384 {
12385 absval = REALABS(vals[v]);
12386 /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12387 * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12388 */
12389 assert(SCIPisFeasIntegral(scip, absval));
12390
12391 oldgcd = gcd;
12392
12393 if( gcd == -1 )
12394 {
12395 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12396 assert(gcd >= 1);
12397 }
12398 else
12399 {
12400 /* calculate greatest common divisor for all general and binary variables */
12401 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12402 }
12403
12404 /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12405 * can terminate
12406 */
12407 if( gcd == 1 )
12408 {
12409 /* found candidate */
12410 if( candpos == -1 )
12411 {
12412 gcd = oldgcd;
12413 candpos = v;
12414
12415 /* if we have only binary variables and both first coefficients have a gcd of 1, both are candidates for
12416 * the coefficient change
12417 */
12418 if( onlybin && v == foundbin - 1 )
12419 candpos2 = foundbin;
12420 }
12421 /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12422 else
12423 {
12424 if( onlybin && candpos == v + 1 && candpos2 == v + 2 )
12425 {
12426 assert(candpos2 == nvars - 1);
12427
12428 /* take new candidates */
12429 candpos = candpos2;
12430
12431 /* recalculate gcd from scratch */
12432 gcd = (SCIP_Longint)(REALABS(vals[v+1]) + feastol);
12433 assert(gcd >= 1);
12434
12435 /* calculate greatest common divisor for all general and binary variables */
12436 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12437 if( gcd == 1 )
12438 return SCIP_OKAY;
12439 }
12440 else
12441 /* cannot determine a possible coefficient for reduction */
12442 return SCIP_OKAY;
12443 }
12444 }
12445 }
12446 }
12447 assert(gcd >= 2);
12448
12449 /* we should have found one coefficient, that led to a gcd of 1, otherwise we could normalize the constraint
12450 * further
12451 */
12452 assert(candpos >= 0 && candpos < nvars);
12453
12454 /* all variables and all coefficients are integral, so the side should be too */
12455 assert((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs)));
12456
12457 /* check again, if we have a normalized inequality (not ranged) the one side should be positive,
12458 * @see normalizeCons()
12459 */
12460 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12461 assert(!haslhs || !SCIPisNegative(scip, lhs));
12462
12463 /* determine the remainder of the side and the gcd */
12464 if( hasrhs )
12465 rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12466 else
12467 rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12468 assert(rest >= 0);
12469 assert(rest < gcd);
12470
12471 /* determine the remainder of the coefficient candidate and the gcd */
12472 if( vals[candpos] < 0 )
12473 {
12474 restcoef = ((SCIP_Longint)(vals[candpos] - feastol)) % gcd;
12475 assert(restcoef <= -1);
12476 restcoef += gcd;
12477 }
12478 else
12479 restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12480 assert(restcoef >= 1);
12481 assert(restcoef < gcd);
12482
12483 if( hasrhs )
12484 {
12485 if( rest > 0 )
12486 {
12487 /* replace old with new right hand side */
12488 SCIP_CALL( chgRhs(scip, cons, rhs - rest) );
12489 ++(*nchgsides);
12490 }
12491
12492 /* calculate new coefficient */
12493 if( restcoef > rest )
12494 newcoef = vals[candpos] - restcoef + gcd;
12495 else
12496 newcoef = vals[candpos] - restcoef;
12497 }
12498 else
12499 {
12500 if( rest > 0 )
12501 {
12502 /* replace old with new left hand side */
12503 SCIP_CALL( chgLhs(scip, cons, lhs - rest + gcd) );
12504 ++(*nchgsides);
12505 }
12506
12507 /* calculate new coefficient */
12508 if( rest == 0 || restcoef < rest )
12509 newcoef = vals[candpos] - restcoef;
12510 else
12511 newcoef = vals[candpos] - restcoef + gcd;
12512 }
12513 assert(SCIPisZero(scip, newcoef) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(newcoef) + feastol)) == gcd);
12514
12515 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));
12516
12517 if( SCIPisZero(scip, newcoef) )
12518 {
12519 /* delete redundant coefficient */
12520 SCIP_CALL( delCoefPos(scip, cons, candpos) );
12521 }
12522 else
12523 {
12524 /* replace old with new coefficient */
12525 SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12526 }
12527 ++(*nchgcoefs);
12528
12529 /* now constraint can be normalized, might be directly done by dividing it by the gcd */
12530 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12531 assert(vars == consdata->vars);
12532 assert(vals == consdata->vals);
12533
12534 if( *infeasible )
12535 return SCIP_OKAY;
12536
12538
12539 rhs = consdata->rhs;
12540 lhs = consdata->lhs;
12541 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12542 assert(!haslhs || !SCIPisNegative(scip, lhs));
12543
12544 nvars = consdata->nvars;
12545
12546 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));
12547 }
12548 while( nvars >= 2 );
12549
12550 return SCIP_OKAY;
12551}
12552
12553
12554/** tries to aggregate an (in)equality and an equality in order to decrease the number of variables in the (in)equality:
12555 * cons0 := a * cons0 + b * cons1,
12556 * where a = val1[v] and b = -val0[v] for common variable v which removes most variable weight;
12557 * for numerical stability, we will only accept integral a and b;
12558 * the variable weight is a weighted sum over all included variables, where each binary variable weighs BINWEIGHT,
12559 * each integer or implied integral variable weighs INTWEIGHT and each continuous variable weighs CONTWEIGHT
12560 */
12561static
12563 SCIP* scip, /**< SCIP data structure */
12564 SCIP_CONS* cons0, /**< (in)equality to modify */
12565 SCIP_CONS* cons1, /**< equality to use for aggregation of cons0 */
12566 int* commonidx0, /**< array with indices of variables in cons0, that appear also in cons1 */
12567 int* commonidx1, /**< array with indices of variables in cons1, that appear also in cons0 */
12568 int* diffidx0minus1, /**< array with indices of variables in cons0, that don't appear in cons1 */
12569 int* diffidx1minus0, /**< array with indices of variables in cons1, that don't appear in cons0 */
12570 int nvarscommon, /**< number of variables, that appear in both constraints */
12571 int commonidxweight, /**< variable weight sum of common variables */
12572 int diffidx0minus1weight, /**< variable weight sum of variables in cons0, that don't appear in cons1 */
12573 int diffidx1minus0weight, /**< variable weight sum of variables in cons1, that don't appear in cons0 */
12574 SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
12575 int* nchgcoefs, /**< pointer to count the number of changed coefficients */
12576 SCIP_Bool* aggregated, /**< pointer to store whether an aggregation was made */
12577 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
12578 )
12579{
12580 SCIP_CONSDATA* consdata0;
12581 SCIP_CONSDATA* consdata1;
12582 SCIP_Real a;
12583 SCIP_Real b;
12584 SCIP_Real aggrcoef;
12585 SCIP_Real scalarsum;
12586 SCIP_Real bestscalarsum;
12587 SCIP_Bool betterscalarsum;
12588 SCIP_Bool commonvarlindependent; /* indicates whether coefficient vector of common variables in linearly dependent */
12589 int varweight;
12590 int nvars;
12591 int bestvarweight;
12592 int bestnvars;
12593 int bestv;
12594 int v;
12595 int i;
12596
12597 assert(scip != NULL);
12598 assert(cons0 != NULL);
12599 assert(cons1 != NULL);
12600 assert(commonidx0 != NULL);
12601 assert(commonidx1 != NULL);
12602 assert(diffidx0minus1 != NULL);
12603 assert(diffidx1minus0 != NULL);
12604 assert(nvarscommon >= 1);
12605 assert(commonidxweight >= nvarscommon);
12606 assert(nchgcoefs != NULL);
12607 assert(aggregated != NULL);
12608
12609 assert(SCIPconsIsActive(cons0));
12610 assert(SCIPconsIsActive(cons1));
12611
12612 *infeasible = FALSE;
12613
12614 SCIPdebugMsg(scip, "try aggregation of <%s> and <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
12615
12616 /* cons0 is an (in)equality */
12617 consdata0 = SCIPconsGetData(cons0);
12618 assert(consdata0 != NULL);
12619 assert(consdata0->nvars >= 1);
12620 assert(SCIPisLE(scip, consdata0->lhs, consdata0->rhs));
12621 assert(diffidx0minus1weight >= consdata0->nvars - nvarscommon);
12622
12623 /* cons1 is an equality */
12624 consdata1 = SCIPconsGetData(cons1);
12625 assert(consdata1 != NULL);
12626 assert(consdata1->nvars >= 1);
12627 assert(SCIPisEQ(scip, consdata1->lhs, consdata1->rhs));
12628 assert(diffidx1minus0weight >= consdata1->nvars - nvarscommon);
12629
12630 *aggregated = FALSE;
12631
12632 /* search for the best common variable such that
12633 * val1[var] * consdata0 - val0[var] * consdata1
12634 * has least weighted number of variables
12635 */
12636 bestvarweight = commonidxweight + diffidx0minus1weight;
12637 bestnvars = consdata0->nvars;
12638 bestv = -1;
12639 bestscalarsum = 0.0;
12640 commonvarlindependent = TRUE;
12641 for( v = 0; v < nvarscommon; ++v )
12642 {
12643 assert(consdata0->vars[commonidx0[v]] == consdata1->vars[commonidx1[v]]);
12644 a = consdata1->vals[commonidx1[v]];
12645 b = -consdata0->vals[commonidx0[v]];
12646
12647 /* only try aggregation, if coefficients are integral (numerical stability) */
12649 {
12650 /* count the number of variables in the potential new constraint a * consdata0 + b * consdata1 */
12651 varweight = diffidx0minus1weight + diffidx1minus0weight;
12652 nvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12653 scalarsum = REALABS(a) + REALABS(b);
12654 betterscalarsum = (scalarsum < bestscalarsum);
12655 for( i = 0; i < nvarscommon
12656 && (varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum)); ++i )
12657 {
12658 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12659 if( !SCIPisZero(scip, aggrcoef) )
12660 {
12661 varweight += getVarWeight(consdata0->vars[commonidx0[i]]);
12662 nvars++;
12663 }
12664 }
12665 if( varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum) )
12666 {
12667 bestv = v;
12668 bestvarweight = varweight;
12669 bestnvars = nvars;
12670 bestscalarsum = scalarsum;
12671 }
12672 }
12673
12674 /* update commonvarlindependent flag, if still TRUE:
12675 * 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
12676 */
12677 if( commonvarlindependent && v > 0 )
12678 commonvarlindependent = SCIPisEQ(scip,
12679 consdata1->vals[commonidx1[v]] * consdata0->vals[commonidx0[0]],
12680 consdata1->vals[commonidx1[0]] * consdata0->vals[commonidx0[v]]);
12681 }
12682
12683 /* if better aggregation was found, create new constraint and delete old one */
12684 if( (bestv != -1 || commonvarlindependent) && SCIPconsGetNUpgradeLocks(cons0) == 0 )
12685 {
12686 SCIP_CONS* newcons;
12687 SCIP_CONSDATA* newconsdata;
12688 SCIP_VAR** newvars;
12689 SCIP_Real* newvals;
12690 SCIP_Real newlhs;
12691 SCIP_Real newrhs;
12692 int newnvars;
12693
12694 if( bestv != -1 )
12695 {
12696 /* choose multipliers such that the multiplier for the (in)equality cons0 is positive */
12697 if( consdata1->vals[commonidx1[bestv]] > 0.0 )
12698 {
12699 a = consdata1->vals[commonidx1[bestv]];
12700 b = -consdata0->vals[commonidx0[bestv]];
12701 }
12702 else
12703 {
12704 a = -consdata1->vals[commonidx1[bestv]];
12705 b = consdata0->vals[commonidx0[bestv]];
12706 }
12710 assert(!SCIPisZero(scip, b));
12711 }
12712 else
12713 {
12714 assert(commonvarlindependent);
12715 if( consdata1->vals[commonidx1[0]] > 0.0 )
12716 {
12717 a = consdata1->vals[commonidx1[0]];
12718 b = -consdata0->vals[commonidx0[0]];
12719 }
12720 else
12721 {
12722 a = -consdata1->vals[commonidx1[0]];
12723 b = consdata0->vals[commonidx0[0]];
12724 }
12726 assert(!SCIPisZero(scip, b));
12727
12728 /* if a/b is integral, then we can easily choose integer multipliers */
12729 if( SCIPisIntegral(scip, a/b) )
12730 {
12731 if( a/b > 0 )
12732 {
12733 a /= b;
12734 b = 1.0;
12735 }
12736 else
12737 {
12738 a /= -b;
12739 b = -1.0;
12740 }
12741 }
12742
12743 /* setup best* variables that were not setup above because we are in the commonvarlindependent case */
12744 SCIPdebug( bestvarweight = diffidx0minus1weight + diffidx1minus0weight; )
12745 bestnvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12746 }
12747
12748 SCIPdebugMsg(scip, "aggregate linear constraints <%s> := %.15g*<%s> + %.15g*<%s> -> nvars: %d -> %d, weight: %d -> %d\n",
12749 SCIPconsGetName(cons0), a, SCIPconsGetName(cons0), b, SCIPconsGetName(cons1),
12750 consdata0->nvars, bestnvars, commonidxweight + diffidx0minus1weight, bestvarweight);
12751 SCIPdebugPrintCons(scip, cons0, NULL);
12752 SCIPdebugPrintCons(scip, cons1, NULL);
12753
12754 /* get temporary memory for creating the new linear constraint */
12755 SCIP_CALL( SCIPallocBufferArray(scip, &newvars, bestnvars) );
12756 SCIP_CALL( SCIPallocBufferArray(scip, &newvals, bestnvars) );
12757
12758 /* calculate the common coefficients, if we have not recognized linear dependency */
12759 newnvars = 0;
12760 if( !commonvarlindependent )
12761 {
12762 for( i = 0; i < nvarscommon; ++i )
12763 {
12764 assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12765 assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12766
12767 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12768 if( !SCIPisZero(scip, aggrcoef) )
12769 {
12770 assert(newnvars < bestnvars);
12771 newvars[newnvars] = consdata0->vars[commonidx0[i]];
12772 newvals[newnvars] = aggrcoef;
12773 newnvars++;
12774 }
12775 }
12776 }
12777 else
12778 {
12779 /* if we recognized linear dependency of the common coefficients, then the aggregation coefficient should be 0.0 for every common variable */
12780#ifndef NDEBUG
12781 for( i = 0; i < nvarscommon; ++i )
12782 {
12783 assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12784 assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12785
12786 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12787 assert(SCIPisZero(scip, aggrcoef));
12788 }
12789#endif
12790 }
12791
12792 /* calculate the coefficients appearing in cons0 but not in cons1 */
12793 for( i = 0; i < consdata0->nvars - nvarscommon; ++i )
12794 {
12795 assert(0 <= diffidx0minus1[i] && diffidx0minus1[i] < consdata0->nvars);
12796
12797 aggrcoef = a * consdata0->vals[diffidx0minus1[i]];
12798 assert(!SCIPisZero(scip, aggrcoef));
12799 assert(newnvars < bestnvars);
12800 newvars[newnvars] = consdata0->vars[diffidx0minus1[i]];
12801 newvals[newnvars] = aggrcoef;
12802 newnvars++;
12803 }
12804
12805 /* calculate the coefficients appearing in cons1 but not in cons0 */
12806 for( i = 0; i < consdata1->nvars - nvarscommon; ++i )
12807 {
12808 assert(0 <= diffidx1minus0[i] && diffidx1minus0[i] < consdata1->nvars);
12809
12810 aggrcoef = b * consdata1->vals[diffidx1minus0[i]];
12811 assert(!SCIPisZero(scip, aggrcoef));
12812 assert(newnvars < bestnvars);
12813 newvars[newnvars] = consdata1->vars[diffidx1minus0[i]];
12814 newvals[newnvars] = aggrcoef;
12815 newnvars++;
12816 }
12817 assert(newnvars == bestnvars);
12818
12819 /* calculate the new left and right hand side of the (in)equality */
12820 assert(!SCIPisInfinity(scip, -consdata1->lhs));
12821 assert(!SCIPisInfinity(scip, consdata1->rhs));
12822 if( SCIPisInfinity(scip, -consdata0->lhs) )
12823 newlhs = -SCIPinfinity(scip);
12824 else
12825 newlhs = a * consdata0->lhs + b * consdata1->lhs;
12826 if( SCIPisInfinity(scip, consdata0->rhs) )
12827 newrhs = SCIPinfinity(scip);
12828 else
12829 newrhs = a * consdata0->rhs + b * consdata1->rhs;
12830
12831 /* create the new linear constraint */
12832 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, SCIPconsGetName(cons0), newnvars, newvars, newvals, newlhs, newrhs,
12837
12838 newconsdata = SCIPconsGetData(newcons);
12839 assert(newconsdata != NULL);
12840
12841 /* copy the upgraded flag from the old cons0 to the new constraint */
12842 newconsdata->upgraded = consdata0->upgraded;
12843
12844 SCIP_CALL( normalizeCons(scip, newcons, infeasible) );
12845
12846 /* check, if we really want to use the new constraint instead of the old one:
12847 * use the new one, if the maximum norm doesn't grow too much
12848 */
12849 if( !(*infeasible) && consdataGetMaxAbsval(SCIPconsGetData(newcons)) <= maxaggrnormscale * consdataGetMaxAbsval(consdata0) )
12850 {
12851 SCIPdebugMsg(scip, " -> aggregated to <%s>\n", SCIPconsGetName(newcons));
12852 SCIPdebugPrintCons(scip, newcons, NULL);
12853
12854 /* update the statistics: we changed all coefficients */
12855 if( !consdata0->upgraded )
12856 (*nchgcoefs) += consdata0->nvars + consdata1->nvars - nvarscommon;
12857 *aggregated = TRUE;
12858
12859 /* add the new linear constraint to the problem and delete the old constraint */
12860 SCIP_CALL( SCIPaddConsUpgrade(scip, cons0, &newcons) );
12861 SCIP_CALL( SCIPdelCons(scip, cons0) );
12862 }
12863 else
12864 {
12865 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
12866 }
12867
12868 /* free temporary memory */
12869 SCIPfreeBufferArray(scip, &newvals);
12870 SCIPfreeBufferArray(scip, &newvars);
12871 }
12872
12873 return SCIP_OKAY;
12874}
12875
12876/** gets the key of the given element */
12877static
12878SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
12879{ /*lint --e{715}*/
12880 /* the key is the element itself */
12881 return elem;
12882}
12883
12884/** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables and the
12885 * coefficients are either equal or negated
12886 */
12887static
12888SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
12889{
12890 SCIP* scip;
12891 SCIP_CONSDATA* consdata1;
12892 SCIP_CONSDATA* consdata2;
12893 SCIP_Real minscale;
12894 SCIP_Real maxscale;
12895 int i;
12896
12897 assert(key1 != NULL);
12898 assert(key2 != NULL);
12899 consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
12900 consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
12901 assert(consdata1->indexsorted);
12902 assert(consdata2->indexsorted);
12903
12904 scip = (SCIP*)userptr;
12905 assert(scip != NULL);
12906
12907 /* if it is the same constraint we dont need to check anything */
12908 if( key1 == key2 )
12909 return TRUE;
12910
12911 /* checks trivial case */
12912 if( consdata1->nvars != consdata2->nvars )
12913 return FALSE;
12914
12915 /* tests if variables are equal */
12916 for( i = 0; i < consdata1->nvars; ++i )
12917 {
12918 if( consdata1->vars[i] != consdata2->vars[i] )
12919 {
12920 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
12921 SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
12922 return FALSE;
12923 }
12924 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
12925 }
12926
12927 /* order by maxabsval */
12928 if( consdataGetMaxAbsval(consdata1) > consdataGetMaxAbsval(consdata2) )
12929 SCIPswapPointers((void**)&consdata1, (void**)&consdata2);
12930
12931 /* initialize extremal scales */
12932 minscale = SCIPinfinity(scip);
12933 maxscale = -SCIPinfinity(scip);
12934
12935 /* test if coefficient scales are equal */
12936 for( i = 0; i < consdata1->nvars; ++i )
12937 {
12938 SCIP_Real scale = consdata2->vals[i] / consdata1->vals[i];
12939
12940 if( minscale > scale )
12941 {
12942 minscale = scale;
12943
12944 if( SCIPisLT(scip, minscale, maxscale) )
12945 return FALSE;
12946 }
12947
12948 if( maxscale < scale )
12949 {
12950 maxscale = scale;
12951
12952 if( SCIPisLT(scip, minscale, maxscale) )
12953 return FALSE;
12954 }
12955 }
12956
12957 return TRUE;
12958}
12959
12960/** returns the hash value of the key */
12961static
12962SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
12963{
12964 SCIP_CONSDATA* consdata;
12965 int minidx;
12966 int mididx;
12967 int maxidx;
12968#ifndef NDEBUG
12969 SCIP* scip;
12970
12971 scip = (SCIP*)userptr;
12972 assert(scip != NULL);
12973#endif
12974
12975 assert(key != NULL);
12976 consdata = SCIPconsGetData((SCIP_CONS*)key);
12977 assert(consdata != NULL);
12978 assert(consdata->nvars > 0);
12979
12980 assert(consdata->indexsorted);
12981
12982 minidx = SCIPvarGetIndex(consdata->vars[0]);
12983 mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
12984 maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
12985
12986 /* using only the variable indices as hash, since the values are compared by epsilon */
12987 return SCIPhashFour(consdata->nvars, minidx, mididx, maxidx);
12988}
12989
12990/** returns the key for deciding which of two parallel constraints should be kept (smaller key should be kept);
12991 * prefers non-upgraded constraints and as second criterion the constraint with the smallest position
12992 */
12993static
12995 SCIP_CONS* cons /**< linear constraint */
12996 )
12997{
12998 SCIP_CONSDATA* consdata;
12999
13000 assert(cons != NULL);
13001
13002 consdata = SCIPconsGetData(cons);
13003 assert(consdata != NULL);
13004
13005 return (((unsigned int)consdata->upgraded)<<31) + (unsigned int)SCIPconsGetPos(cons); /*lint !e571*/
13006}
13007
13008/** updates the hashtable such that out of all constraints in the hashtable that are detected
13009 * to be parallel to *querycons, only one is kept in the hashtable and stored into *querycons,
13010 * and all others are removed from the hashtable and stored in the given array
13011 */
13012static
13014 SCIP_HASHTABLE* hashtable, /**< hashtable containing linear constraints */
13015 SCIP_CONS** querycons, /**< pointer to linear constraint used to look for duplicates in the hash table;
13016 * upon return will contain the constraint that should be kept */
13017 SCIP_CONS** parallelconss, /**< array to return constraints that are parallel to the given;
13018 * these constraints where removed from the hashtable */
13019 int* nparallelconss /**< pointer to return number of parallel constraints */
13020 )
13021{
13022 SCIP_CONS* parallelcons;
13023 unsigned int querykey;
13024
13025 *nparallelconss = 0;
13026 querykey = getParallelConsKey(*querycons);
13027
13028 while( (parallelcons = (SCIP_CONS*)SCIPhashtableRetrieve(hashtable, (void*)(*querycons))) != NULL )
13029 {
13030 unsigned int conskey = getParallelConsKey(parallelcons);
13031
13032 if( conskey < querykey )
13033 {
13034 parallelconss[(*nparallelconss)++] = *querycons;
13035 *querycons = parallelcons;
13036 querykey = conskey;
13037 }
13038 else
13039 {
13040 parallelconss[(*nparallelconss)++] = parallelcons;
13041 }
13042
13043 /* if the constraint that just came out of the hash table is the one that is kept,
13044 * we do not need to look into the hashtable again, since the invariant is that
13045 * in the hashtable only pair-wise non-parallel constraints are contained.
13046 * For the original querycons, however, multiple constraints that compare equal (=parallel)
13047 * could be contained due to non-transitivity of the equality comparison.
13048 * Also we can return immediately, since parallelcons is already contained in the
13049 * hashtable and we do not need to remove and reinsert it.
13050 */
13051 if( *querycons == parallelcons )
13052 return SCIP_OKAY;
13053
13054 /* remove parallelcons from the hashtable, since it will be replaced by querycons */
13055 SCIP_CALL( SCIPhashtableRemove(hashtable, (void*) parallelcons) );
13056 }
13057
13058 /* in debug mode we make sure, that the hashtable cannot contain a constraint that
13059 * comnpares equal to querycons at this point
13060 */
13061#ifndef NDEBUG
13062 SCIP_CALL_ABORT( SCIPhashtableSafeInsert(hashtable, *querycons) );
13063#else
13064 SCIP_CALL( SCIPhashtableInsert(hashtable, *querycons) );
13065#endif
13066
13067 return SCIP_OKAY;
13068}
13069
13070/** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
13071 * accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
13072 */
13073static
13075 SCIP* scip, /**< SCIP data structure */
13076 BMS_BLKMEM* blkmem, /**< block memory */
13077 SCIP_CONS** conss, /**< constraint set */
13078 int nconss, /**< number of constraints in constraint set */
13079 int* firstchange, /**< pointer to store first changed constraint */
13080 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13081 int* ndelconss, /**< pointer to count number of deleted constraints */
13082 int* nchgsides /**< pointer to count number of changed left/right hand sides */
13083 )
13084{
13085 SCIP_HASHTABLE* hashtable;
13086 SCIP_CONS** parallelconss;
13087 int nparallelconss;
13088 int hashtablesize;
13089 int c;
13090
13091 assert(scip != NULL);
13092 assert(blkmem != NULL);
13093 assert(conss != NULL);
13094 assert(firstchange != NULL);
13095 assert(cutoff != NULL);
13096 assert(ndelconss != NULL);
13097 assert(nchgsides != NULL);
13098
13099 /* create a hash table for the constraint set */
13100 hashtablesize = nconss;
13101 SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
13102 hashGetKeyLinearcons, hashKeyEqLinearcons, hashKeyValLinearcons, (void*) scip) );
13103
13104 SCIP_CALL( SCIPallocBufferArray(scip, &parallelconss, nconss) );
13105
13106 /* check all constraints in the given set for redundancy */
13107 for( c = 0; c < nconss; ++c )
13108 {
13109 SCIP_CONS* cons0;
13110 SCIP_CONSDATA* consdata0;
13111
13112 cons0 = conss[c];
13113
13114 if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
13115 continue;
13116
13117 /* do not check for parallel constraints if they should not be upgraded */
13118 if ( SCIPconsGetNUpgradeLocks(cons0) > 0 )
13119 continue;
13120
13121 /* check for interuption */
13122 if( c % 1000 == 0 && SCIPisStopped(scip) )
13123 break;
13124
13125 /* sorts the constraint */
13126 consdata0 = SCIPconsGetData(cons0);
13127 assert(consdata0 != NULL);
13128 SCIP_CALL( consdataSort(scip, consdata0) );
13129 assert(consdata0->indexsorted);
13130
13131 /* get constraints from current hash table with same variables as cons0 and with coefficients equal
13132 * to the ones of cons0 when both are scaled such that maxabsval is 1.0 and the coefficient of the
13133 * first variable is positive
13134 * Also inserts cons0 into the hashtable.
13135 */
13136 SCIP_CALL( retrieveParallelConstraints(hashtable, &cons0, parallelconss, &nparallelconss) );
13137
13138 if( nparallelconss != 0 )
13139 {
13140 SCIP_Real lhs;
13141 SCIP_Real rhs;
13142
13143 int i;
13144
13145 /* cons0 may have been changed in retrieveParallelConstraints() */
13146 consdata0 = SCIPconsGetData(cons0);
13147
13148 lhs = consdata0->lhs;
13149 rhs = consdata0->rhs;
13150
13151 for( i = 0; i < nparallelconss; ++i )
13152 {
13153 SCIP_CONS* consdel;
13154 SCIP_CONSDATA* consdatadel;
13155 SCIP_Real scale;
13156
13157 consdel = parallelconss[i];
13158 consdatadel = SCIPconsGetData(consdel);
13159
13160 /* do not delete constraint if it should not be upgraded */
13161 if ( SCIPconsGetNUpgradeLocks(consdel) > 0 )
13162 continue;
13163
13164 assert(SCIPconsIsActive(consdel));
13165 assert(!SCIPconsIsModifiable(consdel));
13166
13167 /* constraint found: create a new constraint with same coefficients and best left and right hand side;
13168 * delete old constraints afterwards
13169 */
13170 assert(consdatadel != NULL);
13171 assert(consdata0->nvars >= 1 && consdata0->nvars == consdatadel->nvars);
13172
13173 assert(consdatadel->indexsorted);
13174 assert(consdata0->vars[0] == consdatadel->vars[0]);
13175
13176 scale = consdata0->vals[0] / consdatadel->vals[0];
13177 assert(scale != 0.0);
13178
13179 /* in debug mode, check that all coefficients are equal with respect to epsilon
13180 * if the constraints are in equilibrium scale
13181 */
13182#ifndef NDEBUG
13183 {
13184 assert(consdata0->validmaxabsval);
13185 assert(consdatadel->validmaxabsval);
13186 int k;
13187 SCIP_Real scale0 = 1.0 / consdata0->maxabsval;
13188 SCIP_Real scaledel = COPYSIGN(1.0 / consdatadel->maxabsval, scale);
13189
13190 for( k = 0; k < consdata0->nvars; ++k )
13191 {
13192 assert(SCIPisEQ(scip, scale0 * consdata0->vals[k], scaledel * consdatadel->vals[k]));
13193 }
13194 }
13195#endif
13196
13197 if( scale > 0.0 )
13198 {
13199 /* the coefficients of both constraints are parallel with a positive scale */
13200 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with equal coefficients into single ranged row\n",
13201 SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13202 SCIPdebugPrintCons(scip, cons0, NULL);
13203 SCIPdebugPrintCons(scip, consdel, NULL);
13204
13205 if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13206 lhs = MAX(scale * consdatadel->lhs, lhs);
13207
13208 if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13209 rhs = MIN(scale * consdatadel->rhs, rhs);
13210 }
13211 else
13212 {
13213 /* the coefficients of both rows are negations */
13214 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with negated coefficients into single ranged row\n",
13215 SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13216 SCIPdebugPrintCons(scip, cons0, NULL);
13217 SCIPdebugPrintCons(scip, consdel, NULL);
13218
13219 if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13220 lhs = MAX(scale * consdatadel->rhs, lhs);
13221
13222 if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13223 rhs = MIN(scale * consdatadel->lhs, rhs);
13224 }
13225
13226 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13227 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, consdel) );
13228
13229 /* delete consdel */
13230 assert( ! consdata0->upgraded || consdatadel->upgraded );
13231 SCIP_CALL( SCIPdelCons(scip, consdel) );
13232 if( !consdatadel->upgraded )
13233 (*ndelconss)++;
13234 }
13235
13236 if( SCIPisFeasLT(scip, rhs, lhs) )
13237 {
13238 SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13239 *cutoff = TRUE;
13240 break;
13241 }
13242
13243 /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
13244 if( lhs > rhs )
13245 {
13246 rhs = (lhs + rhs)/2;
13247 lhs = rhs;
13248 }
13249
13250 /* update lhs and rhs of cons0 */
13251 SCIP_CALL( chgLhs(scip, cons0, lhs) );
13252 SCIP_CALL( chgRhs(scip, cons0, rhs) );
13253
13254 /* update the first changed constraint to begin the next aggregation round with */
13255 if( consdata0->changed && SCIPconsGetPos(cons0) < *firstchange )
13256 *firstchange = SCIPconsGetPos(cons0);
13257
13258 assert(SCIPconsIsActive(cons0));
13259 }
13260 }
13261#ifdef SCIP_MORE_DEBUG
13262 SCIPinfoMessage(scip, NULL, "linear pairwise comparison hashtable statistics:\n");
13264#endif
13265
13266 SCIPfreeBufferArray(scip, &parallelconss);
13267
13268 /* free hash table */
13269 SCIPhashtableFree(&hashtable);
13270
13271 return SCIP_OKAY;
13272}
13273
13274/** compares constraint with all prior constraints for possible redundancy or aggregation,
13275 * and removes or changes constraint accordingly
13276 */
13277static
13279 SCIP* scip, /**< SCIP data structure */
13280 SCIP_CONS** conss, /**< constraint set */
13281 int firstchange, /**< first constraint that changed since last pair preprocessing round */
13282 int chkind, /**< index of constraint to check against all prior indices upto startind */
13283 SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
13284 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13285 int* ndelconss, /**< pointer to count number of deleted constraints */
13286 int* nchgsides, /**< pointer to count number of changed left/right hand sides */
13287 int* nchgcoefs /**< pointer to count number of changed coefficients */
13288 )
13289{
13290 SCIP_CONS* cons0;
13291 SCIP_CONSDATA* consdata0;
13292 int* commonidx0;
13293 int* commonidx1;
13294 int* diffidx0minus1;
13295 int* diffidx1minus0;
13296 uint64_t possignature0;
13297 uint64_t negsignature0;
13298 SCIP_Bool cons0changed;
13299 SCIP_Bool cons0isequality;
13300 int diffidx1minus0size;
13301 int c;
13302 SCIP_Real cons0lhs;
13303 SCIP_Real cons0rhs;
13304 SCIP_Bool cons0upgraded;
13305
13306 assert(scip != NULL);
13307 assert(conss != NULL);
13308 assert(firstchange <= chkind);
13309 assert(cutoff != NULL);
13310 assert(ndelconss != NULL);
13311 assert(nchgsides != NULL);
13312 assert(nchgcoefs != NULL);
13313
13314 /* get the constraint to be checked against all prior constraints */
13315 cons0 = conss[chkind];
13316 assert(cons0 != NULL);
13317 assert(SCIPconsIsActive(cons0));
13319
13320 consdata0 = SCIPconsGetData(cons0);
13321 assert(consdata0 != NULL);
13322 assert(consdata0->nvars >= 1);
13323 cons0isequality = SCIPisEQ(scip, consdata0->lhs, consdata0->rhs);
13324
13325 /* sort the constraint */
13326 SCIP_CALL( consdataSort(scip, consdata0) );
13327
13328 /* calculate bit signatures of cons0 for potentially positive and negative coefficients */
13329 consdataCalcSignatures(consdata0);
13330 possignature0 = consdata0->possignature;
13331 negsignature0 = consdata0->negsignature;
13332
13333 /* get temporary memory for indices of common variables */
13334 SCIP_CALL( SCIPallocBufferArray(scip, &commonidx0, consdata0->nvars) );
13335 SCIP_CALL( SCIPallocBufferArray(scip, &commonidx1, consdata0->nvars) );
13336 SCIP_CALL( SCIPallocBufferArray(scip, &diffidx0minus1, consdata0->nvars) );
13337 SCIP_CALL( SCIPallocBufferArray(scip, &diffidx1minus0, consdata0->nvars) );
13338 diffidx1minus0size = consdata0->nvars;
13339
13340 cons0lhs = consdata0->lhs;
13341 cons0rhs = consdata0->rhs;
13342 cons0upgraded = consdata0->upgraded;
13343
13344 /* check constraint against all prior constraints */
13345 cons0changed = consdata0->changed;
13346 consdata0->changed = FALSE;
13347 for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && conss[chkind] != NULL; ++c )
13348 {
13349 SCIP_CONS* cons1;
13350 SCIP_CONSDATA* consdata1;
13351 uint64_t possignature1;
13352 uint64_t negsignature1;
13353 SCIP_Bool cons0dominateslhs;
13354 SCIP_Bool cons1dominateslhs;
13355 SCIP_Bool cons0dominatesrhs;
13356 SCIP_Bool cons1dominatesrhs;
13357 SCIP_Bool cons1isequality;
13358 SCIP_Bool coefsequal;
13359 SCIP_Bool coefsnegated;
13360 SCIP_Bool tryaggregation;
13361 int nvarscommon;
13362 int nvars0minus1;
13363 int nvars1minus0;
13364 int commonidxweight;
13365 int diffidx0minus1weight;
13366 int diffidx1minus0weight;
13367 int v0;
13368 int v1;
13369
13370 assert(cons0lhs == consdata0->lhs); /*lint !e777*/
13371 assert(cons0rhs == consdata0->rhs); /*lint !e777*/
13372 assert(cons0upgraded == consdata0->upgraded);
13373
13374 cons1 = conss[c];
13375
13376 /* cons1 has become inactive during presolving of constraint pairs */
13377 if( cons1 == NULL )
13378 continue;
13379
13380 assert(SCIPconsIsActive(cons0) && !SCIPconsIsModifiable(cons0));
13381 assert(SCIPconsIsActive(cons1) && !SCIPconsIsModifiable(cons1));
13382
13383 consdata1 = SCIPconsGetData(cons1);
13384 assert(consdata1 != NULL);
13385
13386 /* SCIPdebugMsg(scip, "preprocess linear constraint pair <%s>[chgd:%d, upgd:%d] and <%s>[chgd:%d, upgd:%d]\n",
13387 SCIPconsGetName(cons0), cons0changed, cons0upgraded,
13388 SCIPconsGetName(cons1), consdata1->changed, consdata1->upgraded); */
13389
13390 /* if both constraints didn't change since last pair processing, we can ignore the pair */
13391 if( !cons0changed && !consdata1->changed )
13392 continue;
13393
13394 /* if both constraints are already upgraded, skip the pair;
13395 * because changes on these constraints cannot be applied to the instance anymore */
13396 if( cons0upgraded && consdata1->upgraded )
13397 continue;
13398
13399 assert(consdata1->nvars >= 1);
13400
13401 /* sort the constraint */
13402 SCIP_CALL( consdataSort(scip, consdata1) );
13403
13404 /* calculate bit signatures of cons1 for potentially positive and negative coefficients */
13405 consdataCalcSignatures(consdata1);
13406 possignature1 = consdata1->possignature;
13407 negsignature1 = consdata1->negsignature;
13408
13409 /* the signatures give a quick test to check for domination and equality of coefficients */
13410 coefsequal = (possignature0 == possignature1) && (negsignature0 == negsignature1);
13411 coefsnegated = (possignature0 == negsignature1) && (negsignature0 == possignature1);
13412 cons0dominateslhs = SCIPisGE(scip, cons0lhs, consdata1->lhs)
13413 && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13414 && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13415 cons1dominateslhs = SCIPisGE(scip, consdata1->lhs, cons0lhs)
13416 && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13417 && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13418 cons0dominatesrhs = SCIPisLE(scip, cons0rhs, consdata1->rhs)
13419 && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13420 && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13421 cons1dominatesrhs = SCIPisLE(scip, consdata1->rhs, cons0rhs)
13422 && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13423 && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13424 cons1isequality = SCIPisEQ(scip, consdata1->lhs, consdata1->rhs);
13425 tryaggregation = (cons0isequality || cons1isequality) && (maxaggrnormscale > 0.0);
13426 if( !cons0dominateslhs && !cons1dominateslhs && !cons0dominatesrhs && !cons1dominatesrhs
13427 && !coefsequal && !coefsnegated && !tryaggregation )
13428 continue;
13429
13430 /* make sure, we have enough memory for the index set of V_1 \ V_0 */
13431 if( tryaggregation && consdata1->nvars > diffidx1minus0size )
13432 {
13433 SCIP_CALL( SCIPreallocBufferArray(scip, &diffidx1minus0, consdata1->nvars) );
13434 diffidx1minus0size = consdata1->nvars;
13435 }
13436
13437 /* check consdata0 against consdata1:
13438 * - if lhs0 >= lhs1 and for each variable v and each solution value x_v val0[v]*x_v <= val1[v]*x_v,
13439 * consdata0 dominates consdata1 w.r.t. left hand side
13440 * - if rhs0 <= rhs1 and for each variable v and each solution value x_v val0[v]*x_v >= val1[v]*x_v,
13441 * consdata0 dominates consdata1 w.r.t. right hand side
13442 * - if val0[v] == -val1[v] for all variables v, the two inequalities can be replaced by a single
13443 * ranged row (or equality)
13444 * - if at least one constraint is an equality, count the weighted number of common variables W_c
13445 * and the weighted number of variable in the difference sets W_0 = w(V_0 \ V_1), W_1 = w(V_1 \ V_0),
13446 * where the weight of each variable depends on its type, such that aggregations in order to remove the
13447 * number of continuous and integer variables are preferred:
13448 * - if W_c > W_1, try to aggregate consdata0 := a * consdata0 + b * consdata1 in order to decrease the
13449 * variable weight in consdata0, where a = +/- val1[v] and b = -/+ val0[v] for common v which leads to
13450 * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13451 * to be positive to not switch the sense of the (in)equality cons0
13452 * - if W_c > W_0, try to aggregate consdata1 := a * consdata1 + b * consdata0 in order to decrease the
13453 * variable weight in consdata1, where a = +/- val0[v] and b = -/+ val1[v] for common v which leads to
13454 * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13455 * to be positive to not switch the sense of the (in)equality cons1
13456 */
13457
13458 /* check consdata0 against consdata1 for redundancy, or ranged row accumulation */
13459 nvarscommon = 0;
13460 commonidxweight = 0;
13461 nvars0minus1 = 0;
13462 diffidx0minus1weight = 0;
13463 nvars1minus0 = 0;
13464 diffidx1minus0weight = 0;
13465 v0 = 0;
13466 v1 = 0;
13467 while( (v0 < consdata0->nvars || v1 < consdata1->nvars)
13468 && (cons0dominateslhs || cons1dominateslhs || cons0dominatesrhs || cons1dominatesrhs
13469 || coefsequal || coefsnegated || tryaggregation) )
13470 {
13471 SCIP_VAR* var;
13472 SCIP_Real val0;
13473 SCIP_Real val1;
13474 int varcmp;
13475
13476 /* test, if variable appears in only one or in both constraints */
13477 if( v0 < consdata0->nvars && v1 < consdata1->nvars )
13478 varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
13479 else if( v0 < consdata0->nvars )
13480 varcmp = -1;
13481 else
13482 varcmp = +1;
13483
13484 switch( varcmp )
13485 {
13486 case -1:
13487 /* variable doesn't appear in consdata1 */
13488 var = consdata0->vars[v0];
13489 val0 = consdata0->vals[v0];
13490 val1 = 0.0;
13491 if( tryaggregation )
13492 {
13493 diffidx0minus1[nvars0minus1] = v0;
13494 nvars0minus1++;
13495 diffidx0minus1weight += getVarWeight(var);
13496 }
13497 v0++;
13498 coefsequal = FALSE;
13499 coefsnegated = FALSE;
13500 break;
13501
13502 case +1:
13503 /* variable doesn't appear in consdata0 */
13504 var = consdata1->vars[v1];
13505 val0 = 0.0;
13506 val1 = consdata1->vals[v1];
13507 if( tryaggregation )
13508 {
13509 diffidx1minus0[nvars1minus0] = v1;
13510 nvars1minus0++;
13511 diffidx1minus0weight += getVarWeight(var);
13512 }
13513 v1++;
13514 coefsequal = FALSE;
13515 coefsnegated = FALSE;
13516 break;
13517
13518 case 0:
13519 /* variable appears in both constraints */
13520 assert(consdata0->vars[v0] == consdata1->vars[v1]);
13521 var = consdata0->vars[v0];
13522 val0 = consdata0->vals[v0];
13523 val1 = consdata1->vals[v1];
13524 if( tryaggregation )
13525 {
13526 commonidx0[nvarscommon] = v0;
13527 commonidx1[nvarscommon] = v1;
13528 nvarscommon++;
13529 commonidxweight += getVarWeight(var);
13530 }
13531 v0++;
13532 v1++;
13533 coefsequal = coefsequal && (SCIPisEQ(scip, val0, val1));
13534 coefsnegated = coefsnegated && (SCIPisEQ(scip, val0, -val1));
13535 break;
13536
13537 default:
13538 SCIPerrorMessage("invalid comparison result\n");
13539 SCIPABORT();
13540 var = NULL;
13541 val0 = 0.0;
13542 val1 = 0.0;
13543 }
13544 assert(var != NULL);
13545
13546 /* update domination criteria w.r.t. the coefficient and the variable's bounds */
13547 if( SCIPisGT(scip, val0, val1) )
13548 {
13550 {
13551 cons0dominatesrhs = FALSE;
13552 cons1dominateslhs = FALSE;
13553 }
13555 {
13556 cons0dominateslhs = FALSE;
13557 cons1dominatesrhs = FALSE;
13558 }
13559 }
13560 else if( SCIPisLT(scip, val0, val1) )
13561 {
13563 {
13564 cons0dominateslhs = FALSE;
13565 cons1dominatesrhs = FALSE;
13566 }
13568 {
13569 cons0dominatesrhs = FALSE;
13570 cons1dominateslhs = FALSE;
13571 }
13572 }
13573 }
13574
13575 /* check for disaggregated ranged rows */
13576 if( coefsequal || coefsnegated )
13577 {
13578 SCIP_CONS* consstay;
13579 SCIP_CONS* consdel;
13580#ifndef NDEBUG
13581 SCIP_CONSDATA* consdatastay;
13582#endif
13583 SCIP_CONSDATA* consdatadel;
13584 SCIP_Real lhs;
13585 SCIP_Real rhs;
13586 int consinddel;
13587
13588 /* the coefficients in both rows are either equal or negated: create a new constraint with same coefficients and
13589 * best left and right hand sides; delete the old constraints afterwards
13590 */
13591 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with %s coefficients into single ranged row\n",
13592 SCIPconsGetName(cons0), SCIPconsGetName(cons1), coefsequal ? "equal" : "negated");
13593 SCIPdebugPrintCons(scip, cons0, NULL);
13594 SCIPdebugPrintCons(scip, cons1, NULL);
13595
13596 if( coefsequal )
13597 {
13598 /* the coefficients of both rows are equal */
13599 lhs = MAX(consdata0->lhs, consdata1->lhs);
13600 rhs = MIN(consdata0->rhs, consdata1->rhs);
13601 }
13602 else
13603 {
13604 /* the coefficients of both rows are negations */
13605 lhs = MAX(consdata0->lhs, -consdata1->rhs);
13606 rhs = MIN(consdata0->rhs, -consdata1->lhs);
13607 }
13608 if( SCIPisFeasLT(scip, rhs, lhs) )
13609 {
13610 SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13611 *cutoff = TRUE;
13612 break;
13613 }
13614
13615 /* check which constraint has to stay;
13616 * changes applied to an upgraded constraint will not be considered in the instance */
13617 if( consdata0->upgraded )
13618 {
13619 assert(!consdata1->upgraded);
13620 consstay = cons1;
13621#ifndef NDEBUG
13622 consdatastay = consdata1;
13623#endif
13624
13625 consdel = cons0;
13626 consdatadel = consdata0;
13627 consinddel = chkind;
13628 }
13629 else
13630 {
13631 consstay = cons0;
13632#ifndef NDEBUG
13633 consdatastay = consdata0;
13634#endif
13635
13636 consdel = cons1;
13637 consdatadel = consdata1;
13638 consinddel = c;
13639 }
13640
13641 /* update the sides of consstay */
13642 SCIP_CALL( chgLhs(scip, consstay, lhs) );
13643 SCIP_CALL( chgRhs(scip, consstay, rhs) );
13644 if( !consdata0->upgraded )
13645 {
13646 assert(consstay == cons0);
13647 cons0lhs = consdata0->lhs;
13648 cons0rhs = consdata0->rhs;
13649 }
13650
13651 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13652 SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) );
13653
13654 assert( !consdatastay->upgraded );
13655 /* delete consdel */
13656 SCIP_CALL( SCIPdelCons(scip, consdel) );
13657 conss[consinddel] = NULL;
13658 if( !consdatadel->upgraded )
13659 (*ndelconss)++;
13660 continue;
13661 }
13662
13663 /* check for domination: remove dominated sides, but don't touch equalities as long as they are not totally
13664 * redundant
13665 */
13666 if( cons1dominateslhs && (!cons0isequality || cons1dominatesrhs || SCIPisInfinity(scip, consdata0->rhs) ) )
13667 {
13668 /* left hand side is dominated by consdata1: delete left hand side of consdata0 */
13669 SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13670 SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13671 SCIPdebugPrintCons(scip, cons0, NULL);
13672 SCIPdebugPrintCons(scip, cons1, NULL);
13673
13674 /* check for infeasibility */
13675 if( SCIPisFeasGT(scip, consdata1->lhs, consdata0->rhs) )
13676 {
13677 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13678 *cutoff = TRUE;
13679 break;
13680 }
13681
13682 /* remove redundant left hand side */
13683 if( !SCIPisInfinity(scip, -consdata0->lhs) )
13684 {
13685 SCIP_CALL( chgLhs(scip, cons0, -SCIPinfinity(scip)) );
13686 cons0lhs = consdata0->lhs;
13687 cons0isequality = FALSE;
13688 if( !consdata0->upgraded )
13689 {
13690 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13691 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13692
13693 (*nchgsides)++;
13694 }
13695 }
13696 }
13697 else if( cons0dominateslhs && (!cons1isequality || cons0dominatesrhs || SCIPisInfinity(scip, consdata1->rhs)) )
13698 {
13699 /* left hand side is dominated by consdata0: delete left hand side of consdata1 */
13700 SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13701 SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13702 SCIPdebugPrintCons(scip, cons1, NULL);
13703 SCIPdebugPrintCons(scip, cons0, NULL);
13704
13705 /* check for infeasibility */
13706 if( SCIPisFeasGT(scip, consdata0->lhs, consdata1->rhs) )
13707 {
13708 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13709 *cutoff = TRUE;
13710 break;
13711 }
13712
13713 /* remove redundant left hand side */
13714 if( !SCIPisInfinity(scip, -consdata1->lhs) )
13715 {
13716 SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
13717 cons1isequality = FALSE;
13718 if( !consdata1->upgraded )
13719 {
13720 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13721 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13722
13723 (*nchgsides)++;
13724 }
13725 }
13726 }
13727 if( cons1dominatesrhs && (!cons0isequality || cons1dominateslhs || SCIPisInfinity(scip, -consdata0->lhs)) )
13728 {
13729 /* right hand side is dominated by consdata1: delete right hand side of consdata0 */
13730 SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13731 SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13732 SCIPdebugPrintCons(scip, cons0, NULL);
13733 SCIPdebugPrintCons(scip, cons1, NULL);
13734
13735 /* check for infeasibility */
13736 if( SCIPisFeasLT(scip, consdata1->rhs, consdata0->lhs) )
13737 {
13738 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13739 *cutoff = TRUE;
13740 break;
13741 }
13742
13743 /* remove redundant right hand side */
13744 if( !SCIPisInfinity(scip, consdata0->rhs) )
13745 {
13746 SCIP_CALL( chgRhs(scip, cons0, SCIPinfinity(scip)) );
13747 cons0rhs = consdata0->rhs;
13748 cons0isequality = FALSE;
13749 if( !consdata0->upgraded )
13750 {
13751 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13752 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13753
13754 (*nchgsides)++;
13755 }
13756 }
13757 }
13758 else if( cons0dominatesrhs && (!cons1isequality || cons0dominateslhs || SCIPisInfinity(scip, -consdata1->lhs)) )
13759 {
13760 /* right hand side is dominated by consdata0: delete right hand side of consdata1 */
13761 SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13762 SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13763 SCIPdebugPrintCons(scip, cons1, NULL);
13764 SCIPdebugPrintCons(scip, cons0, NULL);
13765
13766 /* check for infeasibility */
13767 if( SCIPisFeasLT(scip, consdata0->rhs, consdata1->lhs) )
13768 {
13769 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13770 *cutoff = TRUE;
13771 break;
13772 }
13773
13774 /* remove redundant right hand side */
13775 if( !SCIPisInfinity(scip, consdata1->rhs) )
13776 {
13777 SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
13778 cons1isequality = FALSE;
13779 if( !consdata1->upgraded )
13780 {
13781 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13782 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13783
13784 (*nchgsides)++;
13785 }
13786 }
13787 }
13788
13789 /* check for now redundant constraints */
13790 if( SCIPisInfinity(scip, -consdata0->lhs) && SCIPisInfinity(scip, consdata0->rhs) )
13791 {
13792 /* consdata0 became redundant */
13793 SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons0));
13794 SCIP_CALL( SCIPdelCons(scip, cons0) );
13795 conss[chkind] = NULL;
13796 if( !consdata0->upgraded )
13797 {
13798 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13799 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13800
13801 (*ndelconss)++;
13802 }
13803 continue;
13804 }
13805 if( SCIPisInfinity(scip, -consdata1->lhs) && SCIPisInfinity(scip, consdata1->rhs) )
13806 {
13807 /* consdata1 became redundant */
13808 SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons1));
13809 SCIP_CALL( SCIPdelCons(scip, cons1) );
13810 conss[c] = NULL;
13811 if( !consdata1->upgraded )
13812 {
13813 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13814 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13815
13816 (*ndelconss)++;
13817 }
13818 continue;
13819 }
13820
13821 /* check, if we want to aggregate an (in)equality with an equality:
13822 * consdata0 := a * consdata0 + b * consdata1 or consdata1 := a * consdata1 + b * consdata0
13823 */
13824 if( tryaggregation )
13825 {
13826 SCIP_Bool aggregated;
13827
13828 assert(consdata0->nvars == nvarscommon + nvars0minus1);
13829 assert(consdata1->nvars == nvarscommon + nvars1minus0);
13830
13831 aggregated = FALSE;
13832 if( cons1isequality && !consdata0->upgraded && commonidxweight > diffidx1minus0weight )
13833 {
13834 /* W_c > W_1: try to aggregate consdata0 := a * consdata0 + b * consdata1 */
13835 SCIP_CALL( aggregateConstraints(scip, cons0, cons1, commonidx0, commonidx1, diffidx0minus1, diffidx1minus0,
13836 nvarscommon, commonidxweight, diffidx0minus1weight, diffidx1minus0weight, maxaggrnormscale,
13837 nchgcoefs, &aggregated, cutoff) );
13838
13839 if( *cutoff )
13840 break;
13841
13842 /* update array of active constraints */
13843 if( aggregated )
13844 {
13845 assert(!SCIPconsIsActive(cons0));
13846 assert(SCIPconsIsActive(cons1));
13847 conss[chkind] = NULL;
13848 }
13849 }
13850 if( !aggregated && cons0isequality && !consdata1->upgraded && commonidxweight > diffidx0minus1weight )
13851 {
13852 /* W_c > W_0: try to aggregate consdata1 := a * consdata1 + b * consdata0 */
13853 SCIP_CALL( aggregateConstraints(scip, cons1, cons0, commonidx1, commonidx0, diffidx1minus0, diffidx0minus1,
13854 nvarscommon, commonidxweight, diffidx1minus0weight, diffidx0minus1weight, maxaggrnormscale,
13855 nchgcoefs, &aggregated, cutoff) );
13856
13857 if( *cutoff )
13858 break;
13859
13860 /* update array of active constraints */
13861 if( aggregated )
13862 {
13863 assert(!SCIPconsIsActive(cons1));
13864 assert(SCIPconsIsActive(cons0));
13865 conss[c] = NULL;
13866 }
13867 }
13868 }
13869 }
13870
13871 /* free temporary memory */
13872 SCIPfreeBufferArray(scip, &diffidx1minus0);
13873 SCIPfreeBufferArray(scip, &diffidx0minus1);
13874 SCIPfreeBufferArray(scip, &commonidx1);
13875 SCIPfreeBufferArray(scip, &commonidx0);
13876
13877 return SCIP_OKAY;
13878}
13879
13880/** do stuffing presolving on a single constraint */
13881static
13883 SCIP* scip, /**< SCIP data structure */
13884 SCIP_CONS* cons, /**< linear constraint */
13885 SCIP_Bool singletonstuffing, /**< should stuffing of singleton continuous variables be performed? */
13886 SCIP_Bool singlevarstuffing, /**< should single variable stuffing be performed, which tries to fulfill
13887 * constraints using the cheapest variable? */
13888 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13889 int* nfixedvars, /**< pointer to count the total number of fixed variables */
13890 int* nchgbds /**< pointer to count the total number of tightened bounds */
13891 )
13892{
13893 SCIP_CONSDATA* consdata;
13894 SCIP_Real* ratios;
13895 int* varpos;
13896 SCIP_Bool* swapped;
13897 SCIP_VAR** vars;
13898 SCIP_Real* vals;
13899 SCIP_VAR* var;
13900 SCIP_Real lb;
13901 SCIP_Real ub;
13902 SCIP_Real minactivity;
13903 SCIP_Real maxactivity;
13904 SCIP_Real maxcondactivity;
13905 SCIP_Real mincondactivity;
13906 SCIP_Real rhs;
13907 SCIP_Real val;
13908 SCIP_Real obj;
13909 SCIP_Real factor;
13910 SCIP_Bool isminacttight;
13911 SCIP_Bool ismaxacttight;
13912 SCIP_Bool isminsettoinfinity;
13913 SCIP_Bool ismaxsettoinfinity;
13914 SCIP_Bool tryfixing;
13915 int nsingletons;
13916 int idx;
13917 int v;
13918 int nvars;
13919
13920 assert(scip != NULL);
13921 assert(cons != NULL);
13922 assert(nfixedvars != NULL);
13923
13924 consdata = SCIPconsGetData(cons);
13925
13926 /* we only want to run for inequalities */
13927 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->lhs) )
13928 return SCIP_OKAY;
13929
13930 if( singlevarstuffing )
13931 {
13932 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
13933 &isminsettoinfinity, &ismaxsettoinfinity);
13934 }
13935 else
13936 {
13937 minactivity = SCIP_INVALID;
13938 maxactivity = SCIP_INVALID;
13939 isminsettoinfinity = FALSE;
13940 ismaxsettoinfinity = FALSE;
13941 }
13942
13943 /* we want to have a <= constraint, if the rhs is infinite, we implicitly multiply the constraint by -1,
13944 * the new maxactivity is minus the old minactivity then
13945 */
13946 if( SCIPisInfinity(scip, consdata->rhs) )
13947 {
13948 rhs = -consdata->lhs;
13949 factor = -1.0;
13950 maxactivity = -minactivity;
13951 ismaxsettoinfinity = isminsettoinfinity;
13952 }
13953 else
13954 {
13955 assert(SCIPisInfinity(scip, -consdata->lhs));
13956 rhs = consdata->rhs;
13957 factor = 1.0;
13958 }
13959
13960 nvars = consdata->nvars;
13961 vars = consdata->vars;
13962 vals = consdata->vals;
13963
13964 /* check for continuous singletons */
13965 if( singletonstuffing )
13966 {
13967 for( v = 0; v < nvars; ++v )
13968 {
13969 var = vars[v];
13970
13973 break;
13974 }
13975 }
13976 else
13977 /* we don't want to go into the next block */
13978 v = nvars;
13979
13980 /* a singleton was found -> perform singleton variable stuffing */
13981 if( v < nvars )
13982 {
13983 assert(singletonstuffing);
13984
13988
13989 tryfixing = TRUE;
13990 nsingletons = 0;
13991 mincondactivity = 0.0;
13992 maxcondactivity = 0.0;
13993
13994 for( v = 0; v < nvars; ++v )
13995 {
13996 var = vars[v];
13997 lb = SCIPvarGetLbGlobal(var);
13998 ub = SCIPvarGetUbGlobal(var);
14000 val = factor * vals[v];
14001
14002 assert(!SCIPisZero(scip, val));
14003
14004 /* the variable is a singleton and continuous */
14007 {
14008 if( SCIPisNegative(scip, obj) && val > 0 )
14009 {
14010 /* case 1: obj < 0 and coef > 0 */
14011 if( SCIPisInfinity(scip, -lb) )
14012 {
14013 tryfixing = FALSE;
14014 break;
14015 }
14016
14017 maxcondactivity += val * lb;
14018 mincondactivity += val * lb;
14019 swapped[v] = FALSE;
14020 ratios[nsingletons] = obj / val;
14021 varpos[nsingletons] = v;
14022 nsingletons++;
14023 }
14024 else if( SCIPisPositive(scip, obj) && val < 0 )
14025 {
14026 /* case 2: obj > 0 and coef < 0 */
14027 if( SCIPisInfinity(scip, ub) )
14028 {
14029 tryfixing = FALSE;
14030 break;
14031 }
14032 /* multiply column by (-1) to become case 1.
14033 * now bounds are swapped: ub := -lb, lb := -ub
14034 */
14035
14036 maxcondactivity += val * ub;
14037 mincondactivity += val * ub;
14038 swapped[v] = TRUE;
14039 ratios[nsingletons] = obj / val;
14040 varpos[nsingletons] = v;
14041 nsingletons++;
14042 }
14043 else if( val > 0 )
14044 {
14045 /* case 3: obj >= 0 and coef >= 0 is handled by duality fixing.
14046 * we only consider the lower bound for the constants
14047 */
14049
14050 if( SCIPisInfinity(scip, -lb) )
14051 {
14052 /* maybe unbounded */
14053 tryfixing = FALSE;
14054 break;
14055 }
14056
14057 maxcondactivity += val * lb;
14058 mincondactivity += val * lb;
14059 }
14060 else
14061 {
14062 /* case 4: obj <= 0 and coef <= 0 is also handled by duality fixing.
14063 * we only consider the upper bound for the constants
14064 */
14066 assert(val < 0);
14067
14068 if( SCIPisInfinity(scip, ub) )
14069 {
14070 /* maybe unbounded */
14071 tryfixing = FALSE;
14072 break;
14073 }
14074
14075 maxcondactivity += val * ub;
14076 mincondactivity += val * ub;
14077 }
14078 }
14079 else
14080 {
14081 /* consider contribution of discrete variables, non-singleton
14082 * continuous variables and variables with more than one lock
14083 */
14084 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14085 {
14086 tryfixing = FALSE;
14087 break;
14088 }
14089
14090 if( val > 0 )
14091 {
14092 maxcondactivity += val * ub;
14093 mincondactivity += val * lb;
14094 }
14095 else
14096 {
14097 maxcondactivity += val * lb;
14098 mincondactivity += val * ub;
14099 }
14100 }
14101 }
14102 if( tryfixing && nsingletons > 0 && (SCIPisGT(scip, rhs, maxcondactivity) || SCIPisLE(scip, rhs, mincondactivity)) )
14103 {
14104 SCIP_Real delta;
14105 SCIP_Bool tightened;
14106#ifdef SCIP_DEBUG
14107 int oldnfixedvars = *nfixedvars;
14108#endif
14109
14110 SCIPsortRealInt(ratios, varpos, nsingletons);
14111
14112 /* verify which singleton continuous variables can be fixed */
14113 for( v = 0; v < nsingletons; ++v )
14114 {
14115 idx = varpos[v];
14116 var = vars[idx];
14117 val = factor * vals[idx];
14118 lb = SCIPvarGetLbGlobal(var);
14119 ub = SCIPvarGetUbGlobal(var);
14120
14122 assert((val < 0) == swapped[idx]);
14123 val = REALABS(val);
14124
14125 /* stop fixing if variable bounds are not finite */
14126 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14127 break;
14128
14132
14133 /* calculate the change in the row activities if this variable changes
14134 * its value from its worst to its best bound
14135 */
14136 if( swapped[idx] )
14137 delta = -(lb - ub) * val;
14138 else
14139 delta = (ub - lb) * val;
14140
14141 assert(!SCIPisNegative(scip, delta));
14142
14143 if( SCIPisLE(scip, delta, rhs - maxcondactivity) )
14144 {
14145 if( swapped[idx] )
14146 {
14147 SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14148 SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14149 }
14150 else
14151 {
14152 SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14153 SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14154 }
14155
14156 if( *cutoff )
14157 break;
14158 if( tightened )
14159 {
14160 (*nfixedvars)++;
14161 }
14162 }
14163 /* @note: we could in theory tighten the bound of the first singleton variable which does not fall into the above case,
14164 * since it cannot be fully fixed. However, this is not needed and should be done by activity-based bound tightening
14165 * anyway after all other continuous singleton columns were fixed; doing it here may introduce numerical
14166 * troubles in case of large bounds.
14167 */
14168 else if( SCIPisLE(scip, rhs, mincondactivity) )
14169 {
14170 if( swapped[idx] )
14171 {
14172 SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14173 SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14174 }
14175 else
14176 {
14177 SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14178 SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14179 }
14180
14181 if( *cutoff )
14182 break;
14183 if( tightened )
14184 {
14185 (*nfixedvars)++;
14186 }
14187 }
14188
14189 maxcondactivity += delta;
14190 mincondactivity += delta;
14191 }
14192
14193#ifdef SCIP_DEBUG
14194 if( *nfixedvars - oldnfixedvars > 0 )
14195 {
14196 SCIPdebugMsg(scip, "### stuffing fixed %d variables\n", *nfixedvars - oldnfixedvars);
14197 }
14198#endif
14199 }
14200
14201 SCIPfreeBufferArray(scip, &swapped);
14202 SCIPfreeBufferArray(scip, &ratios);
14203 SCIPfreeBufferArray(scip, &varpos);
14204 }
14205
14206 /* perform single-variable stuffing:
14207 * for a linear inequality
14208 * a_1 x_1 + a_2 x_2 + ... + a_n x_n <= b
14209 * with a_i > 0 and objective coefficients c_i < 0,
14210 * setting all variables to their upper bound (giving us the maximal activity of the constraint) is worst w.r.t.
14211 * feasibility of the constraint. On the other hand, this gives the best objective function contribution of the
14212 * variables contained in the constraint. The maximal activity should be larger than the rhs, otherwise the constraint
14213 * is redundant.
14214 * Now we are searching for a variable x_k with maximal ratio c_k / a_k (note that all these ratios are negative), so
14215 * that by reducing the value of this variable we reduce the activity of the constraint while having the smallest
14216 * objective deterioration per activity unit. If x_k has no downlocks, is continuous, and can be reduced enough to
14217 * render the constraint feasible, and ALL other variables have only the one uplock installed by the current constraint,
14218 * we can reduce the upper bound of x_k such that the maxactivity equals the rhs and fix all other variables to their
14219 * upper bound.
14220 * Note that the others variables may have downlocks from other constraints, which we do not need to care
14221 * about since we are setting them to the highest possible value. Also, they may be integer or binary, because the
14222 * computed ratio is still a lower bound on the change in the objective caused by reducing those variable to reach
14223 * constraint feasibility. On the other hand, uplocks on x_k from other constraint do no interfer with the method.
14224 * With a slight adjustment, the procedure even works for integral x_k. If (maxactivity - rhs)/val is integral,
14225 * the variable gets an integral value in order to fulfill the constraint tightly, and we can just apply the procedure.
14226 * If (maxactivity - rhs)/val is fractional, we need to check, if overfulfilling the constraint by setting x_k to
14227 * ceil((maxactivity - rhs)/val) is still better than setting x_k to ceil((maxactivity - rhs)/val) - 1 and
14228 * filling the remaining gap in the constraint with the next-best variable. For this, we check that
14229 * c_k * ceil((maxactivity - rhs)/val) is still better than
14230 * c_k * floor((maxactivity - rhs)/val) + c_j * ((maxactivity - rhs) - (floor((maxactivity - rhs)/val) * val))/a_j.
14231 * In this case, the upper bound of x_k is decreased to ub_k - ceil(maxactivity - rhs).
14232 * If there are variables with a_i < 0 and c_i > 0, they are negated to obtain the above form, variables with same
14233 * sign of coefficients in constraint and objective prevent the use of this method.
14234 */
14235 if( singlevarstuffing && !ismaxsettoinfinity )
14236 {
14237 SCIP_Real bestratio = -SCIPinfinity(scip);
14238 SCIP_Real secondbestratio = -SCIPinfinity(scip);
14239 SCIP_Real ratio;
14240 int bestindex = -1;
14241 int bestuplocks = 0;
14242 int bestdownlocks = 1;
14243 int downlocks;
14244 int uplocks;
14245 SCIPdebug( int oldnfixedvars = *nfixedvars; )
14246 SCIPdebug( int oldnchgbds = *nchgbds; )
14247
14248 /* loop over all variables to identify the best and second-best ratio */
14249 for( v = 0; v < nvars; ++v )
14250 {
14251 var = vars[v];
14253 val = factor * vals[v];
14254
14255 assert(!SCIPisZero(scip, val));
14256
14257 ratio = obj / val;
14258
14259 /* if both objective and constraint push the variable to the same direction, we can do nothing here */
14260 if( !SCIPisNegative(scip, ratio) )
14261 {
14262 bestindex = -1;
14263 break;
14264 }
14265
14266 if( val > 0 )
14267 {
14270 }
14271 else
14272 {
14275 }
14276
14277 /* better ratio, update best candidate
14278 * @todo use some tolerance
14279 * @todo check size of domain and updated ratio for integer variables already?
14280 */
14281 if( ratio > bestratio || ( downlocks == 0 && ratio == bestratio && ( bestdownlocks > 0 /*lint !e777*/
14282 || ( !SCIPvarIsIntegral(var) && SCIPvarIsIntegral(vars[bestindex]) ) ) ) )
14283 {
14284 /* best index becomes second-best*/
14285 if( bestindex != -1 )
14286 {
14287 /* second-best index must not have more than 1 uplock */
14288 if( bestuplocks > 1 )
14289 {
14290 bestindex = -1;
14291 break;
14292 }
14293 else
14294 {
14295 secondbestratio = bestratio;
14296 }
14297 }
14298 bestdownlocks = downlocks;
14299 bestuplocks = uplocks;
14300 bestratio = ratio;
14301 bestindex = v;
14302
14303 /* if this variable is the best in the end, we cannot do reductions since it has a downlocks,
14304 * if it is not the best, it has too many uplocks -> not applicable
14305 */
14306 if( bestdownlocks > 0 && bestuplocks > 1 )
14307 {
14308 bestindex = -1;
14309 break;
14310 }
14311 }
14312 else
14313 {
14314 /* non-best index must not have more than 1 uplock */
14315 if( uplocks > 1 )
14316 {
14317 bestindex = -1;
14318 break;
14319 }
14320 /* update second-best ratio */
14321 if( ratio > secondbestratio )
14322 {
14323 secondbestratio = ratio;
14324 }
14325 }
14326 }
14327
14328 /* check if we can apply single variable stuffing */
14329 if( bestindex != -1 && bestdownlocks == 0 )
14330 {
14331 SCIP_Bool tightened = FALSE;
14332 SCIP_Real bounddelta;
14333
14334 var = vars[bestindex];
14336 val = factor * vals[bestindex];
14337 lb = SCIPvarGetLbGlobal(var);
14338 ub = SCIPvarGetUbGlobal(var);
14339 tryfixing = TRUE;
14340
14341 if( val < 0 )
14342 {
14344
14345 /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14346 if( SCIPvarIsIntegral(var) && !SCIPisIntegral(scip, (maxactivity - rhs) / val) )
14347 {
14348 SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/-val);
14349 SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * -val);
14350 assert(SCIPisPositive(scip, activitydelta));
14351
14352 tryfixing = SCIPisLE(scip, obj, -activitydelta * secondbestratio);
14353
14354 bounddelta = SCIPceil(scip, (maxactivity - rhs)/-val);
14355 assert(SCIPisPositive(scip, bounddelta));
14356 }
14357 else
14358 bounddelta = (maxactivity - rhs)/-val;
14359
14360 tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14361
14362 if( tryfixing )
14363 {
14365
14366 if( SCIPisEQ(scip, lb + bounddelta, ub) )
14367 {
14368 SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), lb + bounddelta);
14369 SCIP_CALL( SCIPfixVar(scip, var, lb + bounddelta, cutoff, &tightened) );
14370 }
14371 else
14372 {
14373 SCIPdebugMsg(scip, "tighten the lower bound of <%s> from %g to %g (ub=%g)\n", SCIPvarGetName(var), lb, lb + bounddelta, ub);
14374 SCIP_CALL( SCIPtightenVarLb(scip, var, lb + bounddelta, FALSE, cutoff, &tightened) );
14375 }
14376 }
14377 }
14378 else
14379 {
14381
14382 /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14383 if( SCIPvarIsIntegral(var) && !SCIPisIntegral(scip, (maxactivity - rhs) / val) )
14384 {
14385 SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/val);
14386 SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * val);
14387 assert(SCIPisPositive(scip, activitydelta));
14388
14389 tryfixing = SCIPisLE(scip, -obj, activitydelta * secondbestratio);
14390
14391 bounddelta = SCIPceil(scip, (maxactivity - rhs)/val);
14392 assert(SCIPisPositive(scip, bounddelta));
14393 }
14394 else
14395 bounddelta = (maxactivity - rhs)/val;
14396
14397 tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14398
14399 if( tryfixing )
14400 {
14402
14403 if( SCIPisEQ(scip, ub - bounddelta, lb) )
14404 {
14405 SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), ub - bounddelta);
14406 SCIP_CALL( SCIPfixVar(scip, var, ub - bounddelta, cutoff, &tightened) );
14407 }
14408 else
14409 {
14410 SCIPdebugMsg(scip, "tighten the upper bound of <%s> from %g to %g (lb=%g)\n", SCIPvarGetName(var), ub, ub - bounddelta, lb);
14411 SCIP_CALL( SCIPtightenVarUb(scip, var, ub - bounddelta, FALSE, cutoff, &tightened) );
14412 }
14413 }
14414 }
14415
14416 if( *cutoff )
14417 return SCIP_OKAY;
14418 if( tightened )
14419 {
14421 ++(*nfixedvars);
14422 else
14423 ++(*nchgbds);
14424
14425 SCIPdebugMsg(scip, "cons <%s>: %g <=\n", SCIPconsGetName(cons), factor > 0 ? consdata->lhs : -consdata->rhs);
14426 for( v = 0; v < nvars; ++v )
14427 {
14428 SCIPdebugMsg(scip, "%+g <%s>([%g,%g],%g,[%d,%d],%s)\n", factor * vals[v], SCIPvarGetName(vars[v]),
14432 SCIPvarIsIntegral(vars[v]) ? "I" : "C");
14433 }
14434 SCIPdebugMsg(scip, "<= %g\n", factor > 0 ? consdata->rhs : -consdata->lhs);
14435
14436 for( v = 0; v < nvars; ++v )
14437 {
14438 if( v == bestindex )
14439 continue;
14440
14441 if( factor * vals[v] < 0 )
14442 {
14444 SCIPdebugMsg(scip, "fix <%s> to its lower bound (%g)\n",
14446 SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetLbGlobal(vars[v]), cutoff, &tightened) );
14447 }
14448 else
14449 {
14451 SCIPdebugMsg(scip, "fix <%s> to its upper bound (%g)\n",
14453 SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetUbGlobal(vars[v]), cutoff, &tightened) );
14454 }
14455
14456 if( *cutoff )
14457 return SCIP_OKAY;
14458 if( tightened )
14459 ++(*nfixedvars);
14460 }
14461 SCIPdebug( SCIPdebugMsg(scip, "### new stuffing fixed %d vars, tightened %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds); )
14462 }
14463 }
14464 }
14465
14466 return SCIP_OKAY;
14467}
14468
14469/** applies full dual presolving on variables that only appear in linear constraints */
14470static
14472 SCIP* scip, /**< SCIP data structure */
14473 SCIP_CONS** conss, /**< constraint set */
14474 int nconss, /**< number of constraints */
14475 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14476 int* nchgbds, /**< pointer to count the number of bound changes */
14477 int* nchgvartypes /**< pointer to count the number of variable type changes */
14478 )
14479{
14480 SCIP_Real* redlb;
14481 SCIP_Real* redub;
14482 int* nlocksdown;
14483 int* nlocksup;
14484 SCIP_Bool* isimplint;
14485 SCIP_VAR** origvars;
14486 SCIP_VAR** vars;
14487 SCIP_VAR** conscontvars;
14488 int nvars;
14489 int nbinvars;
14490 int nintvars;
14491 int ncontvars;
14492 int v;
14493 int c;
14494
14495 /* we calculate redundancy bounds with the following meaning:
14496 * redlb[v] == k : if x_v >= k, we can always round x_v down to x_v == k without violating any constraint
14497 * redub[v] == k : if x_v <= k, we can always round x_v up to x_v == k without violating any constraint
14498 * then:
14499 * c_v >= 0 : x_v <= redlb[v] is feasible due to optimality
14500 * c_v <= 0 : x_v >= redub[v] is feasible due to optimality
14501 */
14502
14503 /* Additionally, we detect continuous variables that are implied integral.
14504 * A continuous variable j is implied integral if it only has only +/-1 coefficients,
14505 * and all constraints (including the bounds as trivial constraints) in which:
14506 * c_j > 0: the variable is down-locked,
14507 * c_j < 0: the variable is up-locked,
14508 * c_j = 0: the variable appears
14509 * have, apart from j, only integer variables with integral coefficients and integral sides.
14510 * This is because then, the value of the variable is either determined by one of its bounds or
14511 * by one of these constraints, and in all cases, the value of the variable is integral.
14512 */
14513
14514 assert(scip != NULL);
14515 assert(nconss == 0 || conss != NULL);
14516 assert(nchgbds != NULL);
14518
14519 /* get active variables */
14521 origvars = SCIPgetVars(scip);
14522
14523 /* if the problem is a pure binary program, nothing can be achieved by full dual presolve */
14524 nbinvars = SCIPgetNBinVars(scip);
14525 if( nbinvars == nvars )
14526 return SCIP_OKAY;
14527
14528 /* get number of continuous variables */
14529 ncontvars = SCIPgetNContVars(scip);
14530 nintvars = nvars - ncontvars;
14531
14532 /* copy the variable array since this array might change during the curse of this algorithm */
14533 nvars = nvars - nbinvars;
14534 SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &(origvars[nbinvars]), nvars) );
14535
14536 /* allocate temporary memory */
14539 SCIP_CALL( SCIPallocBufferArray(scip, &nlocksdown, nvars) );
14540 SCIP_CALL( SCIPallocBufferArray(scip, &nlocksup, nvars) );
14541 SCIP_CALL( SCIPallocBufferArray(scip, &isimplint, ncontvars) );
14542 SCIP_CALL( SCIPallocBufferArray(scip, &conscontvars, ncontvars) );
14543
14544 /* initialize redundancy bounds */
14545 for( v = 0; v < nvars; ++v )
14546 {
14548 redlb[v] = SCIPvarGetLbGlobal(vars[v]);
14549 redub[v] = SCIPvarGetUbGlobal(vars[v]);
14550 }
14551 BMSclearMemoryArray(nlocksdown, nvars);
14552 BMSclearMemoryArray(nlocksup, nvars);
14553
14554 /* Initialize isimplint array: variable may be implied integral if rounded to their best bound they are integral
14555 * we better not use SCIPisFeasIntegral() in these checks.
14556 */
14557 for( v = 0; v < ncontvars; v++ )
14558 {
14559 SCIP_VAR* var;
14560 SCIP_Real obj;
14561 SCIP_Real lb;
14562 SCIP_Real ub;
14563
14564 var = vars[v + nintvars - nbinvars];
14566
14567 lb = SCIPvarGetLbGlobal(var);
14568 ub = SCIPvarGetUbGlobal(var);
14569
14571 if( SCIPisZero(scip, obj) )
14572 isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb)) && (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14573 else
14574 {
14575 if( SCIPisPositive(scip, obj) )
14576 isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb));
14577 else
14578 {
14580 isimplint[v] = (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14581 }
14582 }
14583 }
14584
14585 /* scan all constraints */
14586 for( c = 0; c < nconss; ++c )
14587 {
14588 /* we only need to consider constraints that have been locked (i.e., checked constraints or constraints that are
14589 * part of checked disjunctions)
14590 */
14591 if( SCIPconsIsLocked(conss[c]) )
14592 {
14593 SCIP_CONSDATA* consdata;
14594 SCIP_Bool lhsexists;
14595 SCIP_Bool rhsexists;
14596 SCIP_Bool hasimpliedpotential;
14597 SCIP_Bool integralcoefs;
14598 int nlockspos;
14599 int contvarpos;
14600 int nconscontvars;
14601 int i;
14602
14603 consdata = SCIPconsGetData(conss[c]);
14604 assert(consdata != NULL);
14605
14606 /* get number of times the constraint was locked */
14607 nlockspos = SCIPconsGetNLocksPos(conss[c]);
14608
14609 /* we do not want to include constraints with locked negation (this would be too weird) */
14610 if( SCIPconsGetNLocksNeg(conss[c]) > 0 )
14611 {
14612 /* mark all non-implied continuous variables */
14613 for( i = 0; i < consdata->nvars; ++i )
14614 {
14615 SCIP_VAR* var;
14616
14617 var = consdata->vars[i];
14618 if( !SCIPvarIsIntegral(var) )
14619 {
14620 int contv;
14621 contv = SCIPvarGetProbindex(var) - nintvars;
14622 assert(0 <= contv && contv < ncontvars); /* variable should be active due to applyFixings() */
14623 isimplint[contv] = FALSE;
14624 }
14625 }
14626 continue;
14627 }
14628
14629 /* check for existing sides */
14630 lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
14631 rhsexists = !SCIPisInfinity(scip, consdata->rhs);
14632
14633 /* count locks and update redundancy bounds */
14634 contvarpos = -1;
14635 nconscontvars = 0;
14636 hasimpliedpotential = FALSE;
14637 integralcoefs = !SCIPconsIsModifiable(conss[c]);
14638
14639 for( i = 0; i < consdata->nvars; ++i )
14640 {
14641 SCIP_VAR* var;
14642 SCIP_Real val;
14643 SCIP_Real minresactivity;
14644 SCIP_Real maxresactivity;
14645 SCIP_Real newredlb;
14646 SCIP_Real newredub;
14647 SCIP_Bool ismintight;
14648 SCIP_Bool ismaxtight;
14649 SCIP_Bool isminsettoinfinity;
14650 SCIP_Bool ismaxsettoinfinity;
14651 int arrayindex;
14652
14653 var = consdata->vars[i];
14654 assert(var != NULL);
14655 val = consdata->vals[i];
14656 assert(!SCIPisZero(scip, val));
14657
14658 /* check if still all integer variables have integral coefficients */
14659 if( SCIPvarIsIntegral(var) )
14660 integralcoefs = integralcoefs && SCIPisIntegral(scip, val);
14661
14662 /* we do not need to process binary variables */
14663 if( SCIPvarIsBinary(var) )
14664 continue;
14665
14666 if( SCIPconsIsModifiable(conss[c]) )
14667 {
14668 minresactivity = -SCIPinfinity(scip);
14669 maxresactivity = SCIPinfinity(scip);
14670 isminsettoinfinity = TRUE;
14671 ismaxsettoinfinity = TRUE;
14672 }
14673 else
14674 {
14675 /* calculate residual activity bounds if variable would be fixed to zero */
14676 consdataGetGlbActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
14677 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
14678
14679 /* We called consdataGetGlbActivityResiduals() saying that we do not need a good relaxation,
14680 * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
14681 * This is needed, because we do not want to rely on relaxed finite resactivities.
14682 */
14683 assert((ismintight || isminsettoinfinity) && (ismaxtight || ismaxsettoinfinity));
14684
14685 /* check minresactivity for reliability */
14686 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
14687 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, TRUE);
14688
14689 /* check maxresactivity for reliability */
14690 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
14691 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, TRUE);
14692 }
14693
14694 arrayindex = SCIPvarGetProbindex(var) - nbinvars;
14695
14696 assert(0 <= arrayindex && arrayindex < nvars); /* variable should be active due to applyFixings() */
14697
14698 newredlb = redlb[arrayindex];
14699 newredub = redub[arrayindex];
14700 if( val > 0.0 )
14701 {
14702 if( lhsexists )
14703 {
14704 /* lhs <= d*x + a*y, d > 0 -> redundant in y if x >= (lhs - min{a*y})/d */
14705 nlocksdown[arrayindex] += nlockspos;
14706 newredlb = (isminsettoinfinity ? SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14707 }
14708 if( rhsexists )
14709 {
14710 /* d*x + a*y <= rhs, d > 0 -> redundant in y if x <= (rhs - max{a*y})/d */
14711 nlocksup[arrayindex] += nlockspos;
14712 newredub = (ismaxsettoinfinity ? -SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14713 }
14714 }
14715 else
14716 {
14717 if( lhsexists )
14718 {
14719 /* lhs <= d*x + a*y, d < 0 -> redundant in y if x <= (lhs - min{a*y})/d */
14720 nlocksup[arrayindex] += nlockspos;
14721 newredub = (isminsettoinfinity ? -SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14722 }
14723 if( rhsexists )
14724 {
14725 /* d*x + a*y <= rhs, d < 0 -> redundant in y if x >= (rhs - max{a*y})/d */
14726 nlocksdown[arrayindex] += nlockspos;
14727 newredlb = (ismaxsettoinfinity ? SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14728 }
14729 }
14730
14731 /* if the variable is integer, we have to round the value to the next integral value */
14732 if( SCIPvarIsIntegral(var) )
14733 {
14734 if( !SCIPisInfinity(scip, newredlb) )
14735 newredlb = SCIPceil(scip, newredlb);
14736 if( !SCIPisInfinity(scip, -newredub) )
14737 newredub = SCIPfloor(scip, newredub);
14738 }
14739
14740 /* update redundancy bounds */
14741 redlb[arrayindex] = MAX(redlb[arrayindex], newredlb);
14742 redub[arrayindex] = MIN(redub[arrayindex], newredub);
14743
14744 /* collect the continuous variables of the constraint */
14745 if( !SCIPvarIsIntegral(var) )
14746 {
14747 int contv;
14748
14749 assert(nconscontvars < ncontvars);
14750 contvarpos = i;
14751 conscontvars[nconscontvars] = var;
14752 nconscontvars++;
14753
14754 contv = SCIPvarGetProbindex(var) - nintvars;
14755 assert(0 <= contv && contv < ncontvars);
14756 hasimpliedpotential = hasimpliedpotential || isimplint[contv];
14757 }
14758 }
14759
14760 /* update implied integrality status of continuous variables */
14761 if( hasimpliedpotential )
14762 {
14763 if( nconscontvars > 1 || !integralcoefs )
14764 {
14765 /* there is more than one continuous variable or the integer variables have fractional coefficients:
14766 * none of the continuous variables is implied integral
14767 */
14768 for( i = 0; i < nconscontvars; i++ )
14769 {
14770 int contv;
14771 contv = SCIPvarGetProbindex(conscontvars[i]) - nintvars;
14772 assert(0 <= contv && contv < ncontvars);
14773 isimplint[contv] = FALSE;
14774 }
14775 }
14776 else
14777 {
14778 SCIP_VAR* var;
14779 SCIP_Real val;
14780 SCIP_Real absval;
14781 int contv;
14782
14783 /* there is exactly one continuous variable and the integer variables have integral coefficients:
14784 * this is the interesting case, and we have to check whether the coefficient is +/-1 and the corresponding
14785 * side(s) of the constraint is integral
14786 */
14787 assert(nconscontvars == 1);
14788 assert(0 <= contvarpos && contvarpos < consdata->nvars);
14789 var = consdata->vars[contvarpos];
14790 val = consdata->vals[contvarpos];
14791 contv = SCIPvarGetProbindex(var) - nintvars;
14792 assert(0 <= contv && contv < ncontvars);
14793 assert(isimplint[contv]);
14794
14795 absval = REALABS(val);
14796 if( !SCIPisEQ(scip, absval, 1.0) )
14797 isimplint[contv] = FALSE;
14798 else
14799 {
14800 SCIP_Real obj;
14801
14803 if( obj * val >= 0.0 && lhsexists )
14804 {
14805 /* the variable may be blocked by the constraint's left hand side */
14806 isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->lhs);
14807 }
14808 if( obj * val <= 0.0 && rhsexists )
14809 {
14810 /* the variable may be blocked by the constraint's left hand side */
14811 isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->rhs);
14812 }
14813 }
14814 }
14815 }
14816 }
14817 }
14818
14819 /* check if any bounds can be tightened due to optimality */
14820 for( v = 0; v < nvars; ++v )
14821 {
14822 SCIP_VAR* var;
14823 SCIP_Real obj;
14824 SCIP_Bool infeasible;
14825 SCIP_Bool tightened;
14826
14830
14831 var = vars[v];
14833 if( !SCIPisPositive(scip, -obj) )
14834 {
14835 /* making the variable as small as possible does not increase the objective:
14836 * check if all down locks of the variables are due to linear constraints;
14837 * if variable is cost neutral and only upper bounded non-positively or negative largest bound to make
14838 * constraints redundant is huge, we better do nothing for numerical reasons
14839 */
14842 && !SCIPisHugeValue(scip, -redlb[v])
14843 && redlb[v] < SCIPvarGetUbGlobal(var) )
14844 {
14845 SCIP_Real ub;
14846
14847 /* if x_v >= redlb[v], we can always round x_v down to x_v == redlb[v] without violating any constraint
14848 * -> tighten upper bound to x_v <= redlb[v]
14849 */
14850 SCIPdebugMsg(scip, "variable <%s> only locked down in linear constraints: dual presolve <%s>[%.15g,%.15g] <= %.15g\n",
14852 redlb[v]);
14853 SCIP_CALL( SCIPtightenVarUb(scip, var, redlb[v], FALSE, &infeasible, &tightened) );
14854 assert(!infeasible);
14855
14856 ub = SCIPvarGetUbGlobal(var);
14857 redub[v] = MIN(redub[v], ub);
14858 if( tightened )
14859 (*nchgbds)++;
14860 }
14861 }
14862 if( !SCIPisPositive(scip, obj) )
14863 {
14864 /* making the variable as large as possible does not increase the objective:
14865 * check if all up locks of the variables are due to linear constraints;
14866 * if variable is cost neutral and only lower bounded non-negatively or positive smallest bound to make
14867 * constraints redundant is huge, we better do nothing for numerical reasons
14868 */
14871 && !SCIPisHugeValue(scip, redub[v])
14872 && redub[v] > SCIPvarGetLbGlobal(var) )
14873 {
14874 SCIP_Real lb;
14875
14876 /* if x_v <= redub[v], we can always round x_v up to x_v == redub[v] without violating any constraint
14877 * -> tighten lower bound to x_v >= redub[v]
14878 */
14879 SCIPdebugMsg(scip, "variable <%s> only locked up in linear constraints: dual presolve <%s>[%.15g,%.15g] >= %.15g\n",
14881 redub[v]);
14882 SCIP_CALL( SCIPtightenVarLb(scip, var, redub[v], FALSE, &infeasible, &tightened) );
14883 assert(!infeasible);
14884
14885 lb = SCIPvarGetLbGlobal(var);
14886 redlb[v] = MAX(redlb[v], lb);
14887 if( tightened )
14888 (*nchgbds)++;
14889 }
14890 }
14891 }
14892
14893 /* @TODO: improve range names */
14894 /* declare continuous variables implied integral */
14895 for( v = nintvars - nbinvars; v < nvars; ++v )
14896 {
14897 SCIP_VAR* var;
14898 SCIP_Bool infeasible;
14899
14900 var = vars[v];
14901 assert(var != NULL);
14902
14906 assert(0 <= v - nintvars + nbinvars && v - nintvars + nbinvars < ncontvars);
14907
14908 /* @TODO: relax lock conditions */
14909 /* we can only conclude implied integrality if the variable appears in no other constraint */
14910 if( isimplint[v - nintvars + nbinvars]
14912 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v] )
14913 {
14914 /* since we locally copied the variable array we can change the variable type immediately */
14917 (*nchgvartypes)++;
14918 if( infeasible )
14919 {
14920 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
14921 *cutoff = TRUE;
14922
14923 break;
14924 }
14925
14926 SCIPdebugMsg(scip, "dual presolve: declare continuous variable <%s>[%g,%g] implied integral\n",
14928 }
14929 }
14930
14931 /* free temporary memory */
14932 SCIPfreeBufferArray(scip, &conscontvars);
14933 SCIPfreeBufferArray(scip, &isimplint);
14934 SCIPfreeBufferArray(scip, &nlocksup);
14935 SCIPfreeBufferArray(scip, &nlocksdown);
14936 SCIPfreeBufferArray(scip, &redub);
14937 SCIPfreeBufferArray(scip, &redlb);
14938
14940
14941 return SCIP_OKAY;
14942}
14943
14944/** helper function to enforce constraints */
14945static
14947 SCIP* scip, /**< SCIP data structure */
14948 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
14949 SCIP_CONS** conss, /**< constraints to process */
14950 int nconss, /**< number of constraints */
14951 int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
14952 SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
14953 SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
14954 )
14955{
14956 SCIP_CONSHDLRDATA* conshdlrdata;
14957 SCIP_Bool checkrelmaxabs;
14958 SCIP_Bool violated;
14960 int c;
14961
14962 assert(scip != NULL);
14963 assert(conshdlr != NULL);
14964 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
14965 assert(result != NULL);
14966
14967 conshdlrdata = SCIPconshdlrGetData(conshdlr);
14968 assert(conshdlrdata != NULL);
14969
14970 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
14971
14972 SCIPdebugMsg(scip, "Enforcement method of linear constraints for %s solution\n", sol == NULL ? "LP" : "relaxation");
14973
14974 /* check for violated constraints
14975 * LP is processed at current node -> we can add violated linear constraints to the SCIP_LP
14976 */
14978
14979 /* check all useful linear constraints for feasibility */
14980 for( c = 0; c < nusefulconss; ++c )
14981 {
14982 SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
14983
14984 if( violated )
14985 {
14986 /* insert LP row as cut */
14987 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
14988 if ( cutoff )
14990 else
14992 }
14993 }
14994
14995 /* check all obsolete linear constraints for feasibility */
14996 for( c = nusefulconss; c < nconss && *result == SCIP_FEASIBLE; ++c )
14997 {
14998 SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
14999
15000 if( violated )
15001 {
15002 /* insert LP row as cut */
15003 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15004 if ( cutoff )
15006 else
15008 }
15009 }
15010
15011 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
15012
15013 return SCIP_OKAY;
15014}
15015
15016/** adds symmetry information of constraint to a symmetry detection graph */
15017static
15019 SCIP* scip, /**< SCIP pointer */
15020 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
15021 SCIP_CONS* cons, /**< constraint */
15022 SYM_GRAPH* graph, /**< symmetry detection graph */
15023 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
15024 )
15025{
15026 SCIP_CONSDATA* consdata;
15027 SCIP_VAR** vars;
15028 SCIP_Real* vals;
15029 SCIP_Real constant = 0.0;
15030 SCIP_Real lhs;
15031 SCIP_Real rhs;
15032 int nlocvars;
15033 int nvars;
15034 int i;
15035
15036 assert(scip != NULL);
15037 assert(cons != NULL);
15038 assert(graph != NULL);
15039 assert(success != NULL);
15040
15041 consdata = SCIPconsGetData(cons);
15042 assert(consdata != NULL);
15043
15044 /* get active variables of the constraint */
15046 nlocvars = consdata->nvars;
15047
15050
15051 for( i = 0; i < nlocvars; ++i )
15052 {
15053 vars[i] = consdata->vars[i];
15054 vals[i] = consdata->vals[i];
15055 }
15056
15057 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
15058 lhs = consdata->lhs - constant;
15059 rhs = consdata->rhs - constant;
15060
15061 /* if rhs is infinite, normalize rhs to be finite to make sure that different encodings
15062 * of the same constraint are rated as equal
15063 */
15064 if ( SCIPisInfinity(scip, rhs) )
15065 {
15066 SCIP_Real tmp;
15067 assert(!SCIPisInfinity(scip, -lhs));
15068
15069 for( i = 0; i < nlocvars; ++i )
15070 vals[i] *= -1;
15071 tmp = rhs;
15072 rhs = -lhs;
15073 lhs = -tmp;
15074 }
15075
15077 cons, lhs, rhs, success) );
15078
15079 SCIPfreeBufferArray(scip, &vals);
15081
15082 return SCIP_OKAY;
15083}
15084
15085/*
15086 * Callback methods of constraint handler
15087 */
15088
15089/** copy method for constraint handler plugins (called when SCIP copies plugins) */
15090static
15091SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
15092{ /*lint --e{715}*/
15093 assert(scip != NULL);
15094 assert(conshdlr != NULL);
15095 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15096
15097 /* call inclusion method of constraint handler */
15099
15100 *valid = TRUE;
15101
15102 return SCIP_OKAY;
15103}
15104
15105/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
15106static
15107SCIP_DECL_CONSFREE(consFreeLinear)
15108{ /*lint --e{715}*/
15109 SCIP_CONSHDLRDATA* conshdlrdata;
15110
15111 assert(scip != NULL);
15112 assert(conshdlr != NULL);
15113 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15114
15115 /* free constraint handler data */
15116 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15117 assert(conshdlrdata != NULL);
15118
15119 conshdlrdataFree(scip, &conshdlrdata);
15120
15121 SCIPconshdlrSetData(conshdlr, NULL);
15122
15123 return SCIP_OKAY;
15124}
15125
15126
15127/** initialization method of constraint handler (called after problem was transformed) */
15128static
15129SCIP_DECL_CONSINIT(consInitLinear)
15130{
15131 SCIP_CONSHDLRDATA* conshdlrdata;
15132 int c;
15133
15134 assert(scip != NULL);
15135
15136 /* check for event handler */
15137 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15138 assert(conshdlrdata != NULL);
15139 assert(conshdlrdata->eventhdlr != NULL);
15140 assert(nconss == 0 || conss != NULL);
15141
15142 conshdlrdata->naddconss = 0;
15143
15144 /* catch events for the constraints */
15145 for( c = 0; c < nconss; ++c )
15146 {
15147 /* catch all events */
15148 SCIP_CALL( consCatchAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15149 }
15150
15151 return SCIP_OKAY;
15152}
15153
15154
15155/** deinitialization method of constraint handler (called before transformed problem is freed) */
15156static
15157SCIP_DECL_CONSEXIT(consExitLinear)
15158{
15159 SCIP_CONSHDLRDATA* conshdlrdata;
15160 int c;
15161
15162 assert(scip != NULL);
15163
15164 /* check for event handler */
15165 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15166 assert(conshdlrdata != NULL);
15167 assert(conshdlrdata->eventhdlr != NULL);
15168
15169 /* drop events for the constraints */
15170 for( c = nconss - 1; c >= 0; --c )
15171 {
15172 SCIP_CONSDATA* consdata;
15173
15174 consdata = SCIPconsGetData(conss[c]);
15175 assert(consdata != NULL);
15176
15177 if( consdata->eventdata != NULL )
15178 {
15179 /* drop all events */
15180 SCIP_CALL( consDropAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15181 assert(consdata->eventdata == NULL);
15182 }
15183 }
15184
15185 return SCIP_OKAY;
15186}
15187
15188/** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15189static
15191 SCIP* scip, /**< SCIP data structure */
15192 SCIP_Real lhs, /**< left hand side */
15193 SCIP_Real rhs /**< right hand side */
15194 )
15195{
15196 assert(scip != NULL);
15197
15198 return !(SCIPisEQ(scip, lhs, rhs) || SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs) );
15199}
15200
15201/** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15202static
15204 SCIP* scip, /**< SCIP data structure */
15205 SCIP_Real x /**< value */
15206 )
15207{
15208 assert(scip != NULL);
15209
15210 return (!SCIPisInfinity(scip, x) && !SCIPisNegative(scip, x) && SCIPisIntegral(scip, x));
15211}
15212
15213/** performs linear constraint type classification as used for MIPLIB
15214 *
15215 * iterates through all linear constraints and stores relevant statistics in the linear constraint statistics \p linconsstats.
15216 *
15217 * @note only constraints are iterated that belong to the linear constraint handler. If the problem has been presolved already,
15218 * constraints that were upgraded to more special types such as, e.g., varbound constraints, will not be shown correctly anymore.
15219 * Similarly, if specialized constraints were created through the API, these are currently not present.
15220 */
15222 SCIP* scip, /**< SCIP data structure */
15223 SCIP_LINCONSSTATS* linconsstats /**< linear constraint type classification */
15224 )
15225{
15226 int c;
15227 SCIP_CONSHDLR* conshdlr;
15228 SCIP_CONS** conss;
15229 int nconss;
15230
15231 assert(scip != NULL);
15232 assert(linconsstats != NULL);
15233 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
15234 assert(conshdlr != NULL);
15235
15237 {
15238 conss = SCIPgetConss(scip);
15239 nconss = SCIPgetNConss(scip);
15240 }
15241 else
15242 {
15243 conss = SCIPconshdlrGetConss(conshdlr);
15244 nconss = SCIPconshdlrGetNConss(conshdlr);
15245 }
15246
15247 /* reset linear constraint type classification */
15248 SCIPlinConsStatsReset(linconsstats);
15249
15250 /* loop through all constraints */
15251 for( c = 0; c < nconss; c++ )
15252 {
15253 SCIP_CONS* cons;
15254 SCIP_CONSDATA* consdata;
15255 SCIP_Real lhs;
15256 SCIP_Real rhs;
15257 int i;
15258
15259 /* get constraint */
15260 cons = conss[c];
15261 assert(cons != NULL);
15262
15263 /* skip constraints that are not handled by the constraint handler */
15264 if( SCIPconsGetHdlr(cons) != conshdlr )
15265 continue;
15266
15267 /* get constraint data */
15268 consdata = SCIPconsGetData(cons);
15269 assert(consdata != NULL);
15270 rhs = consdata->rhs;
15271 lhs = consdata->lhs;
15272
15273 /* merge multiples and delete variables with zero coefficient */
15274 SCIP_CALL( mergeMultiples(scip, cons) );
15275 for( i = 0; i < consdata->nvars; i++ )
15276 {
15277 assert(!SCIPisZero(scip, consdata->vals[i]));
15278 }
15279
15280 /* is constraint of type SCIP_CONSTYPE_EMPTY? */
15281 if( consdata->nvars == 0 )
15282 {
15283 SCIPdebugMsg(scip, "classified as EMPTY: ");
15286
15287 continue;
15288 }
15289
15290 /* is constraint of type SCIP_CONSTYPE_FREE? */
15291 if( SCIPisInfinity(scip, rhs) && SCIPisInfinity(scip, -lhs) )
15292 {
15293 SCIPdebugMsg(scip, "classified as FREE: ");
15296
15297 continue;
15298 }
15299
15300 /* is constraint of type SCIP_CONSTYPE_SINGLETON? */
15301 if( consdata->nvars == 1 )
15302 {
15303 SCIPdebugMsg(scip, "classified as SINGLETON: ");
15306
15307 continue;
15308 }
15309
15310 /* is constraint of type SCIP_CONSTYPE_AGGREGATION? */
15311 if( consdata->nvars == 2 && SCIPisEQ(scip, lhs, rhs) )
15312 {
15313 SCIPdebugMsg(scip, "classified as AGGREGATION: ");
15316
15317 continue;
15318 }
15319
15320 /* is constraint of type SCIP_CONSTYPE_{VARBOUND,PRECEDENCE}? */
15321 if( consdata->nvars == 2 )
15322 {
15323 /* precedence constraints have same variable type and same absolute coefficient with opposite sign */
15324 if( SCIPvarGetType(consdata->vars[0]) == SCIPvarGetType(consdata->vars[1])
15325 && SCIPisEQ(scip, consdata->vals[0], -consdata->vals[1]) )
15326 {
15327 SCIPdebugMsg(scip, "classified as PRECEDENCE: ");
15330
15331 continue;
15332 }
15333 /* varbound constraints have otherwise a binary variable */
15334 else if( SCIPvarGetType(consdata->vars[0]) == SCIP_VARTYPE_BINARY
15335 || SCIPvarGetType(consdata->vars[1]) == SCIP_VARTYPE_BINARY )
15336 {
15337 SCIPdebugMsg(scip, "classified as VARBOUND: ");
15340
15341 continue;
15342 }
15343 }
15344
15345 /* is constraint of type SCIP_CONSTYPE_{SETPARTITION, SETPACKING, SETCOVERING, CARDINALITY, INVKNAPSACK}? */
15346 {
15347 SCIP_Real scale;
15348 SCIP_Real b;
15349 SCIP_Bool unmatched;
15350 int nnegbinvars;
15351
15352 unmatched = FALSE;
15353 nnegbinvars = 0;
15354
15355 scale = REALABS(consdata->vals[0]);
15356
15357 /* scan through variables and detect if all variables are binary and have a coefficient +/-1 */
15358 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15359 {
15360 unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15361 unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15362 unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15363 unmatched = unmatched || !SCIPisEQ(scip, REALABS(consdata->vals[i]), scale);
15364
15365 if( consdata->vals[i] < 0.0 )
15366 nnegbinvars++;
15367 }
15368
15369 if( !unmatched )
15370 {
15371 if( SCIPisEQ(scip, lhs, rhs) )
15372 {
15373 b = rhs/scale + nnegbinvars;
15374 if( SCIPisEQ(scip, 1.0, b) )
15375 {
15376 SCIPdebugMsg(scip, "classified as SETPARTITION: ");
15379
15380 continue;
15381 }
15382 else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15383 {
15384 SCIPdebugMsg(scip, "classified as CARDINALITY: ");
15387
15388 continue;
15389 }
15390 }
15391
15392 /* compute right hand side divided by scale */
15393 if( !SCIPisInfinity(scip, rhs) )
15394 b = rhs/scale + nnegbinvars;
15395 else
15396 b = SCIPinfinity(scip);
15397
15398 if( SCIPisEQ(scip, 1.0, b) )
15399 {
15400 SCIPdebugMsg(scip, "classified as SETPACKING: ");
15403
15404 /* relax right hand side to prevent further classifications */
15405 rhs = SCIPinfinity(scip);
15406 }
15407 else if( !SCIPisInfinity(scip, b) && SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15408 {
15409 SCIPdebugMsg(scip, "classified as INVKNAPSACK: ");
15411
15413
15414 /* relax right hand side to prevent further classifications */
15415 rhs = SCIPinfinity(scip);
15416 }
15417
15418 if( !SCIPisInfinity(scip, lhs) )
15419 b = lhs/scale + nnegbinvars;
15420 else
15421 b = SCIPinfinity(scip);
15422
15423 if( SCIPisEQ(scip, 1.0, b) )
15424 {
15425 SCIPdebugMsg(scip, "classified as SETCOVERING: ");
15428
15429 /* relax left hand side to prevent further classifications */
15430 lhs = -SCIPinfinity(scip);
15431 }
15432
15433 /* if both sides are infinite at this point, no further classification is necessary for this constraint */
15434 if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
15435 continue;
15436 }
15437 }
15438
15439 /* is constraint of type SCIP_CONSTYPE_{EQKNAPSACK, BINPACKING, KNAPSACK}? */
15440 /* @todo If coefficients or rhs are not integral, we currently do not check
15441 * if the constraint could be scaled (finitely), such that they are.
15442 */
15443 {
15444 SCIP_Real b;
15445 SCIP_Bool unmatched;
15446
15447 b = rhs;
15448 unmatched = FALSE;
15449 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15450 {
15451 unmatched = unmatched || !SCIPvarIsIntegral(consdata->vars[i]);
15452 unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15453 unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15454 unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15455
15456 if( SCIPisNegative(scip, consdata->vals[i]) )
15457 b -= consdata->vals[i];
15458 }
15459 unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15460
15461 if( !unmatched )
15462 {
15463 if( SCIPisEQ(scip, lhs, rhs) )
15464 {
15465 SCIPdebugMsg(scip, "classified as EQKNAPSACK: ");
15467
15469
15470 continue;
15471 }
15472 else
15473 {
15474 SCIP_Bool matched;
15475
15476 matched = FALSE;
15477 for( i = 0; i < consdata->nvars && !matched; i++ )
15478 {
15479 matched = matched || SCIPisEQ(scip, b, REALABS(consdata->vals[i]));
15480 }
15481
15482 SCIPdebugMsg(scip, "classified as %s: ", matched ? "BINPACKING" : "KNAPSACK");
15485 }
15486
15487 /* check if finite left hand side allows for a second classification, relax already used right hand side */
15488 if( SCIPisInfinity(scip, -lhs) )
15489 continue;
15490 else
15491 rhs = SCIPinfinity(scip);
15492 }
15493 }
15494
15495 /* is constraint of type SCIP_CONSTYPE_{INTKNAPSACK}? */
15496 {
15497 SCIP_Real b;
15498 SCIP_Bool unmatched;
15499
15500 unmatched = FALSE;
15501
15502 b = rhs;
15503 unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15504
15505 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15506 {
15507 unmatched = unmatched || !SCIPvarIsIntegral(consdata->vars[i]);
15508 unmatched = unmatched || SCIPisNegative(scip, SCIPvarGetLbGlobal(consdata->vars[i]));
15509 unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15510 unmatched = unmatched || SCIPisNegative(scip, consdata->vals[i]);
15511 }
15512
15513 if( !unmatched )
15514 {
15515 SCIPdebugMsg(scip, "classified as INTKNAPSACK: ");
15518
15519 /* check if finite left hand side allows for a second classification, relax already used right hand side */
15520 if( SCIPisInfinity(scip, -lhs) )
15521 continue;
15522 else
15523 rhs = SCIPinfinity(scip);
15524 }
15525 }
15526
15527 /* is constraint of type SCIP_CONSTYPE_{MIXEDBINARY}? */
15528 {
15529 SCIP_Bool unmatched;
15530
15531 unmatched = FALSE;
15532 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15533 {
15534 if( SCIPvarIsIntegral(consdata->vars[i])
15535 && ( SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0)
15536 || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0) ) )
15537 unmatched = TRUE;
15538 }
15539
15540 if( !unmatched )
15541 {
15542 SCIPdebugMsg(scip, "classified as MIXEDBINARY (%d): ", isRangedRow(scip, lhs, rhs) ? 2 : 1);
15545
15546 continue;
15547 }
15548 }
15549
15550 /* no special structure detected */
15551 SCIPdebugMsg(scip, "classified as GENERAL: ");
15553 SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_GENERAL, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15554 }
15555
15556 return SCIP_OKAY;
15557}
15558
15559
15560/** presolving deinitialization method of constraint handler (called after presolving has been finished) */
15561static
15562SCIP_DECL_CONSEXITPRE(consExitpreLinear)
15563{ /*lint --e{715}*/
15564 int c;
15565#ifdef SCIP_STATISTIC
15566 SCIP_CONSHDLRDATA* conshdlrdata;
15567 int ngoodconss;
15568 int nallconss;
15569#endif
15570
15571 /* delete all linear constraints that were upgraded to a more specific constraint type;
15572 * make sure, only active variables remain in the remaining constraints
15573 */
15574 assert(scip != NULL);
15575
15576#ifdef SCIP_STATISTIC
15577 /* count number of well behaved linear constraints */
15578 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15579 assert(conshdlrdata != NULL);
15580
15581 ngoodconss = 0;
15582 nallconss = 0;
15583
15584 for( c = 0; c < nconss; ++c )
15585 {
15586 SCIP_CONSDATA* consdata;
15587
15588 if( SCIPconsIsDeleted(conss[c]) )
15589 continue;
15590
15591 consdata = SCIPconsGetData(conss[c]);
15592 assert(consdata != NULL);
15593
15594 if( consdata->upgraded )
15595 continue;
15596
15597 nallconss++;
15598
15600
15601 if( SCIPisLT(scip, consdata->maxactdelta, conshdlrdata->maxeasyactivitydelta) )
15602 ngoodconss++;
15603 }
15604 if( nallconss )
15605 {
15606 SCIPstatisticMessage("below threshold: %d / %d ratio= %g\n", ngoodconss, nallconss, (100.0 * ngoodconss / nallconss));
15607 }
15608#endif
15609
15610 for( c = 0; c < nconss; ++c )
15611 {
15612 SCIP_CONSDATA* consdata;
15613
15614 if( SCIPconsIsDeleted(conss[c]) )
15615 continue;
15616
15617 consdata = SCIPconsGetData(conss[c]);
15618 assert(consdata != NULL);
15619
15620 if( consdata->upgraded )
15621 {
15622 /* this is no problem reduction, because the upgraded constraint was added to the problem before, and the
15623 * (redundant) linear constraint was only kept in order to support presolving the the linear constraint handler
15624 */
15625 SCIP_CALL( SCIPdelCons(scip, conss[c]) );
15626 }
15627 else
15628 {
15629 /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */
15630 SCIP_CALL( applyFixings(scip, conss[c], NULL) );
15631 }
15632 }
15633
15634 return SCIP_OKAY;
15635}
15636
15637/** solving process initialization method of constraint handler */
15638static
15639SCIP_DECL_CONSINITSOL(consInitsolLinear)
15640{ /*lint --e{715}*/
15641 /* add nlrow representation to NLP, if NLP had been constructed */
15643 {
15644 int c;
15645 for( c = 0; c < nconss; ++c )
15646 {
15647 SCIP_CALL( addNlrow(scip, conss[c]) );
15648 }
15649 }
15650
15651 return SCIP_OKAY;
15652}
15653
15654/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
15655static
15656SCIP_DECL_CONSEXITSOL(consExitsolLinear)
15657{ /*lint --e{715}*/
15658 int c;
15659
15660 assert(scip != NULL);
15661
15662 /* release the rows and nlrows of all constraints */
15663 for( c = 0; c < nconss; ++c )
15664 {
15665 SCIP_CONSDATA* consdata;
15666
15667 consdata = SCIPconsGetData(conss[c]);
15668 assert(consdata != NULL);
15669
15670 if( consdata->row != NULL )
15671 {
15672 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
15673 }
15674
15675 if( consdata->nlrow != NULL )
15676 {
15677 SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
15678 }
15679 }
15680
15681 /* if this is a restart, convert cutpool rows into linear constraints */
15682 if( restart )
15683 {
15684 int ncutsadded;
15685
15686 ncutsadded = 0;
15687
15688 /* create out of all active cuts in cutpool linear constraints */
15689 SCIP_CALL( SCIPconvertCutsToConss(scip, NULL, NULL, TRUE, &ncutsadded) );
15690
15691 if( ncutsadded > 0 )
15692 {
15694 "(restart) converted %d cuts from the global cut pool into linear constraints\n", ncutsadded);
15695 /* an extra blank line should be printed separately since the buffer message handler only handles up to one
15696 * line correctly
15697 */
15699 }
15700 }
15701
15702 return SCIP_OKAY;
15703}
15704
15705
15706/** constraint activation notification method of constraint handler */
15707static
15708SCIP_DECL_CONSACTIVE(consActiveLinear)
15709{ /*lint --e{715}*/
15710 assert(cons != NULL);
15711
15713 {
15714 SCIP_CALL( addNlrow(scip, cons) );
15715 }
15716
15717 return SCIP_OKAY;
15718}
15719
15720/** constraint deactivation notification method of constraint handler */
15721static
15722SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
15723{ /*lint --e{715}*/
15724 SCIP_CONSDATA* consdata;
15725
15726 assert(scip != NULL);
15727 assert(conshdlr != NULL);
15728 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15729 assert(cons != NULL );
15730
15731 /* get constraint data */
15732 consdata = SCIPconsGetData(cons);
15733 assert(consdata != NULL);
15734
15735 if( SCIPconsIsDeleted(cons) )
15736 {
15737 SCIP_CONSHDLRDATA* conshdlrdata;
15738
15739 /* check for event handler */
15740 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15741 assert(conshdlrdata != NULL);
15742 assert(conshdlrdata->eventhdlr != NULL);
15743
15744 /* free event data */
15745 if( consdata->eventdata != NULL )
15746 {
15747 /* drop bound change events of variables */
15748 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15749 }
15750 assert(consdata->eventdata == NULL);
15751 }
15752
15753 /* remove row from NLP, if still in solving
15754 * if we are in exitsolve, the whole NLP will be freed anyway
15755 */
15756 if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
15757 {
15758 SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
15759 }
15760
15761 return SCIP_OKAY;
15762}
15763
15764
15765/** frees specific constraint data */
15766static
15767SCIP_DECL_CONSDELETE(consDeleteLinear)
15768{ /*lint --e{715}*/
15769 assert(scip != NULL);
15770 assert(conshdlr != NULL);
15771 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15772
15773 if( (*consdata)->eventdata != NULL )
15774 {
15775 SCIP_CONSHDLRDATA* conshdlrdata;
15776
15777 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15778 assert(conshdlrdata != NULL);
15779
15780 /* drop all events */
15781 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15782 assert((*consdata)->eventdata == NULL);
15783 }
15784
15785 /* free linear constraint */
15786 SCIP_CALL( consdataFree(scip, consdata) );
15787
15788 return SCIP_OKAY;
15789}
15790
15791
15792/** transforms constraint data into data belonging to the transformed problem */
15793static
15794SCIP_DECL_CONSTRANS(consTransLinear)
15795{ /*lint --e{715}*/
15796 SCIP_CONSDATA* sourcedata;
15797 SCIP_CONSDATA* targetdata;
15798
15799 /*debugMsg(scip, "Trans method of linear constraints\n");*/
15800
15801 assert(scip != NULL);
15802 assert(conshdlr != NULL);
15803 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15805 assert(sourcecons != NULL);
15806 assert(targetcons != NULL);
15807
15808 sourcedata = SCIPconsGetData(sourcecons);
15809 assert(sourcedata != NULL);
15810 assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
15811
15812 /* create linear constraint data for target constraint */
15813 SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars, sourcedata->vals, sourcedata->lhs,
15814 sourcedata->rhs) );
15815
15816#ifndef NDEBUG
15817 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
15818 if( SCIPconsIsEnforced(sourcecons) || SCIPconsIsChecked(sourcecons) )
15819 {
15820 int n;
15821 for(n = targetdata->nvars - 1; n >= 0; --n )
15822 assert(!SCIPvarIsRelaxationOnly(targetdata->vars[n]));
15823 }
15824#endif
15825
15826 /* create target constraint */
15827 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
15828 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
15829 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
15830 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
15831 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
15832
15833 return SCIP_OKAY;
15834}
15835
15836
15837/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
15838static
15839SCIP_DECL_CONSINITLP(consInitlpLinear)
15840{ /*lint --e{715}*/
15841 int c;
15842
15843 assert(scip != NULL);
15844 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15845
15846 *infeasible = FALSE;
15847
15848 for( c = 0; c < nconss && !(*infeasible); ++c )
15849 {
15850 assert(SCIPconsIsInitial(conss[c]));
15851 SCIP_CALL( addRelaxation(scip, conss[c], infeasible) );
15852 }
15853
15854 return SCIP_OKAY;
15855}
15856
15857
15858/** separation method of constraint handler for LP solutions */
15859static
15860SCIP_DECL_CONSSEPALP(consSepalpLinear)
15861{ /*lint --e{715}*/
15862 SCIP_CONSHDLRDATA* conshdlrdata;
15863 SCIP_Real loclowerbound;
15864 SCIP_Real glblowerbound;
15865 SCIP_Real cutoffbound;
15866 SCIP_Real maxbound;
15867 SCIP_Bool separatecards;
15869 int c;
15870 int depth;
15871 int nrounds;
15872 int maxsepacuts;
15873 int ncuts;
15874
15875 assert(scip != NULL);
15876 assert(conshdlr != NULL);
15877 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15878 assert(result != NULL);
15879
15880 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15881 assert(conshdlrdata != NULL);
15883 nrounds = SCIPgetNSepaRounds(scip);
15884
15885 /*debugMsg(scip, "Sepa method of linear constraints\n");*/
15886
15888
15889 /* only call the separator a given number of times at each node */
15890 if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
15891 || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
15892 return SCIP_OKAY;
15893
15894 /* get the maximal number of cuts allowed in a separation round */
15895 maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
15896
15897 /* check if we want to produce knapsack cardinality cuts at this node */
15898 loclowerbound = SCIPgetLocalLowerbound(scip);
15899 glblowerbound = SCIPgetLowerbound(scip);
15900 cutoffbound = SCIPgetCutoffbound(scip);
15901 maxbound = glblowerbound + conshdlrdata->maxcardbounddist * (cutoffbound - glblowerbound);
15902 separatecards = SCIPisLE(scip, loclowerbound, maxbound);
15903 separatecards = separatecards && (SCIPgetNLPBranchCands(scip) > 0);
15904
15906 ncuts = 0;
15907 cutoff = FALSE;
15908
15909 /* check all useful linear constraints for feasibility */
15910 for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
15911 {
15912 /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
15913 SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, NULL, separatecards, conshdlrdata->separateall, &ncuts, &cutoff) );
15914 }
15915
15916 /* adjust return value */
15917 if( cutoff )
15919 else if( ncuts > 0 )
15921
15922 /* combine linear constraints to get more cuts */
15923 /**@todo further cuts of linear constraints */
15924
15925 return SCIP_OKAY;
15926}
15927
15928
15929/** separation method of constraint handler for arbitrary primal solutions */
15930static
15931SCIP_DECL_CONSSEPASOL(consSepasolLinear)
15932{ /*lint --e{715}*/
15933 SCIP_CONSHDLRDATA* conshdlrdata;
15934 int c;
15935 int depth;
15936 int nrounds;
15937 int maxsepacuts;
15938 int ncuts;
15940
15941 assert(scip != NULL);
15942 assert(conshdlr != NULL);
15943 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15944 assert(result != NULL);
15945
15946 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15947 assert(conshdlrdata != NULL);
15949 nrounds = SCIPgetNSepaRounds(scip);
15950
15951 /*debugMsg(scip, "Sepa method of linear constraints\n");*/
15952
15954
15955 /* only call the separator a given number of times at each node */
15956 if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
15957 || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
15958 return SCIP_OKAY;
15959
15960 /* get the maximal number of cuts allowed in a separation round */
15961 maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
15962
15964 ncuts = 0;
15965 cutoff = FALSE;
15966
15967 /* check all useful linear constraints for feasibility */
15968 for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
15969 {
15970 /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
15971 SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, sol, TRUE, conshdlrdata->separateall, &ncuts, &cutoff) );
15972 }
15973
15974 /* adjust return value */
15975 if( cutoff )
15977 else if( ncuts > 0 )
15979
15980 /* combine linear constraints to get more cuts */
15981 /**@todo further cuts of linear constraints */
15982
15983 return SCIP_OKAY;
15984}
15985
15986
15987/** constraint enforcing method of constraint handler for LP solutions */
15988static
15989SCIP_DECL_CONSENFOLP(consEnfolpLinear)
15990{ /*lint --e{715}*/
15991 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
15992
15993 return SCIP_OKAY;
15994}
15995
15996/** constraint enforcing method of constraint handler for relaxation solutions */
15997static
15998SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
15999{ /*lint --e{715}*/
16000 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
16001
16002 return SCIP_OKAY;
16003}
16004
16005/** constraint enforcing method of constraint handler for pseudo solutions */
16006static
16007SCIP_DECL_CONSENFOPS(consEnfopsLinear)
16008{ /*lint --e{715}*/
16009 SCIP_CONSHDLRDATA* conshdlrdata;
16010 SCIP_Bool checkrelmaxabs;
16011 SCIP_Bool violated;
16012 int c;
16013
16014 assert(scip != NULL);
16015 assert(conshdlr != NULL);
16016 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16017 assert(result != NULL);
16018
16019 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16020 assert(conshdlrdata != NULL);
16021
16022 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16023
16024 SCIPdebugMsg(scip, "Enfops method of linear constraints\n");
16025
16026 /* if the solution is infeasible anyway due to objective value, skip the enforcement */
16027 if( objinfeasible )
16028 {
16029 SCIPdebugMsg(scip, "-> pseudo solution is objective infeasible, return.\n");
16030
16032 return SCIP_OKAY;
16033 }
16034
16035 /* check all linear constraints for feasibility */
16036 violated = FALSE;
16037 for( c = 0; c < nconss && !violated; ++c )
16038 {
16039 SCIP_CALL( checkCons(scip, conss[c], NULL, TRUE, checkrelmaxabs, &violated) );
16040 }
16041
16042 if( violated )
16044 else
16046
16047 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
16048
16049 return SCIP_OKAY;
16050}
16051
16052
16053/** feasibility check method of constraint handler for integral solutions */
16054static
16055SCIP_DECL_CONSCHECK(consCheckLinear)
16056{ /*lint --e{715}*/
16057 SCIP_CONSHDLRDATA* conshdlrdata;
16058 SCIP_Bool checkrelmaxabs;
16059 int c;
16060
16061 assert(scip != NULL);
16062 assert(conshdlr != NULL);
16063 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16064 assert(result != NULL);
16065
16067
16068 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16069 assert(conshdlrdata != NULL);
16070
16071 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16072
16073 /*debugMsg(scip, "Check method of linear constraints\n");*/
16074
16075 /* check all linear constraints for feasibility */
16076 for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
16077 {
16078 SCIP_Bool violated = FALSE;
16079 SCIP_CALL( checkCons(scip, conss[c], sol, checklprows, checkrelmaxabs, &violated) );
16080
16081 if( violated )
16082 {
16084
16085 if( printreason )
16086 {
16087 SCIP_CONSDATA* consdata;
16088 SCIP_Real activity;
16089
16090 consdata = SCIPconsGetData(conss[c]);
16091 assert( consdata != NULL);
16092
16093 activity = consdataGetActivity(scip, consdata, sol);
16094
16095 SCIP_CALL( consPrintConsSol(scip, conss[c], sol, NULL ) );
16096 SCIPinfoMessage(scip, NULL, ";\n");
16097
16098 if( activity == SCIP_INVALID || SCIPisInfinity(scip, ABS(activity)) ) /*lint !e777*/
16099 SCIPinfoMessage(scip, NULL, "activity invalid due to infinity contributions\n");
16100 else if( SCIPisFeasLT(scip, activity, consdata->lhs) )
16101 SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - activity);
16102 else if( SCIPisFeasGT(scip, activity, consdata->rhs) )
16103 SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - consdata->rhs);
16104 }
16105 }
16106 }
16107
16108 return SCIP_OKAY;
16109}
16110
16111
16112/** domain propagation method of constraint handler */
16113static
16114SCIP_DECL_CONSPROP(consPropLinear)
16115{ /*lint --e{715}*/
16116 SCIP_CONSHDLRDATA* conshdlrdata;
16117 SCIP_Bool rangedrowpropagation = FALSE;
16118 SCIP_Bool tightenbounds;
16120 int naddedconss = 0;
16121 int nchgbds = 0;
16122 int i;
16123
16124 assert(scip != NULL);
16125 assert(conshdlr != NULL);
16126 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16127 assert(result != NULL);
16128
16129 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16130 assert(conshdlrdata != NULL);
16131
16132 /*debugMsg(scip, "Prop method of linear constraints\n");*/
16133
16134 /* check, if we want to tighten variable's bounds (in probing, we always want to tighten the bounds) */
16135 if( SCIPinProbing(scip) )
16136 tightenbounds = TRUE;
16137 else
16138 {
16139 int depth;
16140 int propfreq;
16141 int tightenboundsfreq;
16142 int rangedrowfreq;
16143
16145 propfreq = SCIPconshdlrGetPropFreq(conshdlr);
16146 tightenboundsfreq = propfreq * conshdlrdata->tightenboundsfreq;
16147 tightenbounds = (conshdlrdata->tightenboundsfreq >= 0)
16148 && ((tightenboundsfreq == 0 && depth == 0) || (tightenboundsfreq >= 1 && (depth % tightenboundsfreq == 0)));
16149
16150 /* check if we want to do ranged row propagation */
16151 rangedrowpropagation = conshdlrdata->rangedrowpropagation;
16152 rangedrowpropagation = rangedrowpropagation && !SCIPinRepropagation(scip);
16153 rangedrowpropagation = rangedrowpropagation && (depth <= conshdlrdata->rangedrowmaxdepth);
16154 rangedrowfreq = propfreq * conshdlrdata->rangedrowfreq;
16155 rangedrowpropagation = rangedrowpropagation && (conshdlrdata->rangedrowfreq >= 0)
16156 && ((rangedrowfreq == 0 && depth == 0) || (rangedrowfreq >= 1 && (depth % rangedrowfreq == 0)));
16157 rangedrowpropagation = rangedrowpropagation && (SCIPgetStage(scip) != SCIP_STAGE_PRESOLVING); /* ranged rows are also presolved */
16158 }
16159
16160 cutoff = FALSE;
16161
16162 /* process constraints marked for propagation */
16163 for( i = 0; i < nmarkedconss && !cutoff; i++ )
16164 {
16166 SCIP_CALL( propagateCons(scip, conss[i], tightenbounds, rangedrowpropagation,
16167 conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, &nchgbds, &naddedconss) );
16168 assert(naddedconss == 0 || (SCIPgetStage(scip) != SCIP_STAGE_PRESOLVING));
16169 }
16170
16171 /* adjust result code */
16172 if( cutoff )
16174 else if( nchgbds > 0 )
16176 else if( naddedconss > 0 )
16178 else
16180
16181 return SCIP_OKAY;
16182}
16183
16184
16185#define MAXCONSPRESOLROUNDS 10
16186/** presolving method of constraint handler */
16187static
16188SCIP_DECL_CONSPRESOL(consPresolLinear)
16189{ /*lint --e{715}*/
16190 SCIP_CONSHDLRDATA* conshdlrdata;
16191 SCIP_CONS* cons;
16192 SCIP_CONSDATA* consdata;
16193 SCIP_Real minactivity;
16194 SCIP_Real maxactivity;
16195 SCIP_Bool isminacttight;
16196 SCIP_Bool ismaxacttight;
16197 SCIP_Bool isminsettoinfinity;
16198 SCIP_Bool ismaxsettoinfinity;
16200 int oldnfixedvars;
16201 int oldnaggrvars;
16202 int oldnchgbds;
16203 int oldndelconss;
16204 int oldnupgdconss;
16205 int oldnchgcoefs;
16206 int oldnchgsides;
16207 int firstchange;
16208 int firstupgradetry;
16209 int c;
16210
16211 assert(scip != NULL);
16212 assert(conshdlr != NULL);
16213 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16214 assert(result != NULL);
16215
16216 /*debugMsg(scip, "Presol method of linear constraints\n");*/
16217
16218 /* remember old preprocessing counters */
16219 cutoff = FALSE;
16220 oldnfixedvars = *nfixedvars;
16221 oldnaggrvars = *naggrvars;
16222 oldnchgbds = *nchgbds;
16223 oldndelconss = *ndelconss;
16224 oldnupgdconss = *nupgdconss;
16225 oldnchgcoefs = *nchgcoefs;
16226 oldnchgsides = *nchgsides;
16227
16228 /* get constraint handler data */
16229 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16230 assert(conshdlrdata != NULL);
16231
16232 /* process single constraints */
16233 firstchange = INT_MAX;
16234 firstupgradetry = INT_MAX;
16235 for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
16236 {
16237 int npresolrounds;
16238 SCIP_Bool infeasible;
16239
16240 infeasible = FALSE;
16241
16242 cons = conss[c];
16243 assert(SCIPconsIsActive(cons));
16244 consdata = SCIPconsGetData(cons);
16245 assert(consdata != NULL);
16246
16247 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
16248 if( SCIPisEQ(scip, consdata->rhs, consdata->lhs) )
16249 {
16250 consdata->lhs = consdata->rhs;
16251 assert(consdata->row == NULL);
16252 }
16253
16254 if( consdata->eventdata == NULL )
16255 {
16256 /* catch bound change events of variables */
16257 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
16258 assert(consdata->eventdata != NULL);
16259 }
16260
16261 /* constraint should not be already presolved in the initial round */
16262 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || SCIPconsIsMarkedPropagate(cons));
16263 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || consdata->boundstightened == 0);
16264 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->presolved);
16265 assert(!SCIPconsIsMarkedPropagate(cons) || !consdata->presolved);
16266
16267 /* incorporate fixings and aggregations in constraint */
16268 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
16269
16270 if( infeasible )
16271 {
16272 SCIPdebugMsg(scip, " -> infeasible fixing\n");
16273 cutoff = TRUE;
16274 break;
16275 }
16276
16277 assert(consdata->removedfixings);
16278
16279 /* we can only presolve linear constraints, that are not modifiable */
16280 if( SCIPconsIsModifiable(cons) )
16281 continue;
16282
16283 /* remember the first changed constraint to begin the next aggregation round with */
16284 if( firstchange == INT_MAX && consdata->changed )
16285 firstchange = c;
16286
16287 /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16288 if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16289 firstupgradetry = c;
16290
16291 /* check, if constraint is already preprocessed */
16292 if( consdata->presolved )
16293 continue;
16294
16295 assert(SCIPconsIsActive(cons));
16296
16297 SCIPdebugMsg(scip, "presolving linear constraint <%s>\n", SCIPconsGetName(cons));
16299
16300 /* apply presolving as long as possible on the single constraint (however, abort after a certain number of rounds
16301 * to avoid nearly infinite cycling due to very small bound changes)
16302 */
16303 npresolrounds = 0;
16304 while( !consdata->presolved && npresolrounds < MAXCONSPRESOLROUNDS && !SCIPisStopped(scip) )
16305 {
16306 assert(!cutoff);
16307 npresolrounds++;
16308
16309 /* mark constraint being presolved and propagated */
16310 consdata->presolved = TRUE;
16312
16313 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
16314
16315 if( infeasible )
16316 {
16317 SCIPdebugMsg(scip, " -> infeasible normalization\n");
16318 cutoff = TRUE;
16319 break;
16320 }
16321
16322 /* tighten left and right hand side due to integrality */
16323 SCIP_CALL( tightenSides(scip, cons, nchgsides, &infeasible) );
16324
16325 if( infeasible )
16326 {
16327 SCIPdebugMsg(scip, " -> infeasibility detected during tightening sides\n");
16328 cutoff = TRUE;
16329 break;
16330 }
16331
16332 /* check bounds */
16333 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16334 {
16335 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16336 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16337 cutoff = TRUE;
16338 break;
16339 }
16340
16341 /* tighten variable's bounds */
16342 SCIP_CALL( tightenBounds(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, nchgbds) );
16343 if( cutoff )
16344 break;
16345
16346 /* check for fixed variables */
16347 SCIP_CALL( fixVariables(scip, cons, &cutoff, nfixedvars) );
16348 if( cutoff )
16349 break;
16350
16351 /* if the maximal coefficient is large, recompute the activities before infeasibility and redundancy checks */
16352 if( ( consdata->validmaxabsval && consdata->maxabsval > MAXVALRECOMP )
16353 || ( consdata->validminabsval && consdata->minabsval < MINVALRECOMP ) )
16354 {
16357 }
16358
16359 /* get activity bounds */
16360 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
16361 &isminsettoinfinity, &ismaxsettoinfinity);
16362
16363 /* check constraint for infeasibility and redundancy */
16364 if( SCIPisFeasGT(scip, minactivity, consdata->rhs) || SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
16365 {
16366 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16367 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16368 cutoff = TRUE;
16369 break;
16370 }
16371 else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16372 {
16373 SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16374 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16375 SCIP_CALL( SCIPdelCons(scip, cons) );
16376 assert(!SCIPconsIsActive(cons));
16377
16378 if( !consdata->upgraded )
16379 (*ndelconss)++;
16380 break;
16381 }
16382 else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisGE(scip, minactivity, consdata->lhs) )
16383 {
16384 SCIPdebugMsg(scip, "linear constraint <%s> left hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16385 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16386 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
16387 if( !consdata->upgraded )
16388 (*nchgsides)++;
16389 }
16390 else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16391 {
16392 SCIPdebugMsg(scip, "linear constraint <%s> right hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16393 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16395 if( !consdata->upgraded )
16396 (*nchgsides)++;
16397 }
16398
16399 /* handle empty constraint */
16400 if( consdata->nvars == 0 )
16401 {
16402 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16403 {
16404 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16405 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16406 cutoff = TRUE;
16407 }
16408 else
16409 {
16410 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16411 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16412 SCIP_CALL( SCIPdelCons(scip, cons) );
16413 assert(!SCIPconsIsActive(cons));
16414
16415 if( !consdata->upgraded )
16416 (*ndelconss)++;
16417 }
16418 break;
16419 }
16420
16421 /* reduce big-M coefficients, that make the constraint redundant if the variable is on a bound */
16422 SCIP_CALL( consdataTightenCoefs(scip, cons, nchgcoefs, nchgsides) );
16423
16424 /* try to simplify inequalities */
16425 if( conshdlrdata->simplifyinequalities )
16426 {
16427 SCIP_CALL( simplifyInequalities(scip, cons, nchgcoefs, nchgsides, &cutoff) );
16428
16429 if( cutoff )
16430 break;
16431 }
16432
16433 /* aggregation variable in equations */
16434 if( conshdlrdata->aggregatevariables )
16435 {
16436 SCIP_CALL( aggregateVariables(scip, cons, &cutoff, nfixedvars, naggrvars) );
16437 if( cutoff )
16438 break;
16439 }
16440 }
16441
16442 if( !cutoff && !SCIPisStopped(scip) )
16443 {
16444 /* perform ranged row propagation */
16445 if( conshdlrdata->rangedrowpropagation )
16446 {
16447 int lastnfixedvars;
16448
16449 lastnfixedvars = *nfixedvars;
16450
16451 SCIP_CALL( rangedRowPropagation(scip, cons, &cutoff, nfixedvars, nchgbds, naddconss) );
16452 if( !cutoff )
16453 {
16454 if( lastnfixedvars < *nfixedvars )
16455 {
16456 SCIP_CALL( applyFixings(scip, cons, &cutoff) );
16457 }
16458 }
16459 }
16460
16461 /* extract cliques from constraint */
16462 if( conshdlrdata->extractcliques && !cutoff && SCIPconsIsActive(cons) )
16463 {
16464 SCIP_CALL( extractCliques(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars,
16465 nfixedvars, nchgbds, &cutoff) );
16466
16467 /* check if the constraint got redundant or infeasible */
16468 if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 0 )
16469 {
16470 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16471 {
16472 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16473 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16474 cutoff = TRUE;
16475 }
16476 else
16477 {
16478 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16479 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16480 SCIP_CALL( SCIPdelCons(scip, cons) );
16481 assert(!SCIPconsIsActive(cons));
16482
16483 if( !consdata->upgraded )
16484 (*ndelconss)++;
16485 }
16486 }
16487 }
16488
16489 /* convert special equalities */
16490 if( !cutoff && SCIPconsIsActive(cons) )
16491 {
16492 SCIP_CALL( convertEquality(scip, cons, conshdlrdata, &cutoff, nfixedvars, naggrvars, ndelconss, nchgvartypes) );
16493 }
16494
16495 /* apply dual presolving for variables that appear in only one constraint */
16496 if( !cutoff && SCIPconsIsActive(cons) && conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) )
16497 {
16498 SCIP_CALL( dualPresolve(scip, conshdlrdata, cons, &cutoff, nfixedvars, naggrvars, ndelconss, nchgvartypes) );
16499 }
16500
16501 /* check if an inequality is parallel to the objective function */
16502 if( !cutoff && SCIPconsIsActive(cons) )
16503 {
16504 SCIP_CALL( checkParallelObjective(scip, cons, conshdlrdata) );
16505 }
16506
16507 /* remember the first changed constraint to begin the next aggregation round with */
16508 if( firstchange == INT_MAX && consdata->changed )
16509 firstchange = c;
16510
16511 /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16512 if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16513 firstupgradetry = c;
16514 }
16515
16516 /* singleton column stuffing */
16517 if( !cutoff && SCIPconsIsActive(cons) && SCIPconsIsChecked(cons) &&
16518 (conshdlrdata->singletonstuffing || conshdlrdata->singlevarstuffing) && SCIPallowStrongDualReds(scip) )
16519 {
16520 SCIP_CALL( presolStuffing(scip, cons, conshdlrdata->singletonstuffing,
16521 conshdlrdata->singlevarstuffing, &cutoff, nfixedvars, nchgbds) );
16522
16523 /* handle empty constraint */
16524 if( consdata->nvars == 0 )
16525 {
16526 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16527 {
16528 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16529 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16530 cutoff = TRUE;
16531 }
16532 else
16533 {
16534 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16535 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16536 SCIP_CALL( SCIPdelCons(scip, cons) );
16537 assert(!SCIPconsIsActive(cons));
16538
16539 if( !consdata->upgraded )
16540 (*ndelconss)++;
16541 }
16542 break;
16543 }
16544 }
16545 }
16546
16547 /* process pairs of constraints: check them for redundancy and try to aggregate them;
16548 * only apply this expensive procedure in exhaustive presolving timing
16549 */
16550 if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && (conshdlrdata->presolusehashing || conshdlrdata->presolpairwise) && !SCIPisStopped(scip) )
16551 {
16552 assert(firstchange >= 0);
16553
16554 if( firstchange < nconss && conshdlrdata->presolusehashing )
16555 {
16556 /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
16557 SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff,
16558 ndelconss, nchgsides) );
16559 }
16560
16561 if( firstchange < nconss && conshdlrdata->presolpairwise )
16562 {
16563 SCIP_CONS** usefulconss;
16564 int nusefulconss;
16565 int firstchangenew;
16566 SCIP_Longint npaircomparisons;
16567
16568 npaircomparisons = 0;
16569 oldndelconss = *ndelconss;
16570 oldnchgsides = *nchgsides;
16571 oldnchgcoefs = *nchgcoefs;
16572
16573 /* allocate temporary memory */
16574 SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, nconss) );
16575
16576 nusefulconss = 0;
16577 firstchangenew = -1;
16578 for( c = 0; c < nconss; ++c )
16579 {
16580 /* update firstchange */
16581 if( c == firstchange )
16582 firstchangenew = nusefulconss;
16583
16584 /* ignore inactive and modifiable constraints */
16585 if( !SCIPconsIsActive(conss[c]) || SCIPconsIsModifiable(conss[c]) )
16586 continue;
16587
16588 usefulconss[nusefulconss] = conss[c];
16589 ++nusefulconss;
16590 }
16591 firstchange = firstchangenew;
16592 assert(firstchangenew >= 0 && firstchangenew <= nusefulconss);
16593
16594 for( c = firstchange; c < nusefulconss && !cutoff && !SCIPisStopped(scip); ++c )
16595 {
16596 /* constraint has become inactive or modifiable during pairwise presolving */
16597 if( usefulconss[c] == NULL )
16598 continue;
16599
16600 npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? c : (c - firstchange); /*lint !e776*/
16601
16602 assert(SCIPconsIsActive(usefulconss[c]) && !SCIPconsIsModifiable(usefulconss[c]));
16603 SCIP_CALL( preprocessConstraintPairs(scip, usefulconss, firstchange, c, conshdlrdata->maxaggrnormscale,
16604 &cutoff, ndelconss, nchgsides, nchgcoefs) );
16605
16606 if( npaircomparisons > conshdlrdata->nmincomparisons )
16607 {
16608 assert(npaircomparisons > 0);
16609 if( ((*ndelconss - oldndelconss) + (*nchgsides - oldnchgsides)/2.0 + (*nchgcoefs - oldnchgcoefs)/10.0) / ((SCIP_Real) npaircomparisons) < conshdlrdata->mingainpernmincomp )
16610 break;
16611 oldndelconss = *ndelconss;
16612 oldnchgsides = *nchgsides;
16613 oldnchgcoefs = *nchgcoefs;
16614 npaircomparisons = 0;
16615 }
16616 }
16617 /* free temporary memory */
16618 SCIPfreeBufferArray(scip, &usefulconss);
16619 }
16620 }
16621
16622 /* before upgrading, check whether we can apply some additional dual presolving, because a variable only appears
16623 * in linear constraints and we therefore have full information about it
16624 */
16625 if( !cutoff && firstupgradetry < nconss
16626 && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
16627 && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides
16628 )
16629 {
16630 if( conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) && !SCIPisStopped(scip) )
16631 {
16632 SCIP_CALL( fullDualPresolve(scip, conss, nconss, &cutoff, nchgbds, nchgvartypes) );
16633 }
16634 }
16635
16636 /* try to upgrade constraints into a more specific constraint type;
16637 * only upgrade constraints, if no reductions were found in this round (otherwise, the linear constraint handler
16638 * may find additional reductions before giving control away to other (less intelligent?) constraint handlers)
16639 */
16640 if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && SCIPisPresolveFinished(scip) )
16641 {
16642 for( c = firstupgradetry; c < nconss && !SCIPisStopped(scip); ++c )
16643 {
16644 cons = conss[c];
16645
16646 /* don't upgrade modifiable constraints */
16647 if( SCIPconsIsModifiable(cons) )
16648 continue;
16649
16650 consdata = SCIPconsGetData(cons);
16651 assert(consdata != NULL);
16652
16653 /* only upgrade completely presolved constraints, that changed since the last upgrading call */
16654 if( consdata->upgradetried )
16655 continue;
16656 /* @todo force that upgrade will be performed later? */
16657 if( !consdata->presolved )
16658 continue;
16659
16660 consdata->upgradetried = TRUE;
16661 if( SCIPconsIsActive(cons) )
16662 {
16663 SCIP_CONS* upgdcons;
16664
16665 SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
16666 if( upgdcons != NULL )
16667 {
16668 /* add the upgraded constraint to the problem */
16669 SCIP_CALL( SCIPaddConsUpgrade(scip, cons, &upgdcons) );
16670 ++(*nupgdconss);
16671
16672 /* mark the linear constraint being upgraded and to be removed after presolving;
16673 * don't delete it directly, because it may help to preprocess other linear constraints
16674 */
16675 assert(!consdata->upgraded);
16676 consdata->upgraded = TRUE;
16677
16678 /* delete upgraded inequalities immediately;
16679 * delete upgraded equalities, if we don't need it anymore for aggregation and redundancy checking
16680 */
16681 if( SCIPisLT(scip, consdata->lhs, consdata->rhs)
16682 || !conshdlrdata->presolpairwise
16683 || (conshdlrdata->maxaggrnormscale == 0.0) )
16684 {
16685 SCIP_CALL( SCIPdelCons(scip, cons) );
16686 }
16687 }
16688 }
16689 }
16690 }
16691
16692 /* return the correct result code */
16693 if( cutoff )
16695 else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss
16696 || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
16698 else
16700
16701 return SCIP_OKAY;
16702}
16703
16704
16705/** propagation conflict resolving method of constraint handler */
16706static
16707SCIP_DECL_CONSRESPROP(consRespropLinear)
16708{ /*lint --e{715}*/
16709 assert(scip != NULL);
16710 assert(cons != NULL);
16711 assert(result != NULL);
16712
16713 SCIP_CALL( resolvePropagation(scip, cons, infervar, intToInferInfo(inferinfo), boundtype, bdchgidx, result) );
16714
16715 return SCIP_OKAY;
16716}
16717
16718
16719/** variable rounding lock method of constraint handler */
16720static
16721SCIP_DECL_CONSLOCK(consLockLinear)
16722{ /*lint --e{715}*/
16723 SCIP_CONSDATA* consdata;
16724 SCIP_Bool haslhs;
16725 SCIP_Bool hasrhs;
16726 int i;
16727
16728 assert(scip != NULL);
16729 assert(cons != NULL);
16730 consdata = SCIPconsGetData(cons);
16731 assert(consdata != NULL);
16732
16733 haslhs = !SCIPisInfinity(scip, -consdata->lhs);
16734 hasrhs = !SCIPisInfinity(scip, consdata->rhs);
16735
16736 /* update rounding locks of every single variable */
16737 for( i = 0; i < consdata->nvars; ++i )
16738 {
16739 if( SCIPisPositive(scip, consdata->vals[i]) )
16740 {
16741 if( haslhs )
16742 {
16743 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16744 }
16745 if( hasrhs )
16746 {
16747 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16748 }
16749 }
16750 else
16751 {
16752 if( haslhs )
16753 {
16754 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16755 }
16756 if( hasrhs )
16757 {
16758 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16759 }
16760 }
16761 }
16762
16763 return SCIP_OKAY;
16764}
16765
16766
16767/** variable deletion method of constraint handler */
16768static
16769SCIP_DECL_CONSDELVARS(consDelvarsLinear)
16770{
16771 assert(scip != NULL);
16772 assert(conshdlr != NULL);
16773 assert(conss != NULL || nconss == 0);
16774
16775 if( nconss > 0 )
16776 {
16777 SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
16778 }
16779
16780 return SCIP_OKAY;
16781}
16782
16783/** constraint display method of constraint handler */
16784static
16785SCIP_DECL_CONSPRINT(consPrintLinear)
16786{ /*lint --e{715}*/
16787 assert(scip != NULL);
16788 assert(conshdlr != NULL);
16789 assert(cons != NULL);
16790
16792
16793 return SCIP_OKAY;
16794}
16795
16796/** constraint copying method of constraint handler */
16797static
16798SCIP_DECL_CONSCOPY(consCopyLinear)
16799{ /*lint --e{715}*/
16800 SCIP_VAR** sourcevars;
16801 SCIP_Real* sourcecoefs;
16802 const char* consname;
16803 int nvars;
16804
16805 assert(scip != NULL);
16806 assert(sourcescip != NULL);
16807 assert(sourcecons != NULL);
16808
16809 /* get variables and coefficients of the source constraint */
16810 sourcevars = SCIPgetVarsLinear(sourcescip, sourcecons);
16811 sourcecoefs = SCIPgetValsLinear(sourcescip, sourcecons);
16812 nvars = SCIPgetNVarsLinear(sourcescip, sourcecons);
16813
16814 if( name != NULL )
16815 consname = name;
16816 else
16817 consname = SCIPconsGetName(sourcecons);
16818
16819 SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, sourcecoefs,
16820 SCIPgetLhsLinear(sourcescip, sourcecons), SCIPgetRhsLinear(sourcescip, sourcecons), varmap, consmap,
16821 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
16822 assert(cons != NULL || *valid == FALSE);
16823
16824 /* @todo should also the checkabsolute flag of the constraint be copied? */
16825
16826 return SCIP_OKAY;
16827}
16828
16829/** find operators '<=', '==', '>=', [free] in input string and return those places
16830 *
16831 * There should only be one operator, except for ranged rows for which exactly two operators '<=' must be present.
16832 */
16833static
16835 const char* str, /**< null terminated input string */
16836 char** firstoperator, /**< pointer to store the string starting at the first operator */
16837 char** secondoperator, /**< pointer to store the string starting at the second operator */
16838 SCIP_Bool* success /**< pointer to store if the line contains a valid operator order */
16839 )
16840{
16841 char* curr;
16842
16843 assert(str != NULL);
16844 assert(firstoperator != NULL);
16845 assert(secondoperator != NULL);
16846
16847 *firstoperator = NULL;
16848 *secondoperator = NULL;
16849
16850 curr = (char*)str;
16851 *success = TRUE;
16852
16853 /* loop over the input string to find all operators */
16854 while( *curr && *success )
16855 {
16856 SCIP_Bool found = FALSE;
16857 int increment = 1;
16858
16859 /* try if we found a possible operator */
16860 switch( *curr )
16861 {
16862 case '<':
16863 case '=':
16864 case '>':
16865
16866 /* check if the two characters curr[0,1] form an operator together */
16867 if( curr[1] == '=' )
16868 {
16869 found = TRUE;
16870
16871 /* update increment to continue after this operator */
16872 increment = 2;
16873 }
16874 break;
16875 case '[':
16876 if( strncmp(curr, "[free]", 6) == 0 )
16877 {
16878 found = TRUE;
16879
16880 /* update increment to continue after this operator */
16881 increment = 6;
16882 }
16883 break;
16884 default:
16885 break;
16886 }
16887
16888 /* assign the found operator to the first or second pointer and check for violations of the linear constraint grammar */
16889 if( found )
16890 {
16891 if( *firstoperator == NULL )
16892 {
16893 *firstoperator = curr;
16894 }
16895 else
16896 {
16897 if( *secondoperator != NULL )
16898 {
16899 SCIPerrorMessage("Found more than two operators in line %s\n", str);
16900 *success = FALSE;
16901 }
16902 else if( strncmp(*firstoperator, "<=", 2) != 0 )
16903 {
16904 SCIPerrorMessage("Two operators in line that is not a ranged row: %s", str);
16905 *success = FALSE;
16906 }
16907 else if( strncmp(curr, "<=", 2) != 0 )
16908 {
16909 SCIPerrorMessage("Bad second operator, expected ranged row specification: %s", str);
16910 *success = FALSE;
16911 }
16912
16913 *secondoperator = curr;
16914 }
16915 }
16916
16917 curr += increment;
16918 }
16919
16920 /* check if we did find at least one operator */
16921 if( *success )
16922 {
16923 if( *firstoperator == NULL )
16924 {
16925 SCIPerrorMessage("Could not find any operator in line %s\n", str);
16926 *success = FALSE;
16927 }
16928 }
16929}
16930
16931/** constraint parsing method of constraint handler */
16932static
16933SCIP_DECL_CONSPARSE(consParseLinear)
16934{ /*lint --e{715}*/
16935 SCIP_VAR** vars;
16936 SCIP_Real* coefs = NULL;
16937 int nvars;
16938 int coefssize = 100;
16939 int requsize;
16940 SCIP_Real lhs;
16941 SCIP_Real rhs;
16942 char* endptr;
16943 char* firstop;
16944 char* secondop;
16945 SCIP_Bool operatorsuccess;
16946 char* lhsstrptr = NULL;
16947 char* rhsstrptr = NULL;
16948 char* varstrptr = (char*)str;
16949
16950 assert(scip != NULL);
16951 assert(success != NULL);
16952 assert(str != NULL);
16953 assert(name != NULL);
16954 assert(cons != NULL);
16955
16956 *success = FALSE;
16957
16958 /* return of string empty */
16959 if( !(*str) )
16960 return SCIP_OKAY;
16961
16962 /* set left and right hand side to their default values */
16963 lhs = -SCIPinfinity(scip);
16964 rhs = SCIPinfinity(scip);
16965
16966 /* ignore whitespace */
16967 SCIP_CALL( SCIPskipSpace((char**)&str) );
16968
16969 /* find operators in the line first, all other remaining parsing depends on occurence of the operators '<=', '>=', '==',
16970 * and the special word [free]
16971 */
16972 findOperators(str, &firstop, &secondop, &operatorsuccess);
16973
16974 /* if the grammar is not valid for parsing a linear constraint, return */
16975 if( ! operatorsuccess )
16976 return SCIP_OKAY;
16977 assert(firstop != NULL);
16978
16979 /* assign the strings for parsing the left hand side, right hand side, and the linear variable sum */
16980 switch( *firstop )
16981 {
16982 case '<':
16983 assert(firstop[1] == '=');
16984 /* we have ranged row lhs <= a_1 x_1 + ... + a_n x_n <= rhs */
16985 if( secondop != NULL )
16986 {
16987 assert(secondop[0] == '<' && secondop[1] == '=');
16988 lhsstrptr = (char *)str;
16989 varstrptr = firstop + 2;
16990 rhsstrptr = secondop + 2;
16991 }
16992 else
16993 {
16994 /* we have an inequality with infinite left hand side a_1 x_1 + ... + a_n x_n <= rhs */
16995 lhsstrptr = NULL;
16996 varstrptr = (char *)str;
16997 rhsstrptr = firstop + 2;
16998 }
16999 break;
17000 case '>':
17001 assert(firstop[1] == '=');
17002 assert(secondop == NULL);
17003 /* we have a_1 x_1 + ... + a_n x_n >= lhs */
17004 lhsstrptr = firstop + 2;
17005 break;
17006 case '=':
17007 assert(firstop[1] == '=');
17008 assert(secondop == NULL);
17009 /* we have a_1 x_1 + ... + a_n x_n == lhs (rhs) */
17010 rhsstrptr = firstop + 2;
17011 lhsstrptr = firstop + 2;
17012 break;
17013 case '[':
17014 assert(strncmp(firstop, "[free]", 6) == 0);
17015 assert(secondop == NULL);
17016 /* nothing to assign in case of a free a_1 x_1 + ... + a_n x_n [free] */
17017 break;
17018 default:
17019 /* it should not be possible that a different character appears in that position */
17020 SCIPerrorMessage("Parsing has wrong operator character '%c', should be one of <=>[", *firstop);
17021 return SCIP_READERROR;
17022 }
17023
17024 /* parse left hand side, if necessary */
17025 if( lhsstrptr != NULL )
17026 {
17027 if( ! SCIPparseReal(scip, lhsstrptr, &lhs, &endptr) )
17028 {
17029 SCIPerrorMessage("error parsing left hand side number from <%s>\n", lhsstrptr);
17030 return SCIP_OKAY;
17031 }
17032
17033 /* in case of an equation, assign the left also to the right hand side */
17034 if( rhsstrptr == lhsstrptr )
17035 rhs = lhs;
17036 }
17037
17038 /* parse right hand side, if different from left hand side */
17039 if( rhsstrptr != NULL && rhsstrptr != lhsstrptr )
17040 {
17041 if( ! SCIPparseReal(scip, rhsstrptr, &rhs, &endptr) )
17042 {
17043 SCIPerrorMessage("error parsing right hand side number from <%s>\n", lhsstrptr);
17044 return SCIP_OKAY;
17045 }
17046 }
17047
17048 /* initialize buffers for storing the variables and coefficients */
17049 SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) );
17050 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
17051
17052 assert(varstrptr != NULL);
17053
17054 /* parse linear sum to get variables and coefficients */
17055 SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17056
17057 if( *success && requsize > coefssize )
17058 {
17059 /* realloc buffers and try again */
17060 coefssize = requsize;
17061 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, coefssize) );
17062 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
17063
17064 SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17065 assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
17066 }
17067
17068 if( !*success )
17069 {
17070 SCIPerrorMessage("no luck in parsing linear sum '%s'\n", varstrptr);
17071 }
17072 else
17073 {
17074 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
17075 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17076 }
17077
17078 SCIPfreeBufferArray(scip, &coefs);
17080
17081 return SCIP_OKAY;
17082}
17083
17084
17085/** constraint method of constraint handler which returns the variables (if possible) */
17086static
17087SCIP_DECL_CONSGETVARS(consGetVarsLinear)
17088{ /*lint --e{715}*/
17089 SCIP_CONSDATA* consdata;
17090
17091 consdata = SCIPconsGetData(cons);
17092 assert(consdata != NULL);
17093
17094 if( varssize < consdata->nvars )
17095 (*success) = FALSE;
17096 else
17097 {
17098 assert(vars != NULL);
17099
17100 BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
17101 (*success) = TRUE;
17102 }
17103
17104 return SCIP_OKAY;
17105}
17106
17107/**! [Callback for the number of variables]*/
17108/** constraint method of constraint handler which returns the number of variables (if possible) */
17109static
17110SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
17111{ /*lint --e{715}*/
17112 SCIP_CONSDATA* consdata;
17113
17114 consdata = SCIPconsGetData(cons);
17115 assert(consdata != NULL);
17116
17117 (*nvars) = consdata->nvars;
17118 (*success) = TRUE;
17119
17120 return SCIP_OKAY;
17121}
17122/**! [Callback for the number of variables]*/
17123
17124/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
17125static
17126SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphLinear)
17127{ /*lint --e{715}*/
17128 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
17129
17130 return SCIP_OKAY;
17131}
17132
17133/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
17134static
17135SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphLinear)
17136{ /*lint --e{715}*/
17137 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
17138
17139 return SCIP_OKAY;
17140}
17141
17142/*
17143 * Callback methods of event handler
17144 */
17145
17146/** execution method of event handler */
17147static
17148SCIP_DECL_EVENTEXEC(eventExecLinear)
17149{ /*lint --e{715}*/
17150 SCIP_CONS* cons;
17151 SCIP_CONSDATA* consdata;
17152 SCIP_VAR* var;
17153 SCIP_EVENTTYPE eventtype;
17154
17155 assert(scip != NULL);
17156 assert(eventhdlr != NULL);
17157 assert(eventdata != NULL);
17158 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
17159 assert(event != NULL);
17160
17161 cons = eventdata->cons;
17162 assert(cons != NULL);
17163 consdata = SCIPconsGetData(cons);
17164 assert(consdata != NULL);
17165
17166 /* we can skip events droped for deleted constraints */
17167 if( SCIPconsIsDeleted(cons) )
17168 return SCIP_OKAY;
17169
17170 eventtype = SCIPeventGetType(event);
17171 var = SCIPeventGetVar(event);
17172
17174 {
17175 SCIP_Real oldbound;
17176 SCIP_Real newbound;
17177 SCIP_Real val;
17178 int varpos;
17179
17180 varpos = eventdata->varpos;
17181 assert(0 <= varpos && varpos < consdata->nvars);
17182 oldbound = SCIPeventGetOldbound(event);
17183 newbound = SCIPeventGetNewbound(event);
17184 assert(var != NULL);
17185 assert(consdata->vars[varpos] == var);
17186 val = consdata->vals[varpos];
17187
17188 /* we only need to update the activities if the constraint is active,
17189 * otherwise we mark them to be invalid
17190 */
17191 if( SCIPconsIsActive(cons) )
17192 {
17193 /* update the activity values */
17195 consdataUpdateActivitiesLb(scip, consdata, var, oldbound, newbound, val, TRUE);
17196 else
17197 {
17199 consdataUpdateActivitiesUb(scip, consdata, var, oldbound, newbound, val, TRUE);
17200 }
17201 }
17202 else
17204
17205 consdata->presolved = FALSE;
17206
17207 /* in probing do not reset disabled ranged row propagation */
17208 if( !SCIPinProbing(scip) )
17209 consdata->rangedrowpropagated = 0;
17210
17211 /* bound change can turn the constraint infeasible or redundant only if it was a tightening */
17213 {
17215
17216 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17217 if( consdata->maxactdeltavar == var )
17218 {
17219 consdata->maxactdelta = SCIP_INVALID;
17220 consdata->maxactdeltavar = NULL;
17221 }
17222
17223 /* check whether bound tightening might now be successful */
17224 if( consdata->boundstightened > 0)
17225 {
17226 switch( eventtype )
17227 {
17229 if( (val > 0.0 ? !SCIPisInfinity(scip, consdata->rhs) : !SCIPisInfinity(scip, -consdata->lhs)) )
17230 consdata->boundstightened = 0;
17231 break;
17233 if( (val > 0.0 ? !SCIPisInfinity(scip, -consdata->lhs) : !SCIPisInfinity(scip, consdata->rhs)) )
17234 consdata->boundstightened = 0;
17235 break;
17236 default:
17237 SCIPerrorMessage("invalid event type %" SCIP_EVENTTYPE_FORMAT "\n", eventtype);
17238 return SCIP_INVALIDDATA;
17239 }
17240 }
17241 }
17242 /* update maximal activity delta if a bound was relaxed */
17243 else if( !SCIPisInfinity(scip, consdata->maxactdelta) )
17244 {
17245 SCIP_Real lb;
17246 SCIP_Real ub;
17247 SCIP_Real domain;
17248 SCIP_Real delta;
17249
17251
17252 lb = SCIPvarGetLbLocal(var);
17253 ub = SCIPvarGetUbLocal(var);
17254
17255 domain = ub - lb;
17256 delta = REALABS(val) * domain;
17257
17258 if( delta > consdata->maxactdelta )
17259 {
17260 consdata->maxactdelta = delta;
17261 consdata->maxactdeltavar = var;
17262 }
17263 }
17264 }
17265 else if( (eventtype & SCIP_EVENTTYPE_VARFIXED) != SCIP_EVENTTYPE_DISABLED )
17266 {
17267 /* we want to remove the fixed variable */
17268 consdata->presolved = FALSE;
17269 consdata->removedfixings = FALSE;
17270 consdata->rangedrowpropagated = 0;
17271
17272 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17273 if( consdata->maxactdeltavar == var )
17274 {
17275 consdata->maxactdelta = SCIP_INVALID;
17276 consdata->maxactdeltavar = NULL;
17277 }
17278 }
17279 else if( (eventtype & SCIP_EVENTTYPE_VARUNLOCKED) != SCIP_EVENTTYPE_DISABLED )
17280 {
17281 /* there is only one lock left: we may multi-aggregate the variable as slack of an equation */
17284 consdata->presolved = FALSE;
17285 }
17286 else if( (eventtype & SCIP_EVENTTYPE_GBDCHANGED) != SCIP_EVENTTYPE_DISABLED )
17287 {
17288 SCIP_Real oldbound;
17289 SCIP_Real newbound;
17290 SCIP_Real val;
17291 int varpos;
17292
17293 varpos = eventdata->varpos;
17294 assert(0 <= varpos && varpos < consdata->nvars);
17295 oldbound = SCIPeventGetOldbound(event);
17296 newbound = SCIPeventGetNewbound(event);
17297 assert(var != NULL);
17298 assert(consdata->vars[varpos] == var);
17299 val = consdata->vals[varpos];
17300
17301 consdata->rangedrowpropagated = 0;
17302
17303 /* update the activity values */
17305 consdataUpdateActivitiesGlbLb(scip, consdata, oldbound, newbound, val, TRUE);
17306 else
17307 {
17309 consdataUpdateActivitiesGlbUb(scip, consdata, oldbound, newbound, val, TRUE);
17310 }
17311
17312 /* if the variable is binary but not fixed it had to become binary due to this global change */
17314 {
17316 consdata->indexsorted = FALSE;
17317 else
17318 consdata->coefsorted = FALSE;
17319 }
17320 }
17321 else if( (eventtype & SCIP_EVENTTYPE_TYPECHANGED) != SCIP_EVENTTYPE_DISABLED )
17322 {
17324
17325 /* for presolving it only matters if a variable becomes integral */
17326 consdata->presolved = (consdata->presolved && (SCIPeventGetOldtype(event) != SCIP_VARTYPE_CONTINUOUS || SCIPvarIsImpliedIntegral(var)));
17327
17328 /* the ordering is preserved if the variable remains binary */
17329 consdata->indexsorted = (consdata->indexsorted && SCIPvarIsBinary(var) && (SCIPeventGetOldtype(event) != SCIP_VARTYPE_CONTINUOUS || SCIPvarIsImpliedIntegral(var)));
17330 }
17332 {
17334
17335 /* for presolving it only matters if a variable becomes integral */
17336 consdata->presolved = (consdata->presolved && (SCIPeventGetOldImpltype(event) != SCIP_IMPLINTTYPE_NONE || SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS));
17337
17338 /* the ordering is preserved if the variable remains binary */
17339 consdata->indexsorted = (consdata->indexsorted && SCIPvarIsBinary(var) && (SCIPeventGetOldImpltype(event) != SCIP_IMPLINTTYPE_NONE || SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS));
17340 }
17341 else
17342 {
17344 consdata->varsdeleted = TRUE;
17345 }
17346
17347 return SCIP_OKAY;
17348}
17349
17350
17351/*
17352 * Callback methods of conflict handler
17353 */
17354
17355/** conflict processing method of conflict handler (called when conflict was found) */
17356static
17357SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
17358{ /*lint --e{715}*/
17359 SCIP_VAR** vars;
17360 SCIP_Real* vals;
17361 SCIP_Real lhs;
17362 int i;
17363
17364 assert(scip != NULL);
17365 assert(conflicthdlr != NULL);
17366 assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
17367 assert(bdchginfos != NULL || nbdchginfos == 0);
17368 assert(result != NULL);
17369
17370 /* don't process already resolved conflicts */
17371 if( resolved )
17372 {
17374 return SCIP_OKAY;
17375 }
17376
17378
17379 /* create array of variables and coefficients: sum_{i \in P} x_i - sum_{i \in N} x_i >= 1 - |N| */
17380 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
17381 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nbdchginfos) );
17382 lhs = 1.0;
17383 for( i = 0; i < nbdchginfos; ++i )
17384 {
17385 assert(bdchginfos != NULL);
17386
17387 vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
17388
17389 /* we can only treat binary variables */
17390 /**@todo extend linear conflict constraints to some non-binary cases */
17391 if( !SCIPvarIsBinary(vars[i]) )
17392 break;
17393
17394 /* check whether the variable is fixed to zero (P) or one (N) in the conflict set */
17395 if( SCIPbdchginfoGetNewbound(bdchginfos[i]) < 0.5 )
17396 vals[i] = 1.0;
17397 else
17398 {
17399 vals[i] = -1.0;
17400 lhs -= 1.0;
17401 }
17402 }
17403
17404 if( i == nbdchginfos )
17405 {
17406 SCIP_CONS* cons;
17407 SCIP_CONS* upgdcons;
17408 char consname[SCIP_MAXSTRLEN];
17409
17410 /* create a constraint out of the conflict set */
17412 SCIP_CALL( SCIPcreateConsLinear(scip, &cons, consname, nbdchginfos, vars, vals, lhs, SCIPinfinity(scip),
17413 FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
17414
17415 /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
17416 SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
17417 if( upgdcons != NULL )
17418 {
17419 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
17420 cons = upgdcons;
17421 }
17422
17423 /* add conflict to SCIP */
17424 SCIP_CALL( SCIPaddConflict(scip, node, &cons, validnode, conftype, cutoffinvolved) );
17425
17427 }
17428
17429 /* free temporary memory */
17430 SCIPfreeBufferArray(scip, &vals);
17432
17433 return SCIP_OKAY;
17434}
17435
17436
17437/*
17438 * Nonlinear constraint upgrading
17439 */
17440
17441/** tries to upgrade a nonlinear constraint into a linear constraint */
17442static
17443SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
17444{
17445 SCIP_CONSDATA* consdata;
17446 SCIP_EXPR* expr;
17447 SCIP_Real lhs;
17448 SCIP_Real rhs;
17449 int i;
17450
17451 assert(nupgdconss != NULL);
17452 assert(upgdconss != NULL);
17453 assert(upgdconsssize > 0);
17454
17455 expr = SCIPgetExprNonlinear(cons);
17456 assert(expr != NULL);
17457
17458 /* not a linear constraint if the expression is not a sum
17459 * (unless the expression is a variable or a constant or a constant*variable, but these are simplified away in cons_nonlinear)
17460 */
17461 if( !SCIPisExprSum(scip, expr) )
17462 return SCIP_OKAY;
17463
17464 /* if at least one child is not a variable, then not a linear constraint */
17465 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17466 if( !SCIPisExprVar(scip, SCIPexprGetChildren(expr)[i]) )
17467 return SCIP_OKAY;
17468
17469 /* consider constant part of the sum expression */
17472
17473 SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
17474 0, NULL, NULL, lhs, rhs,
17478 SCIPconsIsStickingAtNode(cons)) );
17479 assert(upgdconss[0] != NULL);
17480
17481 consdata = SCIPconsGetData(upgdconss[0]);
17482
17483 /* add linear terms */
17485 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17486 {
17488 }
17489
17490 /* check violation of this linear constraint with absolute tolerances, to be consistent with the original nonlinear constraint */
17491 consdata->checkabsolute = TRUE;
17492
17493 *nupgdconss = 1;
17494
17495 SCIPdebugMsg(scip, "created linear constraint:\n");
17496 SCIPdebugPrintCons(scip, upgdconss[0], NULL);
17497
17498 return SCIP_OKAY;
17499} /*lint !e715*/
17500
17501/*
17502 * constraint specific interface methods
17503 */
17504
17505/** creates the handler for linear constraints and includes it in SCIP */
17507 SCIP* scip /**< SCIP data structure */
17508 )
17509{
17510 SCIP_CONSHDLRDATA* conshdlrdata;
17511 SCIP_CONSHDLR* conshdlr;
17512 SCIP_EVENTHDLR* eventhdlr;
17513 SCIP_CONFLICTHDLR* conflicthdlr;
17514
17515 assert(scip != NULL);
17516
17517 /* create event handler for bound change events */
17519 eventExecLinear, NULL) );
17520
17521 /* create conflict handler for linear constraints */
17523 conflictExecLinear, NULL) );
17524
17525 /* create constraint handler data */
17526 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
17527
17528 /* include constraint handler */
17531 consEnfolpLinear, consEnfopsLinear, consCheckLinear, consLockLinear,
17532 conshdlrdata) );
17533
17534 assert(conshdlr != NULL);
17535
17536 /* set non-fundamental callbacks via specific setter functions */
17537 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLinear, consCopyLinear) );
17538 SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveLinear) );
17539 SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveLinear) );
17540 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLinear) );
17541 SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsLinear) );
17542 SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitLinear) );
17543 SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLinear) );
17544 SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolLinear) );
17545 SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLinear) );
17546 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLinear) );
17547 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLinear) );
17548 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLinear) );
17549 SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitLinear) );
17550 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLinear) );
17551 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLinear) );
17553 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLinear) );
17556 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLinear) );
17557 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLinear, consSepasolLinear, CONSHDLR_SEPAFREQ,
17559 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLinear) );
17560 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLinear) );
17561 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphLinear) );
17562 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphLinear) );
17563
17564 if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
17565 {
17566 /* include the linear constraint upgrade in the nonlinear constraint handler */
17568 }
17569
17570 /* add linear constraint handler parameters */
17572 "constraints/" CONSHDLR_NAME "/tightenboundsfreq",
17573 "multiplier on propagation frequency, how often the bounds are tightened (-1: never, 0: only at root)",
17574 &conshdlrdata->tightenboundsfreq, TRUE, DEFAULT_TIGHTENBOUNDSFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17576 "constraints/" CONSHDLR_NAME "/maxrounds",
17577 "maximal number of separation rounds per node (-1: unlimited)",
17578 &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
17580 "constraints/" CONSHDLR_NAME "/maxroundsroot",
17581 "maximal number of separation rounds per node in the root node (-1: unlimited)",
17582 &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
17584 "constraints/" CONSHDLR_NAME "/maxsepacuts",
17585 "maximal number of cuts separated per separation round",
17586 &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
17588 "constraints/" CONSHDLR_NAME "/maxsepacutsroot",
17589 "maximal number of cuts separated per separation round in the root node",
17590 &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
17592 "constraints/" CONSHDLR_NAME "/presolpairwise",
17593 "should pairwise constraint comparison be performed in presolving?",
17594 &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
17596 "constraints/" CONSHDLR_NAME "/presolusehashing",
17597 "should hash table be used for detecting redundant constraints in advance",
17598 &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
17600 "constraints/" CONSHDLR_NAME "/nmincomparisons",
17601 "number for minimal pairwise presolve comparisons",
17602 &conshdlrdata->nmincomparisons, TRUE, DEFAULT_NMINCOMPARISONS, 1, INT_MAX, NULL, NULL) );
17604 "constraints/" CONSHDLR_NAME "/mingainpernmincomparisons",
17605 "minimal gain per minimal pairwise presolve comparisons to repeat pairwise comparison round",
17606 &conshdlrdata->mingainpernmincomp, TRUE, DEFAULT_MINGAINPERNMINCOMP, 0.0, 1.0, NULL, NULL) );
17608 "constraints/" CONSHDLR_NAME "/maxaggrnormscale",
17609 "maximal allowed relative gain in maximum norm for constraint aggregation (0.0: disable constraint aggregation)",
17610 &conshdlrdata->maxaggrnormscale, TRUE, DEFAULT_MAXAGGRNORMSCALE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17612 "constraints/" CONSHDLR_NAME "/maxeasyactivitydelta",
17613 "maximum activity delta to run easy propagation on linear constraint (faster, but numerically less stable)",
17614 &conshdlrdata->maxeasyactivitydelta, TRUE, DEFAULT_MAXEASYACTIVITYDELTA, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17616 "constraints/" CONSHDLR_NAME "/maxcardbounddist",
17617 "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for separating knapsack cardinality cuts",
17618 &conshdlrdata->maxcardbounddist, TRUE, DEFAULT_MAXCARDBOUNDDIST, 0.0, 1.0, NULL, NULL) );
17620 "constraints/" CONSHDLR_NAME "/separateall",
17621 "should all constraints be subject to cardinality cut generation instead of only the ones with non-zero dual value?",
17622 &conshdlrdata->separateall, FALSE, DEFAULT_SEPARATEALL, NULL, NULL) );
17624 "constraints/" CONSHDLR_NAME "/aggregatevariables",
17625 "should presolving search for aggregations in equations",
17626 &conshdlrdata->aggregatevariables, TRUE, DEFAULT_AGGREGATEVARIABLES, NULL, NULL) );
17628 "constraints/" CONSHDLR_NAME "/simplifyinequalities",
17629 "should presolving try to simplify inequalities",
17630 &conshdlrdata->simplifyinequalities, TRUE, DEFAULT_SIMPLIFYINEQUALITIES, NULL, NULL) );
17632 "constraints/" CONSHDLR_NAME "/dualpresolving",
17633 "should dual presolving steps be performed?",
17634 &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
17636 "constraints/" CONSHDLR_NAME "/singletonstuffing",
17637 "should stuffing of singleton continuous variables be performed?",
17638 &conshdlrdata->singletonstuffing, TRUE, DEFAULT_SINGLETONSTUFFING, NULL, NULL) );
17640 "constraints/" CONSHDLR_NAME "/singlevarstuffing",
17641 "should single variable stuffing be performed, which tries to fulfill constraints using the cheapest variable?",
17642 &conshdlrdata->singlevarstuffing, TRUE, DEFAULT_SINGLEVARSTUFFING, NULL, NULL) );
17644 "constraints/" CONSHDLR_NAME "/sortvars", "apply binaries sorting in decr. order of coeff abs value?",
17645 &conshdlrdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL) );
17647 "constraints/" CONSHDLR_NAME "/checkrelmaxabs",
17648 "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)?",
17649 &conshdlrdata->checkrelmaxabs, TRUE, DEFAULT_CHECKRELMAXABS, NULL, NULL) );
17651 "constraints/" CONSHDLR_NAME "/detectcutoffbound",
17652 "should presolving try to detect constraints parallel to the objective function defining an upper bound and prevent these constraints from entering the LP?",
17653 &conshdlrdata->detectcutoffbound, TRUE, DEFAULT_DETECTCUTOFFBOUND, NULL, NULL) );
17655 "constraints/" CONSHDLR_NAME "/detectlowerbound",
17656 "should presolving try to detect constraints parallel to the objective function defining a lower bound and prevent these constraints from entering the LP?",
17657 &conshdlrdata->detectlowerbound, TRUE, DEFAULT_DETECTLOWERBOUND, NULL, NULL) );
17659 "constraints/" CONSHDLR_NAME "/detectpartialobjective",
17660 "should presolving try to detect subsets of constraints parallel to the objective function?",
17661 &conshdlrdata->detectpartialobjective, TRUE, DEFAULT_DETECTPARTIALOBJECTIVE, NULL, NULL) );
17663 "constraints/" CONSHDLR_NAME "/rangedrowpropagation",
17664 "should presolving and propagation try to improve bounds, detect infeasibility, and extract sub-constraints from ranged rows and equations?",
17665 &conshdlrdata->rangedrowpropagation, TRUE, DEFAULT_RANGEDROWPROPAGATION, NULL, NULL) );
17667 "constraints/" CONSHDLR_NAME "/rangedrowartcons",
17668 "should presolving and propagation extract sub-constraints from ranged rows and equations?",
17669 &conshdlrdata->rangedrowartcons, TRUE, DEFAULT_RANGEDROWARTCONS, NULL, NULL) );
17671 "constraints/" CONSHDLR_NAME "/rangedrowmaxdepth",
17672 "maximum depth to apply ranged row propagation",
17673 &conshdlrdata->rangedrowmaxdepth, TRUE, DEFAULT_RANGEDROWMAXDEPTH, 0, INT_MAX, NULL, NULL) );
17675 "constraints/" CONSHDLR_NAME "/rangedrowfreq",
17676 "frequency for applying ranged row propagation",
17677 &conshdlrdata->rangedrowfreq, TRUE, DEFAULT_RANGEDROWFREQ, 1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17679 "constraints/" CONSHDLR_NAME "/multaggrremove",
17680 "should multi-aggregations only be performed if the constraint can be removed afterwards?",
17681 &conshdlrdata->multaggrremove, TRUE, DEFAULT_MULTAGGRREMOVE, NULL, NULL) );
17683 "constraints/" CONSHDLR_NAME "/maxmultaggrquot",
17684 "maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation",
17685 &conshdlrdata->maxmultaggrquot, TRUE, DEFAULT_MAXMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17687 "constraints/" CONSHDLR_NAME "/maxdualmultaggrquot",
17688 "maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation",
17689 &conshdlrdata->maxdualmultaggrquot, TRUE, DEFAULT_MAXDUALMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17691 "constraints/" CONSHDLR_NAME "/extractcliques",
17692 "should Cliques be extracted?",
17693 &conshdlrdata->extractcliques, TRUE, DEFAULT_EXTRACTCLIQUES, NULL, NULL) );
17694
17695 return SCIP_OKAY;
17696}
17697
17698/** includes a linear constraint update method into the linear constraint handler */
17700 SCIP* scip, /**< SCIP data structure */
17701 SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
17702 int priority, /**< priority of upgrading method */
17703 const char* conshdlrname /**< name of the constraint handler */
17704 )
17705{
17706 SCIP_CONSHDLR* conshdlr;
17707 SCIP_CONSHDLRDATA* conshdlrdata;
17708 SCIP_LINCONSUPGRADE* linconsupgrade;
17710 char paramdesc[SCIP_MAXSTRLEN];
17711
17712 assert(scip != NULL);
17713 assert(linconsupgd != NULL);
17714 assert(conshdlrname != NULL );
17715
17716 /* find the linear constraint handler */
17717 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17718 if( conshdlr == NULL )
17719 {
17720 SCIPerrorMessage("linear constraint handler not found\n");
17721 return SCIP_PLUGINNOTFOUND;
17722 }
17723
17724 conshdlrdata = SCIPconshdlrGetData(conshdlr);
17725 assert(conshdlrdata != NULL);
17726
17727 /* check if linear constraint update method already exists in constraint handler data */
17728 if( !conshdlrdataHasUpgrade(scip, conshdlrdata, linconsupgd, conshdlrname) )
17729 {
17730 /* create a linear constraint upgrade data object */
17731 SCIP_CALL( linconsupgradeCreate(scip, &linconsupgrade, linconsupgd, priority) );
17732
17733 /* insert linear constraint update method into constraint handler data */
17734 SCIP_CALL( conshdlrdataIncludeUpgrade(scip, conshdlrdata, linconsupgrade) );
17735
17736 /* adds parameter to turn on and off the upgrading step */
17737 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/linear/upgrade/%s", conshdlrname);
17738 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "enable linear upgrading for constraint handler <%s>", conshdlrname);
17740 paramname, paramdesc,
17741 &linconsupgrade->active, FALSE, TRUE, NULL, NULL) );
17742 }
17743
17744 return SCIP_OKAY;
17745}
17746
17747/** creates and captures a linear constraint
17748 *
17749 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17750 */
17752 SCIP* scip, /**< SCIP data structure */
17753 SCIP_CONS** cons, /**< pointer to hold the created constraint */
17754 const char* name, /**< name of constraint */
17755 int nvars, /**< number of nonzeros in the constraint */
17756 SCIP_VAR** vars, /**< array with variables of constraint entries */
17757 SCIP_Real* vals, /**< array with coefficients of constraint entries */
17758 SCIP_Real lhs, /**< left hand side of constraint */
17759 SCIP_Real rhs, /**< right hand side of constraint */
17760 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
17761 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
17762 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
17763 * Usually set to TRUE. */
17764 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
17765 * TRUE for model constraints, FALSE for additional, redundant constraints. */
17766 SCIP_Bool check, /**< should the constraint be checked for feasibility?
17767 * TRUE for model constraints, FALSE for additional, redundant constraints. */
17768 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
17769 * Usually set to TRUE. */
17770 SCIP_Bool local, /**< is constraint only valid locally?
17771 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
17772 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
17773 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
17774 * adds coefficients to this constraint. */
17775 SCIP_Bool dynamic, /**< is constraint subject to aging?
17776 * Usually set to FALSE. Set to TRUE for own cuts which
17777 * are separated as constraints. */
17778 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
17779 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
17780 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
17781 * if it may be moved to a more global node?
17782 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
17783 )
17784{
17785 SCIP_CONSHDLR* conshdlr;
17786 SCIP_CONSDATA* consdata;
17787 int i;
17788
17789 assert(scip != NULL);
17790 assert(cons != NULL);
17791
17792 /* find the linear constraint handler */
17793 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17794 if( conshdlr == NULL )
17795 {
17796 SCIPerrorMessage("linear constraint handler not found\n");
17797 return SCIP_PLUGINNOTFOUND;
17798 }
17799
17800 /* terminate if a coefficient is infinite */
17801 assert(SCIPisFinite(lhs));
17802 assert(SCIPisFinite(rhs));
17803 for( i = 0; i < nvars; ++i )
17804 {
17805 assert(SCIPisFinite(vals[i]));
17806 if( SCIPisInfinity(scip, REALABS(vals[i])) )
17807 {
17808 SCIPerrorMessage("coefficient of variable <%s> in constraint <%s> is infinite,"
17809 " consider adjusting the infinity threshold\n", SCIPvarGetName(vars[i]), name);
17810 SCIPABORT();
17811 return SCIP_INVALIDDATA;
17812 }
17813 }
17814
17815 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
17816 * constraint after presolving we have to ensure that it holds active variables
17817 */
17819 {
17820 SCIP_VAR** consvars;
17821 SCIP_Real* consvals;
17822 SCIP_Real constant = 0.0;
17823 int nconsvars;
17824 int requiredsize;
17825
17826 nconsvars = nvars;
17827 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, vars, nconsvars) );
17828 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) );
17829
17830 /* get active variables for new constraint */
17831 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize) );
17832
17833 /* if space was not enough we need to resize the buffers */
17834 if( requiredsize > nconsvars )
17835 {
17836 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
17837 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
17838
17839 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize) );
17840 }
17841 assert(requiredsize == nconsvars);
17842
17843 /* adjust sides and check that we do not subtract infinity values */
17844 if( SCIPisInfinity(scip, REALABS(constant)) )
17845 {
17846 SCIPfreeBufferArray(scip, &consvals);
17847 SCIPfreeBufferArray(scip, &consvars);
17848 SCIPerrorMessage("while creating constraint <%s> inactive variables lead to an infinite constant\n", name);
17849 SCIPABORT();
17850 return SCIP_INVALIDDATA;
17851 }
17852 else
17853 {
17854 if( !SCIPisInfinity(scip, REALABS(lhs)) )
17855 lhs -= constant;
17856 if( !SCIPisInfinity(scip, REALABS(rhs)) )
17857 rhs -= constant;
17858
17859 if( SCIPisInfinity(scip, -lhs) )
17860 lhs = -SCIPinfinity(scip);
17861 else if( SCIPisInfinity(scip, lhs) )
17862 lhs = SCIPinfinity(scip);
17863
17864 if( SCIPisInfinity(scip, rhs) )
17865 rhs = SCIPinfinity(scip);
17866 else if( SCIPisInfinity(scip, -rhs) )
17867 rhs = -SCIPinfinity(scip);
17868 }
17869
17870 /* create constraint data */
17871 SCIP_CALL( consdataCreate(scip, &consdata, nconsvars, consvars, consvals, lhs, rhs) );
17872
17873 SCIPfreeBufferArray(scip, &consvals);
17874 SCIPfreeBufferArray(scip, &consvars);
17875 }
17876 else
17877 {
17878 /* create constraint data */
17879 SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, vals, lhs, rhs) );
17880 }
17881 assert(consdata != NULL);
17882
17883#ifndef NDEBUG
17884 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
17885 if( check || enforce )
17886 {
17887 int n;
17888 for(n = consdata->nvars - 1; n >= 0; --n )
17889 assert(!SCIPvarIsRelaxationOnly(consdata->vars[n]));
17890 }
17891#endif
17892
17893 /* create constraint */
17894 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
17895 local, modifiable, dynamic, removable, stickingatnode) );
17896
17897 return SCIP_OKAY;
17898}
17899
17900/** creates and captures a linear constraint
17901 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
17902 * method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
17903 *
17904 * @see SCIPcreateConsLinear() for information about the basic constraint flag configuration
17905 *
17906 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17907 */
17909 SCIP* scip, /**< SCIP data structure */
17910 SCIP_CONS** cons, /**< pointer to hold the created constraint */
17911 const char* name, /**< name of constraint */
17912 int nvars, /**< number of nonzeros in the constraint */
17913 SCIP_VAR** vars, /**< array with variables of constraint entries */
17914 SCIP_Real* vals, /**< array with coefficients of constraint entries */
17915 SCIP_Real lhs, /**< left hand side of constraint */
17916 SCIP_Real rhs /**< right hand side of constraint */
17917 )
17918{
17919 assert(scip != NULL);
17920
17921 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, vals, lhs, rhs,
17923
17924 return SCIP_OKAY;
17925}
17926
17927/** creates by copying and captures a linear constraint */
17929 SCIP* scip, /**< target SCIP data structure */
17930 SCIP_CONS** cons, /**< pointer to store the created target constraint */
17931 SCIP* sourcescip, /**< source SCIP data structure */
17932 const char* name, /**< name of constraint */
17933 int nvars, /**< number of variables in source variable array */
17934 SCIP_VAR** sourcevars, /**< source variables of the linear constraints */
17935 SCIP_Real* sourcecoefs, /**< coefficient array of the linear constraint, or NULL if all coefficients are one */
17936 SCIP_Real lhs, /**< left hand side of the linear constraint */
17937 SCIP_Real rhs, /**< right hand side of the linear constraint */
17938 SCIP_HASHMAP* varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
17939 * variables of the target SCIP */
17940 SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
17941 * target constraints */
17942 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
17943 SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
17944 SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
17945 SCIP_Bool check, /**< should the constraint be checked for feasibility? */
17946 SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
17947 SCIP_Bool local, /**< is constraint only valid locally? */
17948 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
17949 SCIP_Bool dynamic, /**< is constraint subject to aging? */
17950 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
17951 SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even
17952 * if it may be moved to a more global node? */
17953 SCIP_Bool global, /**< create a global or a local copy? */
17954 SCIP_Bool* valid /**< pointer to store if the copying was valid */
17955 )
17956{
17957 SCIP_VAR** vars;
17958 SCIP_Real* coefs;
17959
17960 SCIP_Real constant;
17961 int requiredsize;
17962 int v;
17963 SCIP_Bool success;
17964
17965 if( SCIPisGT(scip, lhs, rhs) )
17966 {
17967 *valid = FALSE;
17968 return SCIP_OKAY;
17969 }
17970
17971 (*valid) = TRUE;
17972
17973 if( nvars == 0 )
17974 {
17975 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, 0, NULL, NULL, lhs, rhs,
17976 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17977 return SCIP_OKAY;
17978 }
17979
17980 /* duplicate variable array */
17982
17983 /* duplicate coefficient array */
17984 if( sourcecoefs != NULL )
17985 {
17986 SCIP_CALL( SCIPduplicateBufferArray(scip, &coefs, sourcecoefs, nvars) );
17987 }
17988 else
17989 {
17991 for( v = 0; v < nvars; ++v )
17992 coefs[v] = 1.0;
17993 }
17994
17995 constant = 0.0;
17996
17997 /* transform source variable to active variables of the source SCIP since only these can be mapped to variables of
17998 * the target SCIP
17999 */
18000 if( !SCIPvarIsOriginal(vars[0]) )
18001 {
18002 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize) );
18003
18004 if( requiredsize > nvars )
18005 {
18006 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
18007 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requiredsize) );
18008
18009 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize) );
18010 }
18011 assert(requiredsize == nvars);
18012 }
18013 else
18014 {
18015 for( v = 0; v < nvars; ++v )
18016 {
18018 SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &coefs[v], &constant) );
18019 assert(vars[v] != NULL);
18020 }
18021 }
18022
18023 success = TRUE;
18024 /* map variables of the source constraint to variables of the target SCIP */
18025 for( v = 0; v < nvars && success; ++v )
18026 {
18027 SCIP_VAR* var;
18028 var = vars[v];
18029
18030 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18031 assert(!SCIPvarIsRelaxationOnly(var) || (!check && !enforce));
18032
18033 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &vars[v], varmap, consmap, global, &success) );
18034 assert(!(success) || vars[v] != NULL);
18035 }
18036
18037 /* only create the target constraint, if all variables could be copied */
18038 if( success )
18039 {
18040 if( !SCIPisInfinity(scip, -lhs) )
18041 lhs -= constant;
18042
18043 if( !SCIPisInfinity(scip, rhs) )
18044 rhs -= constant;
18045
18046 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
18047 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18048 }
18049 else
18050 *valid = FALSE;
18051
18052 /* free buffer array */
18053 SCIPfreeBufferArray(scip, &coefs);
18055
18056 return SCIP_OKAY;
18057}
18058
18059/** adds coefficient to linear constraint (if it is not zero) */
18061 SCIP* scip, /**< SCIP data structure */
18062 SCIP_CONS* cons, /**< constraint data */
18063 SCIP_VAR* var, /**< variable of constraint entry */
18064 SCIP_Real val /**< coefficient of constraint entry */
18065 )
18066{
18067 assert(scip != NULL);
18068 assert(cons != NULL);
18069 assert(var != NULL);
18070
18071 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18072 {
18073 SCIPerrorMessage("constraint is not linear\n");
18074 return SCIP_INVALIDDATA;
18075 }
18076
18077 /* terminate if coefficient is infinite */
18078 assert(SCIPisFinite(val));
18079 if( SCIPisInfinity(scip, REALABS(val)) )
18080 {
18081 SCIPerrorMessage("coefficient of variable <%s> in constraint <%s> is infinite,"
18082 " consider adjusting the infinity threshold\n", SCIPvarGetName(var), SCIPconsGetName(cons));
18083 SCIPABORT();
18084 return SCIP_INVALIDDATA;
18085 }
18086
18087 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
18088 * constraint after presolving we have to ensure that it holds active variables
18089 */
18091 {
18092 SCIP_CONSDATA* consdata;
18093 SCIP_VAR** consvars;
18094 SCIP_Real* consvals;
18095 SCIP_Real constant = 0.0;
18096 SCIP_Real rhs;
18097 SCIP_Real lhs;
18098 int nconsvars;
18099 int requiredsize;
18100 int v;
18101
18102 nconsvars = 1;
18103 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
18104 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
18105 consvars[0] = var;
18106 consvals[0] = val;
18107
18108 /* get active variables for new constraint */
18109 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize) );
18110
18111 /* if space was not enough we need to resize the buffers */
18112 if( requiredsize > nconsvars )
18113 {
18114 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
18115 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
18116
18117 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize) );
18118 }
18119 assert(requiredsize == nconsvars);
18120
18121 consdata = SCIPconsGetData(cons);
18122 assert(consdata != NULL);
18123
18124 lhs = consdata->lhs;
18125 rhs = consdata->rhs;
18126
18127 /* adjust sides and check that we do not subtract infinity values */
18128 /* constant is infinite */
18129 if( SCIPisInfinity(scip, REALABS(constant)) )
18130 {
18131 if( constant < 0.0 )
18132 {
18133 if( SCIPisInfinity(scip, lhs) )
18134 {
18135 SCIPfreeBufferArray(scip, &consvals);
18136 SCIPfreeBufferArray(scip, &consvars);
18137
18138 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));
18139
18140 SCIPABORT();
18141 return SCIP_INVALIDDATA; /*lint !e527*/
18142 }
18143 if( SCIPisInfinity(scip, rhs) )
18144 {
18145 SCIPfreeBufferArray(scip, &consvals);
18146 SCIPfreeBufferArray(scip, &consvars);
18147
18148 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));
18149
18150 SCIPABORT();
18151 return SCIP_INVALIDDATA; /*lint !e527*/
18152 }
18153
18154 lhs = -SCIPinfinity(scip);
18155 rhs = -SCIPinfinity(scip);
18156 }
18157 else
18158 {
18159 if( SCIPisInfinity(scip, -lhs) )
18160 {
18161 SCIPfreeBufferArray(scip, &consvals);
18162 SCIPfreeBufferArray(scip, &consvars);
18163
18164 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));
18165
18166 SCIPABORT();
18167 return SCIP_INVALIDDATA; /*lint !e527*/
18168 }
18169 if( SCIPisInfinity(scip, -rhs) )
18170 {
18171 SCIPfreeBufferArray(scip, &consvals);
18172 SCIPfreeBufferArray(scip, &consvars);
18173
18174 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));
18175
18176 SCIPABORT();
18177 return SCIP_INVALIDDATA; /*lint !e527*/
18178 }
18179
18180 lhs = SCIPinfinity(scip);
18181 rhs = SCIPinfinity(scip);
18182 }
18183 }
18184 /* constant is not infinite */
18185 else
18186 {
18187 if( !SCIPisInfinity(scip, REALABS(lhs)) )
18188 lhs -= constant;
18189 if( !SCIPisInfinity(scip, REALABS(rhs)) )
18190 rhs -= constant;
18191
18192 if( SCIPisInfinity(scip, -lhs) )
18193 lhs = -SCIPinfinity(scip);
18194 else if( SCIPisInfinity(scip, lhs) )
18195 lhs = SCIPinfinity(scip);
18196
18197 if( SCIPisInfinity(scip, rhs) )
18198 rhs = SCIPinfinity(scip);
18199 else if( SCIPisInfinity(scip, -rhs) )
18200 rhs = -SCIPinfinity(scip);
18201 }
18202
18203 /* add all active variables to constraint */
18204 for( v = nconsvars - 1; v >= 0; --v )
18205 {
18206 if( !SCIPisZero(scip, consvals[v]) )
18207 {
18208 SCIP_CALL( addCoef(scip, cons, consvars[v], consvals[v]) );
18209 }
18210 }
18211
18212 /* update left and right hand sides */
18213 SCIP_CALL( chgLhs(scip, cons, lhs) );
18214 SCIP_CALL( chgRhs(scip, cons, rhs) );
18215
18216 SCIPfreeBufferArray(scip, &consvals);
18217 SCIPfreeBufferArray(scip, &consvars);
18218 }
18219 else if( !SCIPisZero(scip, val) )
18220 {
18221 SCIP_CALL( addCoef(scip, cons, var, val) );
18222 }
18223
18224 return SCIP_OKAY;
18225}
18226
18227/** changes coefficient of variable in linear constraint; deletes the variable if coefficient is zero; adds variable if
18228 * not yet contained in the constraint
18229 *
18230 * @note This method may only be called during problem creation stage for an original constraint and variable.
18231 *
18232 * @note This method requires linear time to search for occurences of the variable in the constraint data.
18233 */
18235 SCIP* scip, /**< SCIP data structure */
18236 SCIP_CONS* cons, /**< constraint data */
18237 SCIP_VAR* var, /**< variable of constraint entry */
18238 SCIP_Real val /**< new coefficient of constraint entry */
18239 )
18240{
18241 SCIP_CONSDATA* consdata;
18242 SCIP_VAR** vars;
18243 SCIP_Bool found;
18244 int i;
18245
18246 assert(scip != NULL);
18247 assert(cons != NULL);
18248 assert(var != NULL);
18249
18250 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18251 {
18252 SCIPerrorMessage("constraint is not linear\n");
18253 return SCIP_INVALIDDATA;
18254 }
18255
18257 {
18258 SCIPerrorMessage("method may only be called during problem creation stage for original constraints and variables\n");
18259 return SCIP_INVALIDDATA;
18260 }
18261
18262 consdata = SCIPconsGetData(cons);
18263 assert(consdata != NULL);
18264
18265 vars = consdata->vars;
18266 found = FALSE;
18267 i = 0;
18268 while( i < consdata->nvars )
18269 {
18270 if( vars[i] == var )
18271 {
18272 if( found || SCIPisZero(scip, val) )
18273 {
18274 SCIP_CALL( delCoefPos(scip, cons, i) );
18275
18276 /* decrease i by one since otherwise we would skip the coefficient which has been switched to position i */
18277 i--;
18278 }
18279 else
18280 {
18281 SCIP_CALL( chgCoefPos(scip, cons, i, val) );
18282 }
18283 found = TRUE;
18284 }
18285 i++;
18286 }
18287
18288 if( !found )
18289 {
18290 SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
18291 }
18292
18293 return SCIP_OKAY;
18294}
18295
18296/** deletes variable from linear constraint
18297 *
18298 * @note This method may only be called during problem creation stage for an original constraint and variable.
18299 *
18300 * @note This method requires linear time to search for occurences of the variable in the constraint data.
18301 */
18303 SCIP* scip, /**< SCIP data structure */
18304 SCIP_CONS* cons, /**< constraint data */
18305 SCIP_VAR* var /**< variable of constraint entry */
18306 )
18307{
18308 assert(scip != NULL);
18309 assert(cons != NULL);
18310 assert(var != NULL);
18311
18312 SCIP_CALL( SCIPchgCoefLinear(scip, cons, var, 0.0) );
18313
18314 return SCIP_OKAY;
18315}
18316
18317/** gets left hand side of linear constraint */
18319 SCIP* scip, /**< SCIP data structure */
18320 SCIP_CONS* cons /**< constraint data */
18321 )
18322{
18323 SCIP_CONSDATA* consdata;
18324
18325 assert(scip != NULL);
18326 assert(cons != NULL);
18327
18328 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18329 {
18330 SCIPerrorMessage("constraint is not linear\n");
18331 SCIPABORT();
18332 return SCIP_INVALID; /*lint !e527*/
18333 }
18334
18335 consdata = SCIPconsGetData(cons);
18336 assert(consdata != NULL);
18337
18338 return consdata->lhs;
18339}
18340
18341/** gets right hand side of linear constraint */
18343 SCIP* scip, /**< SCIP data structure */
18344 SCIP_CONS* cons /**< constraint data */
18345 )
18346{
18347 SCIP_CONSDATA* consdata;
18348
18349 assert(scip != NULL);
18350 assert(cons != NULL);
18351
18352 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18353 {
18354 SCIPerrorMessage("constraint is not linear\n");
18355 SCIPABORT();
18356 return SCIP_INVALID; /*lint !e527*/
18357 }
18358
18359 consdata = SCIPconsGetData(cons);
18360 assert(consdata != NULL);
18361
18362 return consdata->rhs;
18363}
18364
18365/** changes left hand side of linear constraint */
18367 SCIP* scip, /**< SCIP data structure */
18368 SCIP_CONS* cons, /**< constraint data */
18369 SCIP_Real lhs /**< new left hand side */
18370 )
18371{
18372 assert(scip != NULL);
18373 assert(cons != NULL);
18374
18375 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18376 {
18377 SCIPerrorMessage("constraint is not linear\n");
18378 return SCIP_INVALIDDATA;
18379 }
18380
18381 SCIP_CALL( chgLhs(scip, cons, lhs) );
18382
18383 return SCIP_OKAY;
18384}
18385
18386/** changes right hand side of linear constraint */
18388 SCIP* scip, /**< SCIP data structure */
18389 SCIP_CONS* cons, /**< constraint data */
18390 SCIP_Real rhs /**< new right hand side */
18391 )
18392{
18393 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18394 {
18395 SCIPerrorMessage("constraint is not linear\n");
18396 return SCIP_INVALIDDATA;
18397 }
18398
18399 SCIP_CALL( chgRhs(scip, cons, rhs) );
18400
18401 return SCIP_OKAY;
18402}
18403
18404/** gets the number of variables in the linear constraint */
18406 SCIP* scip, /**< SCIP data structure */
18407 SCIP_CONS* cons /**< constraint data */
18408 )
18409{
18410 SCIP_CONSDATA* consdata;
18411
18412 assert(scip != NULL);
18413 assert(cons != NULL);
18414
18415 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18416 {
18417 SCIPerrorMessage("constraint is not linear\n");
18418 SCIPABORT();
18419 return -1; /*lint !e527*/
18420 }
18421
18422 consdata = SCIPconsGetData(cons);
18423 assert(consdata != NULL);
18424
18425 return consdata->nvars;
18426}
18427
18428/** gets the array of variables in the linear constraint; the user must not modify this array! */
18430 SCIP* scip, /**< SCIP data structure */
18431 SCIP_CONS* cons /**< constraint data */
18432 )
18433{
18434 SCIP_CONSDATA* consdata;
18435
18436 assert(scip != NULL);
18437 assert(cons != NULL);
18438
18439 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18440 {
18441 SCIPerrorMessage("constraint is not linear\n");
18442 SCIPABORT();
18443 return NULL; /*lint !e527*/
18444 }
18445
18446 consdata = SCIPconsGetData(cons);
18447 assert(consdata != NULL);
18448
18449 return consdata->vars;
18450}
18451
18452/** gets the array of coefficient values in the linear constraint; the user must not modify this array! */
18454 SCIP* scip, /**< SCIP data structure */
18455 SCIP_CONS* cons /**< constraint data */
18456 )
18457{
18458 SCIP_CONSDATA* consdata;
18459
18460 assert(scip != NULL);
18461 assert(cons != NULL);
18462
18463 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18464 {
18465 SCIPerrorMessage("constraint is not linear\n");
18466 SCIPABORT();
18467 return NULL; /*lint !e527*/
18468 }
18469
18470 consdata = SCIPconsGetData(cons);
18471 assert(consdata != NULL);
18472
18473 return consdata->vals;
18474}
18475
18476/** gets the activity of the linear constraint in the given solution
18477 *
18478 * @note if the solution contains values at infinity, this method will return SCIP_INVALID in case the activity
18479 * comprises positive and negative infinity contributions
18480 */
18482 SCIP* scip, /**< SCIP data structure */
18483 SCIP_CONS* cons, /**< constraint data */
18484 SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18485 )
18486{
18487 SCIP_CONSDATA* consdata;
18488
18489 assert(scip != NULL);
18490 assert(cons != NULL);
18491
18492 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18493 {
18494 SCIPerrorMessage("constraint is not linear\n");
18495 SCIPABORT();
18496 return SCIP_INVALID; /*lint !e527*/
18497 }
18498
18499 consdata = SCIPconsGetData(cons);
18500 assert(consdata != NULL);
18501
18502 if( consdata->row != NULL )
18503 return SCIPgetRowSolActivity(scip, consdata->row, sol);
18504 else
18505 return consdataGetActivity(scip, consdata, sol);
18506}
18507
18508/** gets the feasibility of the linear constraint in the given solution */
18510 SCIP* scip, /**< SCIP data structure */
18511 SCIP_CONS* cons, /**< constraint data */
18512 SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18513 )
18514{
18515 SCIP_CONSDATA* consdata;
18516
18517 assert(scip != NULL);
18518 assert(cons != NULL);
18519
18520 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18521 {
18522 SCIPerrorMessage("constraint is not linear\n");
18523 SCIPABORT();
18524 return SCIP_INVALID; /*lint !e527*/
18525 }
18526
18527 consdata = SCIPconsGetData(cons);
18528 assert(consdata != NULL);
18529
18530 if( consdata->row != NULL )
18531 return SCIPgetRowSolFeasibility(scip, consdata->row, sol);
18532 else
18533 return consdataGetFeasibility(scip, consdata, sol);
18534}
18535
18536/** gets the dual solution of the linear constraint in the current LP */
18538 SCIP* scip, /**< SCIP data structure */
18539 SCIP_CONS* cons /**< constraint data */
18540 )
18541{
18542 SCIP_CONSDATA* consdata;
18543
18544 assert(scip != NULL);
18545 assert(cons != NULL);
18546 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18547
18548 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18549 {
18550 SCIPerrorMessage("constraint is not linear\n");
18551 SCIPABORT();
18552 return SCIP_INVALID; /*lint !e527*/
18553 }
18554
18555 consdata = SCIPconsGetData(cons);
18556 assert(consdata != NULL);
18557
18558 if( consdata->row != NULL )
18559 return SCIProwGetDualsol(consdata->row);
18560 else
18561 return 0.0;
18562}
18563
18564/** gets the dual Farkas value of the linear constraint in the current infeasible LP */
18566 SCIP* scip, /**< SCIP data structure */
18567 SCIP_CONS* cons /**< constraint data */
18568 )
18569{
18570 SCIP_CONSDATA* consdata;
18571
18572 assert(scip != NULL);
18573 assert(cons != NULL);
18574 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18575
18576 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18577 {
18578 SCIPerrorMessage("constraint is not linear\n");
18579 SCIPABORT();
18580 return SCIP_INVALID; /*lint !e527*/
18581 }
18582
18583 consdata = SCIPconsGetData(cons);
18584 assert(consdata != NULL);
18585
18586 if( consdata->row != NULL )
18587 return SCIProwGetDualfarkas(consdata->row);
18588 else
18589 return 0.0;
18590}
18591
18592/** returns the linear relaxation of the given linear constraint; may return NULL if no LP row was yet created;
18593 * the user must not modify the row!
18594 */
18596 SCIP* scip, /**< SCIP data structure */
18597 SCIP_CONS* cons /**< constraint data */
18598 )
18599{
18600 SCIP_CONSDATA* consdata;
18601
18602 assert(scip != NULL);
18603 assert(cons != NULL);
18604
18605 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18606 {
18607 SCIPerrorMessage("constraint is not linear\n");
18608 SCIPABORT();
18609 return NULL; /*lint !e527*/
18610 }
18611
18612 consdata = SCIPconsGetData(cons);
18613 assert(consdata != NULL);
18614
18615 return consdata->row;
18616}
18617
18618/** creates and returns the row of the given linear constraint */
18620 SCIP* scip, /**< SCIP data structure */
18621 SCIP_CONS* cons /**< constraint data */
18622 )
18623{
18624 SCIP_CONSDATA* consdata;
18625
18626 assert(scip != NULL);
18627 assert(cons != NULL);
18628
18629 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18630 {
18631 SCIPerrorMessage("constraint is not linear\n");
18632 SCIPABORT();
18633 return SCIP_ERROR; /*lint !e527*/
18634 }
18635
18636 consdata = SCIPconsGetData(cons);
18637 assert(consdata != NULL);
18638
18639 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
18641
18642 SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) ) ;
18643
18644 return SCIP_OKAY;
18645}
18646
18647/** tries to automatically convert a linear constraint into a more specific and more specialized constraint */
18649 SCIP* scip, /**< SCIP data structure */
18650 SCIP_CONS* cons, /**< source constraint to try to convert */
18651 SCIP_CONS** upgdcons /**< pointer to store upgraded constraint, or NULL if not successful */
18652 )
18653{
18654 SCIP_CONSHDLR* conshdlr;
18655 SCIP_CONSHDLRDATA* conshdlrdata;
18656 SCIP_CONSDATA* consdata;
18657 SCIP_VAR* var;
18658 SCIP_Real val;
18659 SCIP_Real lb;
18660 SCIP_Real ub;
18661 SCIP_Real poscoeffsum;
18662 SCIP_Real negcoeffsum;
18663 SCIP_Bool infeasible;
18664 SCIP_Bool integral;
18665 int nchgsides = 0;
18666 int nposbin;
18667 int nnegbin;
18668 int nposint;
18669 int nnegint;
18670 int nposimpl;
18671 int nnegimpl;
18672 int nposimplbin;
18673 int nnegimplbin;
18674 int nposcont;
18675 int nnegcont;
18676 int ncoeffspone;
18677 int ncoeffsnone;
18678 int ncoeffspint;
18679 int ncoeffsnint;
18680 int ncoeffspfrac;
18681 int ncoeffsnfrac;
18682 int i;
18683
18684 assert(scip != NULL);
18685 assert(cons != NULL);
18686 assert(upgdcons != NULL);
18687
18688 *upgdcons = NULL;
18689
18690 /* we cannot upgrade a modifiable linear constraint, since we don't know what additional coefficients to expect */
18691 if( SCIPconsIsModifiable(cons) )
18692 return SCIP_OKAY;
18693
18694 /* check for upgradability */
18695 if( SCIPconsGetNUpgradeLocks(cons) > 0 )
18696 return SCIP_OKAY;
18697
18698 /* get the constraint handler and check, if it's really a linear constraint */
18699 conshdlr = SCIPconsGetHdlr(cons);
18700 if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
18701 {
18702 SCIPerrorMessage("constraint is not linear\n");
18703 return SCIP_INVALIDDATA;
18704 }
18705
18706 /* get constraint handler data and constraint data */
18707 conshdlrdata = SCIPconshdlrGetData(conshdlr);
18708 assert(conshdlrdata != NULL);
18709 consdata = SCIPconsGetData(cons);
18710 assert(consdata != NULL);
18711
18712 /* check, if the constraint was already upgraded and will be deleted anyway after preprocessing */
18713 if( consdata->upgraded )
18714 return SCIP_OKAY;
18715
18716 /* check, if the constraint is already stored as LP row */
18717 if( consdata->row != NULL )
18718 {
18719 if( SCIProwIsInLP(consdata->row) )
18720 {
18721 SCIPerrorMessage("cannot upgrade linear constraint that is already stored as row in the LP\n");
18722 return SCIP_INVALIDDATA;
18723 }
18724 else
18725 {
18726 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
18727 }
18728 }
18729
18730 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
18731
18732 /* normalizeCons() can only detect infeasibility when scaling with the gcd. in that case, the scaling was
18733 * skipped and we hope that the infeasibility gets detected later again.
18734 *
18735 * TODO: do we want to try to upgrade the constraint anyway?
18736 *
18737 * TODO: this needs to be fixed on master by changing the API and passing a pointer to whether the constraint is
18738 * proven to be infeasible.
18739 */
18740 if( infeasible ) /*lint !e774*/
18741 return SCIP_OKAY;
18742
18743 /* tighten sides */
18744 SCIP_CALL( tightenSides(scip, cons, &nchgsides, &infeasible) );
18745
18746 if( infeasible ) /*lint !e774*/
18747 return SCIP_OKAY;
18748
18749 /*
18750 * calculate some statistics on linear constraint
18751 */
18752
18753 nposbin = 0;
18754 nnegbin = 0;
18755 nposint = 0;
18756 nnegint = 0;
18757 nposimpl = 0;
18758 nnegimpl = 0;
18759 nposimplbin = 0;
18760 nnegimplbin = 0;
18761 nposcont = 0;
18762 nnegcont = 0;
18763 ncoeffspone = 0;
18764 ncoeffsnone = 0;
18765 ncoeffspint = 0;
18766 ncoeffsnint = 0;
18767 ncoeffspfrac = 0;
18768 ncoeffsnfrac = 0;
18769 integral = TRUE;
18770 poscoeffsum = 0.0;
18771 negcoeffsum = 0.0;
18772
18773 for( i = 0; i < consdata->nvars; ++i )
18774 {
18775 var = consdata->vars[i];
18776 val = consdata->vals[i];
18777 lb = SCIPvarGetLbLocal(var);
18778 ub = SCIPvarGetUbLocal(var);
18779 assert(!SCIPisZero(scip, val));
18780
18782 {
18783 if( SCIPvarIsBinary(var) )
18784 {
18785 if( val >= 0.0 )
18786 ++nposimplbin;
18787 else
18788 ++nnegimplbin;
18789 }
18790 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18791 integral = integral && SCIPisIntegral(scip, val);
18792 if( val >= 0.0 )
18793 ++nposimpl;
18794 else
18795 ++nnegimpl;
18796 }
18797 else
18798 {
18799 switch( SCIPvarGetType(var) )
18800 {
18802 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18803 integral = integral && SCIPisIntegral(scip, val);
18804 if( val >= 0.0 )
18805 ++nposbin;
18806 else
18807 ++nnegbin;
18808 break;
18810 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18811 integral = integral && SCIPisIntegral(scip, val);
18812 if( val >= 0.0 )
18813 ++nposint;
18814 else
18815 ++nnegint;
18816 break;
18818 integral = integral && SCIPisEQ(scip, lb, ub) && SCIPisIntegral(scip, val * lb);
18819 if( val >= 0.0 )
18820 ++nposcont;
18821 else
18822 ++nnegcont;
18823 break;
18824 default:
18825 SCIPerrorMessage("unknown variable type\n");
18826 return SCIP_INVALIDDATA;
18827 } /*lint !e788*/
18828 }
18829
18830 if( SCIPisEQ(scip, val, 1.0) )
18831 ncoeffspone++;
18832 else if( SCIPisEQ(scip, val, -1.0) )
18833 ncoeffsnone++;
18834 else if( SCIPisIntegral(scip, val) )
18835 {
18836 if( SCIPisPositive(scip, val) )
18837 ncoeffspint++;
18838 else
18839 ncoeffsnint++;
18840 }
18841 else
18842 {
18843 if( SCIPisPositive(scip, val) )
18844 ncoeffspfrac++;
18845 else
18846 ncoeffsnfrac++;
18847 }
18848 if( SCIPisPositive(scip, val) )
18849 poscoeffsum += val;
18850 else
18851 negcoeffsum += val;
18852 }
18853
18854 /*
18855 * call the upgrading methods
18856 */
18857
18858 SCIPdebugMsg(scip, "upgrading linear constraint <%s> (%d upgrade methods):\n",
18859 SCIPconsGetName(cons), conshdlrdata->nlinconsupgrades);
18860 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",
18861 nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposcont, nnegcont,
18862 ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18863 poscoeffsum, negcoeffsum, integral);
18864
18865 /* try all upgrading methods in priority order in case the upgrading step is enable */
18866 for( i = 0; i < conshdlrdata->nlinconsupgrades && *upgdcons == NULL; ++i )
18867 {
18868 if( conshdlrdata->linconsupgrades[i]->active )
18869 {
18870 SCIP_CALL( conshdlrdata->linconsupgrades[i]->linconsupgd(scip, cons, consdata->nvars,
18871 consdata->vars, consdata->vals, consdata->lhs, consdata->rhs,
18872 nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposimplbin, nnegimplbin, nposcont, nnegcont,
18873 ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18874 poscoeffsum, negcoeffsum, integral,
18875 upgdcons) );
18876 }
18877 }
18878
18879#ifdef SCIP_DEBUG
18880 if( *upgdcons != NULL )
18881 {
18883 SCIPdebugMsg(scip, " -> upgraded to constraint type <%s>\n", SCIPconshdlrGetName(SCIPconsGetHdlr(*upgdcons)));
18884 SCIPdebugPrintCons(scip, *upgdcons, NULL);
18885 }
18886#endif
18887
18888 return SCIP_OKAY; /*lint !e438*/
18889}
18890
18891/** cleans up (multi-)aggregations and fixings from linear constraints */
18893 SCIP* scip, /**< SCIP data structure */
18894 SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
18895 SCIP_Bool* infeasible, /**< pointer to return whether the problem was detected to be infeasible */
18896 int* ndelconss /**< pointer to count number of deleted constraints */
18897 )
18898{
18899 SCIP_CONSHDLR* conshdlr;
18900 SCIP_CONS** conss;
18901 int nconss;
18902 int i;
18903
18904 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
18905 if( conshdlr == NULL )
18906 return SCIP_OKAY;
18907
18908 assert(infeasible != NULL);
18909 *infeasible = FALSE;
18910
18911 nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr);
18912 conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);
18913
18914 /* loop backwards since then deleted constraints do not interfere with the loop */
18915 for( i = nconss - 1; i >= 0; --i )
18916 {
18917 SCIP_CALL( applyFixings(scip, conss[i], infeasible) );
18918
18919 if( *infeasible )
18920 break;
18921
18922 if( SCIPconsGetData(conss[i])->nvars >= 1 )
18923 continue;
18924
18925 SCIP_CALL( SCIPdelCons(scip, conss[i]) );
18926 ++(*ndelconss);
18927 }
18928
18929 return SCIP_OKAY;
18930}
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 updateCutoffbound(SCIP *scip, SCIP_CONS *cons, SCIP_Real primalbound)
static void consdataUpdateDelCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
#define DEFAULT_RANGEDROWARTCONS
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, int pos)
#define MAXSCALEDCOEFINTEGER
static void consdataUpdateAddCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
static void getMinActivity(SCIP *scip, SCIP_CONSDATA *consdata, int posinf, int neginf, int poshuge, int neghuge, SCIP_Real delta, SCIP_Bool global, SCIP_Bool goodrelax, SCIP_Real *minactivity, SCIP_Bool *istight, SCIP_Bool *issettoinfinity)
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
#define BINWEIGHT
static SCIP_RETCODE chgRhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
static SCIP_RETCODE tightenVarBoundsEasy(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
static void consdataUpdateActivities(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound, SCIP_Real val, SCIP_BOUNDTYPE boundtype, SCIP_Bool global, SCIP_Bool checkreliability)
static unsigned int getParallelConsKey(SCIP_CONS *cons)
#define CONTWEIGHT
static SCIP_RETCODE fixVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars)
#define DEFAULT_DETECTPARTIALOBJECTIVE
static SCIP_RETCODE enforceConstraint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, int nusefulconss, SCIP_SOL *sol, SCIP_RESULT *result)
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
static void consdataGetActivityResiduals(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool goodrelax, SCIP_Real *minresactivity, SCIP_Real *maxresactivity, SCIP_Bool *ismintight, SCIP_Bool *ismaxtight, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
static SCIP_Real consdataGetMaxAbsval(SCIP_CONSDATA *consdata)
static SCIP_RETCODE addNlrow(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE consPrintConsSol(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, FILE *file)
static void getMaxActivity(SCIP *scip, SCIP_CONSDATA *consdata, int posinf, int neginf, int poshuge, int neghuge, SCIP_Real delta, SCIP_Bool global, SCIP_Bool goodrelax, SCIP_Real *maxactivity, SCIP_Bool *istight, SCIP_Bool *issettoinfinity)
static void getNewSidesAfterAggregation(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *slackvar, SCIP_Real slackcoef, SCIP_Real *newlhs, SCIP_Real *newrhs)
static SCIP_RETCODE convertUnaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *ndelconss)
static void consdataUpdateChgCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldval, SCIP_Real newval, SCIP_Bool checkreliability)
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
static void consdataRecomputeGlbMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
static SCIP_RETCODE applyFixings(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
static void consdataCalcActivities(SCIP *scip, SCIP_CONSDATA *consdata)
static void consdataGetGlbActivityResiduals(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool goodrelax, SCIP_Real *minresactivity, SCIP_Real *maxresactivity, SCIP_Bool *ismintight, SCIP_Bool *ismaxtight, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
static SCIP_RETCODE tightenVarUb(SCIP *scip, SCIP_CONS *cons, int pos, PROPRULE proprule, SCIP_Real newub, SCIP_Real oldub, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
static int getInferInt(PROPRULE proprule, int pos)
static int inferInfoGetProprule(INFERINFO inferinfo)
static SCIP_RETCODE dualPresolve(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss, int *nchgvartypes)
#define DEFAULT_MINGAINPERNMINCOMP
static SCIP_Real consdataGetFeasibility(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
static SCIP_RETCODE rangedRowSimplify(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides)
static SCIP_RETCODE aggregateVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars)
static SCIP_RETCODE propagateCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool tightenbounds, SCIP_Bool rangedrowpropagation, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, SCIP_Bool *cutoff, int *nchgbds, int *naddconss)
#define MAXSCALEDCOEF
static void consdataInvalidateActivities(SCIP_CONSDATA *consdata)
#define DEFAULT_RANGEDROWMAXDEPTH
static SCIP_RETCODE analyzeConflictRangedRow(SCIP *scip, SCIP_CONS *cons, SCIP_VAR **vars, int nvars, SCIP_VAR *var, SCIP_Real bound)
static SCIP_RETCODE consDropEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
static SCIP_RETCODE tightenVarBounds(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
static SCIP_Real consdataGetMinAbsval(SCIP_CONSDATA *consdata)
static SCIP_Bool consdataIsResidualIntegral(SCIP *scip, SCIP_CONSDATA *consdata, int pos, SCIP_Real val)
static int inferInfoToInt(INFERINFO inferinfo)
static SCIP_RETCODE preprocessConstraintPairs(SCIP *scip, SCIP_CONS **conss, int firstchange, int chkind, SCIP_Real maxaggrnormscale, SCIP_Bool *cutoff, int *ndelconss, int *nchgsides, int *nchgcoefs)
static SCIP_RETCODE consdataSort(SCIP *scip, SCIP_CONSDATA *consdata)
#define DEFAULT_SINGLEVARSTUFFING
#define INTWEIGHT
static SCIP_RETCODE checkParallelObjective(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata)
static SCIP_RETCODE simplifyInequalities(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides, SCIP_Bool *infeasible)
static SCIP_RETCODE consCatchAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
static SCIP_RETCODE resolvePropagation(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, INFERINFO inferinfo, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_RESULT *result)
static SCIP_Bool isRangedRow(SCIP *scip, SCIP_Real lhs, SCIP_Real rhs)
static SCIP_RETCODE checkPartialObjective(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata)
#define MAXVALRECOMP
static void consdataGetGlbActivityBounds(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Bool goodrelax, SCIP_Real *glbminactivity, SCIP_Real *glbmaxactivity, SCIP_Bool *ismintight, SCIP_Bool *ismaxtight, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
static SCIP_Bool canTightenBounds(SCIP_CONS *cons)
#define DEFAULT_SEPARATEALL
static void findOperators(const char *str, char **firstoperator, char **secondoperator, SCIP_Bool *success)
static INFERINFO getInferInfo(PROPRULE proprule, int pos)
Constraint handler for linear constraints in their most general form, .
constraint handler for nonlinear constraints specified by algebraic expressions
defines macros for basic operations in double-double arithmetic giving roughly twice the precision of...
#define QUAD_MEMBER(x)
Definition dbldblarith.h:48
#define SCIPquadprecSumQD(r, a, b)
Definition dbldblarith.h:62
#define QUAD_ASSIGN(a, constant)
Definition dbldblarith.h:51
#define QUAD(x)
Definition dbldblarith.h:47
#define QUAD_ASSIGN_Q(a, b)
Definition dbldblarith.h:52
#define QUAD_TO_DBL(x)
Definition dbldblarith.h:49
methods for debugging
#define SCIPdebugGetSolVal(scip, var, val)
Definition debug.h: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
void SCIPswapPointers(void **pointer1, void **pointer2)
Definition misc.c:10511
int SCIPgetNLPBranchCands(SCIP *scip)
SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
const char * SCIPconflicthdlrGetName(SCIP_CONFLICTHDLR *conflicthdlr)
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
SCIP_RETCODE SCIPincludeConflicthdlrBasic(SCIP *scip, SCIP_CONFLICTHDLR **conflicthdlrptr, const char *name, const char *desc, int priority, SCIP_DECL_CONFLICTEXEC((*conflictexec)), SCIP_CONFLICTHDLRDATA *conflicthdlrdata)
int SCIPconshdlrGetNCheckConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4802
void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
Definition cons.c:4350
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:372
SCIP_RETCODE SCIPsetConshdlrActive(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:670
SCIP_CONS ** SCIPconshdlrGetCheckConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4759
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition scip_cons.c:540
SCIP_RETCODE SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
Definition scip_cons.c:235
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition scip_cons.c:281
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:323
SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
Definition scip_cons.c:181
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:808
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:831
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:785
int SCIPconshdlrGetPropFreq(SCIP_CONSHDLR *conshdlr)
Definition cons.c:5286
SCIP_RETCODE SCIPsetConshdlrGetSignedPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:924
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4782
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4320
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)),)
Definition scip_cons.c:347
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition scip_cons.c:940
SCIP_RETCODE SCIPsetConshdlrInit(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:396
SCIP_RETCODE SCIPsetConshdlrGetPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:900
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:578
SCIP_RETCODE SCIPsetConshdlrInitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:444
SCIP_RETCODE SCIPsetConshdlrDeactive(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:693
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4340
int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4816
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:601
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:647
SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:516
SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:468
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4739
SCIP_RETCODE SCIPsetConshdlrDelvars(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:762
SCIP_RETCODE SCIPsetConshdlrExit(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:420
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:624
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:854
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition cons.c:8423
int SCIPconsGetPos(SCIP_CONS *cons)
Definition cons.c:8403
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition cons.c:8652
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition cons.c:8413
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition cons.c:8562
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition scip_cons.c:2536
int SCIPconsGetNUpgradeLocks(SCIP_CONS *cons)
Definition cons.c:8845
SCIP_RETCODE SCIPsetConsSeparated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool separate)
Definition scip_cons.c:1296
SCIP_Bool SCIPconsIsMarkedPropagate(SCIP_CONS *cons)
Definition cons.c:8602
SCIP_Bool SCIPconsIsOriginal(SCIP_CONS *cons)
Definition cons.c:8692
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition cons.c:8592
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition cons.c:8522
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition cons.c:8702
int SCIPconsGetNLocksPos(SCIP_CONS *cons)
Definition cons.c:8742
SCIP_RETCODE SCIPsetConsInitial(SCIP *scip, SCIP_CONS *cons, SCIP_Bool initial)
Definition scip_cons.c:1271
SCIP_RETCODE SCIPsetConsEnforced(SCIP *scip, SCIP_CONS *cons, SCIP_Bool enforce)
Definition scip_cons.c:1321
SCIP_Bool SCIPconsIsLockedType(SCIP_CONS *cons, SCIP_LOCKTYPE locktype)
Definition cons.c:8786
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition cons.c:8582
SCIP_RETCODE SCIPunmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition scip_cons.c:2042
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition cons.c:8454
SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition scip_cons.c:997
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition cons.c:8612
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition cons.c:8632
int SCIPconsGetNLocksNeg(SCIP_CONS *cons)
Definition cons.c:8752
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition cons.c:8393
SCIP_Bool SCIPconsIsLocked(SCIP_CONS *cons)
Definition cons.c:8732
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition scip_cons.c:1812
SCIP_RETCODE SCIPmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition scip_cons.c:2014
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition cons.c:8642
SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
Definition scip_cons.c:1524
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition cons.c:8672
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition scip_cons.c:1173
SCIP_RETCODE SCIPsetConsPropagated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool propagate)
Definition scip_cons.c:1371
SCIP_RETCODE SCIPsetConsChecked(SCIP *scip, SCIP_CONS *cons, SCIP_Bool check)
Definition scip_cons.c:1346
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition cons.c:8572
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition scip_cons.c:1784
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition cons.c:8662
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition scip_cut.c:225
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition scip_event.c:111
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition event.c:396
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition event.c:1194
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition scip_event.c:367
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition scip_event.c:413
SCIP_Real SCIPeventGetOldbound(SCIP_EVENT *event)
Definition event.c:1391
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition event.c:1217
SCIP_IMPLINTTYPE SCIPeventGetOldImpltype(SCIP_EVENT *event)
Definition event.c:1496
SCIP_Real SCIPeventGetNewbound(SCIP_EVENT *event)
Definition event.c:1415
SCIP_VARTYPE SCIPeventGetOldtype(SCIP_EVENT *event)
Definition event.c:1462
int SCIPexprGetNChildren(SCIP_EXPR *expr)
Definition expr.c:3872
SCIP_Bool SCIPisExprSum(SCIP *scip, SCIP_EXPR *expr)
Definition scip_expr.c:1479
SCIP_Real * SCIPgetCoefsExprSum(SCIP_EXPR *expr)
Definition expr_sum.c:1554
SCIP_Bool SCIPisExprVar(SCIP *scip, SCIP_EXPR *expr)
Definition scip_expr.c:1457
SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
Definition expr.c:3882
SCIP_Real SCIPgetConstantExprSum(SCIP_EXPR *expr)
Definition expr_sum.c:1569
SCIP_VAR * SCIPgetVarExprVar(SCIP_EXPR *expr)
Definition expr_var.c: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:8288
void SCIPlinConsStatsReset(SCIP_LINCONSSTATS *linconsstats)
Definition cons.c:8257
SCIP_Bool SCIProwIsModifiable(SCIP_ROW *row)
Definition lp.c:17805
SCIP_RETCODE SCIPchgRowLhs(SCIP *scip, SCIP_ROW *row, SCIP_Real lhs)
Definition scip_lp.c:1529
SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONS *cons, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition scip_lp.c:1398
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition scip_lp.c:1646
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition scip_lp.c:2176
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition scip_lp.c:2131
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition scip_lp.c:1508
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition lp.c:17719
SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
Definition scip_lp.c:1553
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition lp.c:17917
SCIP_RETCODE SCIPaddVarsToRow(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition scip_lp.c:1672
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition lp.c:17706
SCIP_Real SCIPgetRowSolActivity(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition scip_lp.c:2108
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition scip_sol.c: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:23515
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:18321
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition var.c:23535
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:23844
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition var.c:23869
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition var.c:23643
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition var.c:23479
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:23387
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:23499
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24269
SCIP_Bool SCIPdoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:10942
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition var.c:23431
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:23507
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition var.c:23901
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:23454
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:24143
int SCIPvarGetIndex(SCIP_VAR *var)
Definition var.c:23653
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:23663
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:23268
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:24930
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:24313
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:23491
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:23807
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition var.c:23795
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:23525
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24235
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition var.c:23444
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition var.c:23601
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition var.c:23418
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition var.c:24121
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:23464
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition var.c:17275
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:24920
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:23819
void SCIPsortDownRealPtr(SCIP_Real *realarray, void **ptrarray, int len)
void SCIPsortRealInt(SCIP_Real *realarray, int *intarray, int len)
void SCIPsort(int *perm, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
Definition misc.c:5581
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition misc.c:10827
SCIP_RETCODE SCIPskipSpace(char **s)
Definition misc.c:10816
SCIP_RETCODE SCIPgetSymActiveVariables(SCIP *scip, SYM_SYMTYPE symtype, SCIP_VAR ***vars, SCIP_Real **scalars, int *nvars, SCIP_Real *constant, SCIP_Bool transformed)
SCIP_RETCODE SCIPextendPermsymDetectionGraphLinear(SCIP *scip, SYM_GRAPH *graph, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_CONS *cons, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool *success)
return SCIP_OKAY
int c
int depth
SCIP_Bool cutoff
SCIP_Real objval
static SCIP_SOL * sol
SCIP_Real obj
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
SCIP_VAR * var
SCIP_Real frac
static SCIP_Bool propagate
static SCIP_VAR ** vars
SCIP_Real alpha
static const SCIP_Real scalars[]
Definition lp.c:5959
static const char * paramname[]
Definition lpi_msk.c:5172
memory allocation routines
#define BMScopyMemoryArray(ptr, source, num)
Definition memory.h:134
#define BMSclearMemoryArray(ptr, num)
Definition memory.h:130
struct BMS_BlkMem BMS_BLKMEM
Definition memory.h:437
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition message.c:618
public methods for conflict analysis handlers
public methods for managing constraints
public methods for managing events
public functions to work with algebraic expressions
public methods for LP management
public methods for message output
#define SCIPerrorMessage
Definition pub_message.h:64
#define SCIPstatisticMessage
#define SCIPdebug(x)
Definition pub_message.h:93
#define SCIPdebugPrintCons(x, y, z)
#define SCIPdebugMessage
Definition pub_message.h:96
public data structures and miscellaneous methods
#define SCIPisFinite(x)
Definition pub_misc.h:82
methods for sorting joint arrays of various types
public methods for problem variables
public methods for branching rule plugins and branching
public methods for conflict handler plugins and conflict analysis
public methods for constraint handler plugins and constraints
public methods for problem copies
public methods for cuts and aggregation rows
public methods for event handler plugins and event handlers
general public methods
public methods for the LP relaxation, rows and columns
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for the probing mode
public methods for solutions
public methods for querying solving statistics
public methods for the branch-and-bound tree
public methods for SCIP variables
static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
Main separation function.
SCIP_DECL_LINCONSUPGD((*linconsupgd))
structs for symmetry computations
methods for dealing with symmetry detection graphs
struct SCIP_Conflicthdlr SCIP_CONFLICTHDLR
#define SCIP_DECL_CONFLICTEXEC(x)
@ SCIP_CONFTYPE_PROPAGATION
#define SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(x)
Definition type_cons.h:956
#define SCIP_DECL_CONSGETPERMSYMGRAPH(x)
Definition type_cons.h:938
#define SCIP_DECL_CONSENFOLP(x)
Definition type_cons.h:363
#define SCIP_DECL_CONSDELETE(x)
Definition type_cons.h:229
struct SCIP_Cons SCIP_CONS
Definition type_cons.h:63
#define SCIP_DECL_CONSEXIT(x)
Definition type_cons.h:136
#define SCIP_DECL_CONSGETVARS(x)
Definition type_cons.h:867
#define SCIP_DECL_CONSINITSOL(x)
Definition type_cons.h:201
#define SCIP_DECL_CONSPRINT(x)
Definition type_cons.h:769
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition type_cons.h:64
#define SCIP_DECL_CONSSEPALP(x)
Definition type_cons.h:288
struct SYM_Graph SYM_GRAPH
Definition type_cons.h:68
#define SCIP_DECL_CONSENFORELAX(x)
Definition type_cons.h:388
struct SCIP_LinConsStats SCIP_LINCONSSTATS
Definition type_cons.h:67
#define SCIP_DECL_CONSPROP(x)
Definition type_cons.h:506
#define SCIP_DECL_CONSGETNVARS(x)
Definition type_cons.h:885
#define SCIP_DECL_CONSRESPROP(x)
Definition type_cons.h:612
@ SCIP_LINCONSTYPE_BINPACKING
Definition type_cons.h:85
@ SCIP_LINCONSTYPE_VARBOUND
Definition type_cons.h:78
@ SCIP_LINCONSTYPE_EMPTY
Definition type_cons.h:73
@ SCIP_LINCONSTYPE_INVKNAPSACK
Definition type_cons.h:83
@ SCIP_LINCONSTYPE_PRECEDENCE
Definition type_cons.h:77
@ SCIP_LINCONSTYPE_AGGREGATION
Definition type_cons.h:76
@ SCIP_LINCONSTYPE_MIXEDBINARY
Definition type_cons.h:88
@ SCIP_LINCONSTYPE_SINGLETON
Definition type_cons.h:75
@ SCIP_LINCONSTYPE_SETCOVERING
Definition type_cons.h:81
@ SCIP_LINCONSTYPE_EQKNAPSACK
Definition type_cons.h:84
@ SCIP_LINCONSTYPE_FREE
Definition type_cons.h:74
@ SCIP_LINCONSTYPE_KNAPSACK
Definition type_cons.h:86
@ SCIP_LINCONSTYPE_SETPARTITION
Definition type_cons.h:79
@ SCIP_LINCONSTYPE_INTKNAPSACK
Definition type_cons.h:87
@ SCIP_LINCONSTYPE_SETPACKING
Definition type_cons.h:80
@ SCIP_LINCONSTYPE_GENERAL
Definition type_cons.h:89
@ SCIP_LINCONSTYPE_CARDINALITY
Definition type_cons.h:82
#define SCIP_DECL_CONSACTIVE(x)
Definition type_cons.h:691
#define SCIP_DECL_CONSENFOPS(x)
Definition type_cons.h:431
#define SCIP_DECL_CONSPARSE(x)
Definition type_cons.h:845
#define SCIP_DECL_CONSTRANS(x)
Definition type_cons.h:239
#define SCIP_DECL_CONSDEACTIVE(x)
Definition type_cons.h:706
#define SCIP_DECL_CONSPRESOL(x)
Definition type_cons.h:561
#define SCIP_DECL_CONSINITLP(x)
Definition type_cons.h:259
#define SCIP_DECL_CONSEXITPRE(x)
Definition type_cons.h:180
#define SCIP_DECL_CONSLOCK(x)
Definition type_cons.h:676
struct SCIP_Conshdlr SCIP_CONSHDLR
Definition type_cons.h:62
#define SCIP_DECL_CONSCOPY(x)
Definition type_cons.h:810
#define SCIP_DECL_CONSINIT(x)
Definition type_cons.h:126
struct SCIP_ConsData SCIP_CONSDATA
Definition type_cons.h:65
#define SCIP_DECL_CONSCHECK(x)
Definition type_cons.h:474
#define SCIP_DECL_CONSHDLRCOPY(x)
Definition type_cons.h:108
#define SCIP_DECL_CONSEXITSOL(x)
Definition type_cons.h:216
#define SCIP_DECL_CONSFREE(x)
Definition type_cons.h:116
#define SCIP_DECL_CONSSEPASOL(x)
Definition type_cons.h:320
#define SCIP_DECL_CONSDELVARS(x)
Definition type_cons.h:753
struct SCIP_Eventhdlr SCIP_EVENTHDLR
Definition type_event.h:159
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition type_event.h:127
#define SCIP_EVENTTYPE_VARUNLOCKED
Definition type_event.h:73
#define SCIP_EVENTTYPE_TYPECHANGED
Definition type_event.h:86
#define SCIP_EVENTTYPE_GUBCHANGED
Definition type_event.h:76
#define SCIP_EVENTTYPE_GBDCHANGED
Definition type_event.h:122
struct SCIP_EventData SCIP_EVENTDATA
Definition type_event.h:179
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition type_event.h:79
#define SCIP_EVENTTYPE_VARFIXED
Definition type_event.h:72
#define SCIP_EVENTTYPE_VARDELETED
Definition type_event.h:71
#define SCIP_DECL_EVENTEXEC(x)
Definition type_event.h:259
#define SCIP_EVENTTYPE_FORMAT
Definition type_event.h:157
#define SCIP_EVENTTYPE_GLBCHANGED
Definition type_event.h:75
#define SCIP_EVENTTYPE_BOUNDRELAXED
Definition type_event.h:126
#define SCIP_EVENTTYPE_LBCHANGED
Definition type_event.h:123
#define SCIP_EVENTTYPE_UBCHANGED
Definition type_event.h:124
uint64_t SCIP_EVENTTYPE
Definition type_event.h:156
#define SCIP_EVENTTYPE_IMPLTYPECHANGED
Definition type_event.h:87
#define SCIP_EVENTTYPE_DISABLED
Definition type_event.h:67
#define SCIP_EVENTTYPE_BOUNDTIGHTENED
Definition type_event.h:125
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition type_event.h:77
struct SCIP_Expr SCIP_EXPR
Definition type_expr.h:55
@ SCIP_EXPRCURV_LINEAR
Definition type_expr.h:65
struct SCIP_Row SCIP_ROW
Definition type_lp.h:105
@ SCIP_BOUNDTYPE_UPPER
Definition type_lp.h:58
@ SCIP_BOUNDTYPE_LOWER
Definition type_lp.h:57
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition type_lp.h:60
@ SCIP_VERBLEVEL_HIGH
struct SCIP_HashMap SCIP_HASHMAP
Definition type_misc.h:106
#define SCIP_DECL_HASHKEYEQ(x)
Definition type_misc.h:195
#define SCIP_DECL_SORTINDCOMP(x)
Definition type_misc.h:181
#define SCIP_DECL_HASHGETKEY(x)
Definition type_misc.h:192
#define SCIP_DECL_HASHKEYVAL(x)
Definition type_misc.h:198
struct SCIP_HashTable SCIP_HASHTABLE
Definition type_misc.h:88
struct SCIP_NlRow SCIP_NLROW
Definition type_nlp.h:41
@ SCIP_DIDNOTRUN
Definition type_result.h:42
@ SCIP_CUTOFF
Definition type_result.h:48
@ SCIP_FEASIBLE
Definition type_result.h:45
@ SCIP_REDUCEDDOM
Definition type_result.h:51
@ SCIP_DIDNOTFIND
Definition type_result.h:44
@ SCIP_CONSADDED
Definition type_result.h:52
@ SCIP_SEPARATED
Definition type_result.h:49
@ SCIP_SUCCESS
Definition type_result.h:58
@ SCIP_INFEASIBLE
Definition type_result.h:46
enum SCIP_Result SCIP_RESULT
Definition type_result.h:61
@ SCIP_READERROR
@ SCIP_INVALIDDATA
@ SCIP_PLUGINNOTFOUND
@ SCIP_ERROR
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
@ SCIP_STAGE_PROBLEM
Definition type_set.h:45
@ SCIP_STAGE_PRESOLVING
Definition type_set.h:49
@ SCIP_STAGE_INITSOLVE
Definition type_set.h:52
@ SCIP_STAGE_EXITPRESOLVE
Definition type_set.h:50
@ SCIP_STAGE_SOLVING
Definition type_set.h:53
@ SCIP_STAGE_TRANSFORMING
Definition type_set.h:46
@ SCIP_STAGE_PRESOLVED
Definition type_set.h:51
struct SCIP_Sol SCIP_SOL
Definition type_sol.h:57
enum SYM_Symtype SYM_SYMTYPE
@ SYM_SYMTYPE_SIGNPERM
@ SYM_SYMTYPE_PERM
#define SCIP_PRESOLTIMING_EXHAUSTIVE
Definition type_timing.h:54
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
#define NLOCKTYPES
Definition type_var.h:138
enum SCIP_ImplintType SCIP_IMPLINTTYPE
Definition type_var.h:117
@ SCIP_IMPLINTTYPE_NONE
Definition type_var.h:90
@ SCIP_IMPLINTTYPE_STRONG
Definition type_var.h:106
@ SCIP_IMPLINTTYPE_WEAK
Definition type_var.h:91
struct SCIP_BdChgIdx SCIP_BDCHGIDX
Definition type_var.h:151
#define SCIP_DEPRECATED_VARTYPE_IMPLINT
Definition type_var.h:79
@ SCIP_VARTYPE_INTEGER
Definition type_var.h:65
@ SCIP_VARTYPE_CONTINUOUS
Definition type_var.h:71
@ SCIP_VARTYPE_BINARY
Definition type_var.h:64
@ SCIP_VARSTATUS_ORIGINAL
Definition type_var.h:51
@ SCIP_VARSTATUS_FIXED
Definition type_var.h:54
@ SCIP_VARSTATUS_COLUMN
Definition type_var.h:53
@ SCIP_VARSTATUS_MULTAGGR
Definition type_var.h:56
@ SCIP_VARSTATUS_NEGATED
Definition type_var.h:57
@ SCIP_VARSTATUS_AGGREGATED
Definition type_var.h:55
@ SCIP_VARSTATUS_LOOSE
Definition type_var.h:52
enum SCIP_LockType SCIP_LOCKTYPE
Definition type_var.h:144
@ SCIP_LOCKTYPE_MODEL
Definition type_var.h:141
enum SCIP_Vartype SCIP_VARTYPE
Definition type_var.h:73
enum SCIP_Varstatus SCIP_VARSTATUS
Definition type_var.h:59