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-2023 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/dbldblarith.h"
92
93
94#define CONSHDLR_NAME "linear"
95#define CONSHDLR_DESC "linear constraints of the form lhs <= a^T x <= rhs"
96#define CONSHDLR_SEPAPRIORITY +100000 /**< priority of the constraint handler for separation */
97#define CONSHDLR_ENFOPRIORITY -1000000 /**< priority of the constraint handler for constraint enforcing */
98#define CONSHDLR_CHECKPRIORITY -1000000 /**< priority of the constraint handler for checking feasibility */
99#define CONSHDLR_SEPAFREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
100#define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
101#define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
102 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
103#define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
104#define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
105#define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
106#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
107
108#define CONSHDLR_PRESOLTIMING (SCIP_PRESOLTIMING_FAST | SCIP_PRESOLTIMING_EXHAUSTIVE) /**< presolving timing of the constraint handler (fast, medium, or exhaustive) */
109#define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
110
111#define EVENTHDLR_NAME "linear"
112#define EVENTHDLR_DESC "bound change event handler for linear constraints"
113
114#define CONFLICTHDLR_NAME "linear"
115#define CONFLICTHDLR_DESC "conflict handler creating linear constraints"
116#define CONFLICTHDLR_PRIORITY -1000000
117
118#define DEFAULT_TIGHTENBOUNDSFREQ 1 /**< multiplier on propagation frequency, how often the bounds are tightened */
119#define DEFAULT_MAXROUNDS 5 /**< maximal number of separation rounds per node (-1: unlimited) */
120#define DEFAULT_MAXROUNDSROOT -1 /**< maximal number of separation rounds in the root node (-1: unlimited) */
121#define DEFAULT_MAXSEPACUTS 50 /**< maximal number of cuts separated per separation round */
122#define DEFAULT_MAXSEPACUTSROOT 200 /**< maximal number of cuts separated per separation round in root node */
123#define DEFAULT_PRESOLPAIRWISE TRUE /**< should pairwise constraint comparison be performed in presolving? */
124#define DEFAULT_PRESOLUSEHASHING TRUE /**< should hash table be used for detecting redundant constraints in advance */
125#define DEFAULT_NMINCOMPARISONS 200000 /**< number for minimal pairwise presolving comparisons */
126#define DEFAULT_MINGAINPERNMINCOMP 1e-06 /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise
127 * comparison round */
128#define DEFAULT_SORTVARS TRUE /**< should variables be sorted after presolve w.r.t their coefficient absolute for faster
129 * propagation? */
130#define DEFAULT_CHECKRELMAXABS FALSE /**< should the violation for a constraint with side 0.0 be checked relative
131 * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
132#define DEFAULT_MAXAGGRNORMSCALE 0.0 /**< maximal allowed relative gain in maximum norm for constraint aggregation
133 * (0.0: disable constraint aggregation) */
134#define DEFAULT_MAXEASYACTIVITYDELTA 1e6 /**< maximum activity delta to run easy propagation on linear constraint
135 * (faster, but numerically less stable) */
136#define DEFAULT_MAXCARDBOUNDDIST 0.0 /**< maximal relative distance from current node's dual bound to primal bound compared
137 * to best node's dual bound for separating knapsack cardinality cuts */
138#define DEFAULT_SEPARATEALL FALSE /**< should all constraints be subject to cardinality cut generation instead of only
139 * the ones with non-zero dual value? */
140#define DEFAULT_AGGREGATEVARIABLES TRUE /**< should presolving search for redundant variables in equations */
141#define DEFAULT_SIMPLIFYINEQUALITIES TRUE /**< should presolving try to simplify inequalities */
142#define DEFAULT_DUALPRESOLVING TRUE /**< should dual presolving steps be performed? */
143#define DEFAULT_SINGLETONSTUFFING TRUE /**< should stuffing of singleton continuous variables be performed? */
144#define DEFAULT_SINGLEVARSTUFFING FALSE /**< should single variable stuffing be performed, which tries to fulfill
145 * constraints using the cheapest variable? */
146#define DEFAULT_DETECTCUTOFFBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
147 * function defining an upper bound and prevent these constraints from
148 * entering the LP */
149#define DEFAULT_DETECTLOWERBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
150 * function defining a lower bound and prevent these constraints from
151 * entering the LP */
152#define DEFAULT_DETECTPARTIALOBJECTIVE TRUE/**< should presolving try to detect subsets of constraints parallel to the
153 * objective function */
154#define DEFAULT_RANGEDROWPROPAGATION TRUE /**< should we perform ranged row propagation */
155#define DEFAULT_RANGEDROWARTCONS TRUE /**< should presolving and propagation extract sub-constraints from ranged rows and equations? */
156#define DEFAULT_RANGEDROWMAXDEPTH INT_MAX /**< maximum depth to apply ranged row propagation */
157#define DEFAULT_RANGEDROWFREQ 1 /**< frequency for applying ranged row propagation */
158
159#define DEFAULT_MULTAGGRREMOVE FALSE /**< should multi-aggregations only be performed if the constraint can be
160 * removed afterwards? */
161#define DEFAULT_MAXMULTAGGRQUOT 1e+03 /**< maximum coefficient dynamism (ie. maxabsval / minabsval) for multiaggregation */
162#define DEFAULT_MAXDUALMULTAGGRQUOT 1e+20 /**< maximum coefficient dynamism (ie. maxabsval / minabsval) for multiaggregation */
163#define DEFAULT_EXTRACTCLIQUES TRUE /**< should cliques be extracted? */
164
165#define MAXDNOM 10000LL /**< maximal denominator for simple rational fixed values */
166#define MAXSCALEDCOEF 0 /**< maximal coefficient value after scaling */
167#define MAXSCALEDCOEFINTEGER 0 /**< maximal coefficient value after scaling if all variables are of integral
168 * type
169 */
170#define MAXACTVAL 1e+09 /**< maximal absolute value of full and partial activities such that
171 * redundancy-based simplifications are allowed to be applied
172 */
173
174#define MAXVALRECOMP 1e+06 /**< maximal abolsute value we trust without recomputing the activity */
175#define MINVALRECOMP 1e-05 /**< minimal abolsute value we trust without recomputing the activity */
176
177
178#define NONLINCONSUPGD_PRIORITY 1000000 /**< priority of the constraint handler for upgrading of expressions constraints */
179
180/* @todo add multi-aggregation of variables that are in exactly two equations (, if not numerically an issue),
181 * maybe in fullDualPresolve(), see convertLongEquality()
182 */
183
184
185/** constraint data for linear constraints */
186struct SCIP_ConsData
187{
188 SCIP_Real lhs; /**< left hand side of row (for ranged rows) */
189 SCIP_Real rhs; /**< right hand side of row */
190 SCIP_Real maxabsval; /**< maximum absolute value of all coefficients */
191 SCIP_Real minabsval; /**< minimal absolute value of all coefficients */
192 QUAD_MEMBER(SCIP_Real minactivity); /**< minimal value w.r.t. the variable's local bounds for the constraint's
193 * activity, ignoring the coefficients contributing with infinite value */
194 QUAD_MEMBER(SCIP_Real maxactivity); /**< maximal value w.r.t. the variable's local bounds for the constraint's
195 * activity, ignoring the coefficients contributing with infinite value */
196 SCIP_Real lastminactivity; /**< last minimal activity which was computed by complete summation
197 * over all contributing values */
198 SCIP_Real lastmaxactivity; /**< last maximal activity which was computed by complete summation
199 * over all contributing values */
200 QUAD_MEMBER(SCIP_Real glbminactivity); /**< minimal value w.r.t. the variable's global bounds for the constraint's
201 * activity, ignoring the coefficients contributing with infinite value */
202 QUAD_MEMBER(SCIP_Real glbmaxactivity); /**< maximal value w.r.t. the variable's global bounds for the constraint's
203 * activity, ignoring the coefficients contributing with infinite value */
204 SCIP_Real lastglbminactivity; /**< last global minimal activity which was computed by complete summation
205 * over all contributing values */
206 SCIP_Real lastglbmaxactivity; /**< last global maximal activity which was computed by complete summation
207 * over all contributing values */
208 SCIP_Real maxactdelta; /**< maximal activity contribution of a single variable, or SCIP_INVALID if invalid */
209 SCIP_VAR* maxactdeltavar; /**< variable with maximal activity contribution, or NULL if invalid */
210 uint64_t possignature; /**< bit signature of coefficients that may take a positive value */
211 uint64_t negsignature; /**< bit signature of coefficients that may take a negative value */
212 SCIP_ROW* row; /**< LP row, if constraint is already stored in LP row format */
213 SCIP_NLROW* nlrow; /**< NLP row, if constraint has been added to NLP relaxation */
214 SCIP_VAR** vars; /**< variables of constraint entries */
215 SCIP_Real* vals; /**< coefficients of constraint entries */
216 SCIP_EVENTDATA** eventdata; /**< event data for bound change events of the variables */
217 int minactivityneginf; /**< number of coefficients contributing with neg. infinite value to minactivity */
218 int minactivityposinf; /**< number of coefficients contributing with pos. infinite value to minactivity */
219 int maxactivityneginf; /**< number of coefficients contributing with neg. infinite value to maxactivity */
220 int maxactivityposinf; /**< number of coefficients contributing with pos. infinite value to maxactivity */
221 int minactivityneghuge; /**< number of coefficients contributing with huge neg. value to minactivity */
222 int minactivityposhuge; /**< number of coefficients contributing with huge pos. value to minactivity */
223 int maxactivityneghuge; /**< number of coefficients contributing with huge neg. value to maxactivity */
224 int maxactivityposhuge; /**< number of coefficients contributing with huge pos. value to maxactivity */
225 int glbminactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbminactivity */
226 int glbminactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbminactivity */
227 int glbmaxactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbmaxactivity */
228 int glbmaxactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbmaxactivity */
229 int glbminactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbminactivity */
230 int glbminactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbminactivity */
231 int glbmaxactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbmaxactivity */
232 int glbmaxactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbmaxactivity */
233 int varssize; /**< size of the vars- and vals-arrays */
234 int nvars; /**< number of nonzeros in constraint */
235 int nbinvars; /**< the number of binary variables in the constraint, only valid after
236 * sorting in stage >= SCIP_STAGE_INITSOLVE
237 */
238 unsigned int boundstightened:2; /**< is constraint already propagated with bound tightening? */
239 unsigned int rangedrowpropagated:2; /**< did we perform ranged row propagation on this constraint?
240 * (0: no, 1: yes, 2: with potentially adding artificial constraint */
241 unsigned int validmaxabsval:1; /**< is the maximum absolute value valid? */
242 unsigned int validminabsval:1; /**< is the minimum absolute value valid? */
243 unsigned int validactivities:1; /**< are the activity bounds (local and global) valid? */
244 unsigned int validminact:1; /**< is the local minactivity valid? */
245 unsigned int validmaxact:1; /**< is the local maxactivity valid? */
246 unsigned int validglbminact:1; /**< is the global minactivity valid? */
247 unsigned int validglbmaxact:1; /**< is the global maxactivity valid? */
248 unsigned int presolved:1; /**< is constraint already presolved? */
249 unsigned int removedfixings:1; /**< are all fixed variables removed from the constraint? */
250 unsigned int validsignature:1; /**< is the bit signature valid? */
251 unsigned int changed:1; /**< was constraint changed since last aggregation round in preprocessing? */
252 unsigned int normalized:1; /**< is the constraint in normalized form? */
253 unsigned int upgradetried:1; /**< was the constraint already tried to be upgraded? */
254 unsigned int upgraded:1; /**< is the constraint upgraded and will it be removed after preprocessing? */
255 unsigned int indexsorted:1; /**< are the constraint's variables sorted by type and index? */
256 unsigned int merged:1; /**< are the constraint's equal variables already merged? */
257 unsigned int cliquesadded:1; /**< were the cliques of the constraint already extracted? */
258 unsigned int implsadded:1; /**< were the implications of the constraint already extracted? */
259 unsigned int coefsorted:1; /**< are variables sorted by type and their absolute activity delta? */
260 unsigned int varsdeleted:1; /**< were variables deleted after last cleanup? */
261 unsigned int hascontvar:1; /**< does the constraint contain at least one continuous variable? */
262 unsigned int hasnonbinvar:1; /**< does the constraint contain at least one non-binary variable? */
263 unsigned int hasnonbinvalid:1; /**< is the information stored in hasnonbinvar and hascontvar valid? */
264 unsigned int checkabsolute:1; /**< should the constraint be checked w.r.t. an absolute feasibilty tolerance? */
265};
266
267/** event data for bound change event */
268struct SCIP_EventData
269{
270 SCIP_CONS* cons; /**< linear constraint to process the bound change for */
271 int varpos; /**< position of variable in vars array */
272 int filterpos; /**< position of event in variable's event filter */
273};
274
275/** constraint handler data */
276struct SCIP_ConshdlrData
277{
278 SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events */
279 SCIP_LINCONSUPGRADE** linconsupgrades; /**< linear constraint upgrade methods for specializing linear constraints */
280 SCIP_Real maxaggrnormscale; /**< maximal allowed relative gain in maximum norm for constraint aggregation
281 * (0.0: disable constraint aggregation) */
282 SCIP_Real maxcardbounddist; /**< maximal relative distance from current node's dual bound to primal bound compared
283 * to best node's dual bound for separating knapsack cardinality cuts */
284 SCIP_Real mingainpernmincomp; /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise comparison round */
285 SCIP_Real maxeasyactivitydelta;/**< maximum activity delta to run easy propagation on linear constraint
286 * (faster, but numerically less stable) */
287 int linconsupgradessize;/**< size of linconsupgrade array */
288 int nlinconsupgrades; /**< number of linear constraint upgrade methods */
289 int tightenboundsfreq; /**< multiplier on propagation frequency, how often the bounds are tightened */
290 int maxrounds; /**< maximal number of separation rounds per node (-1: unlimited) */
291 int maxroundsroot; /**< maximal number of separation rounds in the root node (-1: unlimited) */
292 int maxsepacuts; /**< maximal number of cuts separated per separation round */
293 int maxsepacutsroot; /**< maximal number of cuts separated per separation round in root node */
294 int nmincomparisons; /**< number for minimal pairwise presolving comparisons */
295 int naddconss; /**< number of added constraints */
296 SCIP_Bool presolpairwise; /**< should pairwise constraint comparison be performed in presolving? */
297 SCIP_Bool presolusehashing; /**< should hash table be used for detecting redundant constraints in advance */
298 SCIP_Bool separateall; /**< should all constraints be subject to cardinality cut generation instead of only
299 * the ones with non-zero dual value? */
300 SCIP_Bool aggregatevariables; /**< should presolving search for redundant variables in equations */
301 SCIP_Bool simplifyinequalities;/**< should presolving try to cancel down or delete coefficients in inequalities */
302 SCIP_Bool dualpresolving; /**< should dual presolving steps be performed? */
303 SCIP_Bool singletonstuffing; /**< should stuffing of singleton continuous variables be performed? */
304 SCIP_Bool singlevarstuffing; /**< should single variable stuffing be performed, which tries to fulfill
305 * constraints using the cheapest variable? */
306 SCIP_Bool sortvars; /**< should binary variables be sorted for faster propagation? */
307 SCIP_Bool checkrelmaxabs; /**< should the violation for a constraint with side 0.0 be checked relative
308 * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
309 SCIP_Bool detectcutoffbound; /**< should presolving try to detect constraints parallel to the objective
310 * function defining an upper bound and prevent these constraints from
311 * entering the LP */
312 SCIP_Bool detectlowerbound; /**< should presolving try to detect constraints parallel to the objective
313 * function defining a lower bound and prevent these constraints from
314 * entering the LP */
315 SCIP_Bool detectpartialobjective;/**< should presolving try to detect subsets of constraints parallel to
316 * the objective function */
317 SCIP_Bool rangedrowpropagation;/**< should presolving and propagation try to improve bounds, detect
318 * infeasibility, and extract sub-constraints from ranged rows and
319 * equations */
320 SCIP_Bool rangedrowartcons; /**< should presolving and propagation extract sub-constraints from ranged rows and equations?*/
321 int rangedrowmaxdepth; /**< maximum depth to apply ranged row propagation */
322 int rangedrowfreq; /**< frequency for applying ranged row propagation */
323 SCIP_Bool multaggrremove; /**< should multi-aggregations only be performed if the constraint can be
324 * removed afterwards? */
325 SCIP_Real maxmultaggrquot; /**< maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation */
326 SCIP_Real maxdualmultaggrquot;/**< maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation */
327 SCIP_Bool extractcliques; /**< should cliques be extracted? */
328};
329
330/** linear constraint update method */
332{
333 SCIP_DECL_LINCONSUPGD((*linconsupgd)); /**< method to call for upgrading linear constraint */
334 int priority; /**< priority of upgrading method */
335 SCIP_Bool active; /**< is upgrading enabled */
336};
337
338
339/*
340 * Propagation rules
341 */
342
344{
345 PROPRULE_1_RHS = 1, /**< activity residuals of all other variables tighten bounds of single
346 * variable due to the right hand side of the inequality */
347 PROPRULE_1_LHS = 2, /**< activity residuals of all other variables tighten bounds of single
348 * variable due to the left hand side of the inequality */
349 PROPRULE_1_RANGEDROW = 3, /**< fixed variables and gcd of all left variables tighten bounds of a
350 * single variable in this reanged row */
351 PROPRULE_INVALID = 0 /**< propagation was applied without a specific propagation rule */
353typedef enum Proprule PROPRULE;
354
355/** inference information */
356struct InferInfo
357{
358 union
359 {
360 struct
361 {
362 unsigned int proprule:8; /**< propagation rule that was applied */
363 unsigned int pos:24; /**< variable position, the propagation rule was applied at */
364 } asbits;
365 int asint; /**< inference information as a single int value */
366 } val;
367};
368typedef struct InferInfo INFERINFO;
369
370/** converts an integer into an inference information */
371static
373 int i /**< integer to convert */
374 )
375{
376 INFERINFO inferinfo;
377
378 inferinfo.val.asint = i;
379
380 return inferinfo;
381}
382
383/** converts an inference information into an int */
384static
386 INFERINFO inferinfo /**< inference information to convert */
387 )
388{
389 return inferinfo.val.asint;
390}
391
392/** returns the propagation rule stored in the inference information */
393static
395 INFERINFO inferinfo /**< inference information to convert */
396 )
397{
398 return (int) inferinfo.val.asbits.proprule;
399}
400
401/** returns the position stored in the inference information */
402static
404 INFERINFO inferinfo /**< inference information to convert */
405 )
406{
407 return (int) inferinfo.val.asbits.pos;
408}
409
410/** constructs an inference information out of a propagation rule and a position number */
411static
413 PROPRULE proprule, /**< propagation rule that deduced the value */
414 int pos /**< variable position, the propagation rule was applied at */
415 )
416{
417 INFERINFO inferinfo;
418
419 assert(pos >= 0);
420 /* in the inferinfo struct only 24 bits for 'pos' are reserved */
421 assert(pos < (1<<24));
422
423 inferinfo.val.asbits.proprule = (unsigned int) proprule; /*lint !e641*/
424 inferinfo.val.asbits.pos = (unsigned int) pos; /*lint !e732*/
425
426 return inferinfo;
427}
428
429/** constructs an inference information out of a propagation rule and a position number, returns info as int */
430static
432 PROPRULE proprule, /**< propagation rule that deduced the value */
433 int pos /**< variable position, the propagation rule was applied at */
434 )
435{
436 return inferInfoToInt(getInferInfo(proprule, pos));
437}
438
439
440/*
441 * memory growing methods for dynamically allocated arrays
442 */
443
444/** ensures, that linconsupgrades array can store at least num entries */
445static
447 SCIP* scip, /**< SCIP data structure */
448 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
449 int num /**< minimum number of entries to store */
450 )
451{
452 assert(scip != NULL);
453 assert(conshdlrdata != NULL);
454 assert(conshdlrdata->nlinconsupgrades <= conshdlrdata->linconsupgradessize);
455
456 if( num > conshdlrdata->linconsupgradessize )
457 {
458 int newsize;
459
461 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &conshdlrdata->linconsupgrades, conshdlrdata->linconsupgradessize, newsize) );
462 conshdlrdata->linconsupgradessize = newsize;
463 }
464 assert(num <= conshdlrdata->linconsupgradessize);
465
466 return SCIP_OKAY;
467}
468
469/** ensures, that vars and vals arrays can store at least num entries */
470static
472 SCIP* scip, /**< SCIP data structure */
473 SCIP_CONSDATA* consdata, /**< linear constraint data */
474 int num /**< minimum number of entries to store */
475 )
476{
477 assert(scip != NULL);
478 assert(consdata != NULL);
479 assert(consdata->nvars <= consdata->varssize);
480
481 if( num > consdata->varssize )
482 {
483 int newsize;
484
486 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
487 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vals, consdata->varssize, newsize) );
488 if( consdata->eventdata != NULL )
489 {
490 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize, newsize) );
491 }
492 consdata->varssize = newsize;
493 }
494 assert(num <= consdata->varssize);
495
496 return SCIP_OKAY;
497}
498
499
500/*
501 * local methods for managing linear constraint update methods
502 */
503
504/** creates a linear constraint upgrade data object */
505static
507 SCIP* scip, /**< SCIP data structure */
508 SCIP_LINCONSUPGRADE** linconsupgrade, /**< pointer to store the linear constraint upgrade */
509 SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
510 int priority /**< priority of upgrading method */
511 )
512{
513 assert(scip != NULL);
516
518 (*linconsupgrade)->linconsupgd = linconsupgd;
519 (*linconsupgrade)->priority = priority;
520 (*linconsupgrade)->active = TRUE;
521
522 return SCIP_OKAY;
523}
524
525/** frees a linear constraint upgrade data object */
526static
528 SCIP* scip, /**< SCIP data structure */
529 SCIP_LINCONSUPGRADE** linconsupgrade /**< pointer to the linear constraint upgrade */
530 )
531{
532 assert(scip != NULL);
535
537}
538
539/** creates constraint handler data for linear constraint handler */
540static
542 SCIP* scip, /**< SCIP data structure */
543 SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
544 SCIP_EVENTHDLR* eventhdlr /**< event handler */
545 )
546{
547 assert(scip != NULL);
548 assert(conshdlrdata != NULL);
549 assert(eventhdlr != NULL);
550
551 SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
552 (*conshdlrdata)->linconsupgrades = NULL;
553 (*conshdlrdata)->linconsupgradessize = 0;
554 (*conshdlrdata)->nlinconsupgrades = 0;
555 (*conshdlrdata)->naddconss = 0;
556
557 /* set event handler for updating linear constraint activity bounds */
558 (*conshdlrdata)->eventhdlr = eventhdlr;
559
560 return SCIP_OKAY;
561}
562
563/** frees constraint handler data for linear constraint handler */
564static
566 SCIP* scip, /**< SCIP data structure */
567 SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
568 )
569{
570 int i;
571
572 assert(scip != NULL);
573 assert(conshdlrdata != NULL);
574 assert(*conshdlrdata != NULL);
575
576 for( i = 0; i < (*conshdlrdata)->nlinconsupgrades; ++i )
577 {
578 linconsupgradeFree(scip, &(*conshdlrdata)->linconsupgrades[i]);
579 }
580 SCIPfreeBlockMemoryArrayNull(scip, &(*conshdlrdata)->linconsupgrades, (*conshdlrdata)->linconsupgradessize);
581
582 SCIPfreeBlockMemory(scip, conshdlrdata);
583}
584
585/** creates a linear constraint upgrade data object */
586static
588 SCIP* scip, /**< SCIP data structure */
589 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
590 SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
591 const char* conshdlrname /**< name of the constraint handler */
592 )
593{
594 int i;
595
596 assert(scip != NULL);
597 assert(conshdlrdata != NULL);
600
601 for( i = conshdlrdata->nlinconsupgrades - 1; i >= 0; --i )
602 {
603 if( conshdlrdata->linconsupgrades[i]->linconsupgd == linconsupgd )
604 {
605#ifdef SCIP_DEBUG
606 SCIPwarningMessage(scip, "Try to add already known upgrade message for constraint handler %s.\n", conshdlrname);
607#endif
608 return TRUE;
609 }
610 }
611
612 return FALSE;
613}
614
615/** adds a linear constraint update method to the constraint handler's data */
616static
618 SCIP* scip, /**< SCIP data structure */
619 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
620 SCIP_LINCONSUPGRADE* linconsupgrade /**< linear constraint upgrade method */
621 )
622{
623 int i;
624
625 assert(scip != NULL);
626 assert(conshdlrdata != NULL);
628
629 SCIP_CALL( conshdlrdataEnsureLinconsupgradesSize(scip, conshdlrdata, conshdlrdata->nlinconsupgrades+1) );
630
631 for( i = conshdlrdata->nlinconsupgrades;
632 i > 0 && conshdlrdata->linconsupgrades[i-1]->priority < linconsupgrade->priority; --i )
633 {
634 conshdlrdata->linconsupgrades[i] = conshdlrdata->linconsupgrades[i-1];
635 }
636 assert(0 <= i && i <= conshdlrdata->nlinconsupgrades);
637 conshdlrdata->linconsupgrades[i] = linconsupgrade;
638 conshdlrdata->nlinconsupgrades++;
639
640 return SCIP_OKAY;
641}
642
643/*
644 * local methods
645 */
646
647/** installs rounding locks for the given variable associated to the given coefficient in the linear constraint */
648static
650 SCIP* scip, /**< SCIP data structure */
651 SCIP_CONS* cons, /**< linear constraint */
652 SCIP_VAR* var, /**< variable of constraint entry */
653 SCIP_Real val /**< coefficient of constraint entry */
654 )
655{
656 SCIP_CONSDATA* consdata;
657
658 assert(scip != NULL);
659 assert(cons != NULL);
660 assert(var != NULL);
661
662 consdata = SCIPconsGetData(cons);
663 assert(consdata != NULL);
664 assert(!SCIPisZero(scip, val));
665
666 if( SCIPisPositive(scip, val) )
667 {
669 !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
670 }
671 else
672 {
674 !SCIPisInfinity(scip, consdata->rhs), !SCIPisInfinity(scip, -consdata->lhs)) );
675 }
676
677 return SCIP_OKAY;
678}
679
680/** removes rounding locks for the given variable associated to the given coefficient in the linear constraint */
681static
683 SCIP* scip, /**< SCIP data structure */
684 SCIP_CONS* cons, /**< linear constraint */
685 SCIP_VAR* var, /**< variable of constraint entry */
686 SCIP_Real val /**< coefficient of constraint entry */
687 )
688{
689 SCIP_CONSDATA* consdata;
690
691 assert(scip != NULL);
692 assert(cons != NULL);
693 assert(var != NULL);
694
695 consdata = SCIPconsGetData(cons);
696 assert(consdata != NULL);
697 assert(!SCIPisZero(scip, val));
698
699 if( SCIPisPositive(scip, val) )
700 {
701 SCIP_CALL( SCIPunlockVarCons(scip, var, cons, !SCIPisInfinity(scip, -consdata->lhs),
702 !SCIPisInfinity(scip, consdata->rhs)) );
703 }
704 else
705 {
706 SCIP_CALL( SCIPunlockVarCons(scip, var, cons, !SCIPisInfinity(scip, consdata->rhs),
707 !SCIPisInfinity(scip, -consdata->lhs)) );
708 }
709
710 return SCIP_OKAY;
711}
712
713/** creates event data for variable at given position, and catches events */
714/**! [SnippetDebugAssertions] */
715static
717 SCIP* scip, /**< SCIP data structure */
718 SCIP_CONS* cons, /**< linear constraint */
719 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
720 int pos /**< array position of variable to catch bound change events for */
721 )
722{
723 SCIP_CONSDATA* consdata;
724 assert(scip != NULL);
725 assert(cons != NULL);
726 assert(eventhdlr != NULL);
727
728 consdata = SCIPconsGetData(cons);
729 assert(consdata != NULL);
730
731 assert(0 <= pos && pos < consdata->nvars);
732 assert(consdata->vars != NULL);
733 assert(consdata->vars[pos] != NULL);
734 assert(SCIPvarIsTransformed(consdata->vars[pos]));
735 assert(consdata->eventdata != NULL);
736 assert(consdata->eventdata[pos] == NULL);
737
738 SCIP_CALL( SCIPallocBlockMemory(scip, &(consdata->eventdata[pos])) ); /*lint !e866*/
739 consdata->eventdata[pos]->cons = cons;
740 consdata->eventdata[pos]->varpos = pos;
741
742 SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[pos],
745 eventhdlr, consdata->eventdata[pos], &consdata->eventdata[pos]->filterpos) );
746
747 consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(consdata->vars[pos]);
748
749 return SCIP_OKAY;
750}
751/**! [SnippetDebugAssertions] */
752
753/** deletes event data for variable at given position, and drops events */
754static
756 SCIP* scip, /**< SCIP data structure */
757 SCIP_CONS* cons, /**< linear constraint */
758 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
759 int pos /**< array position of variable to catch bound change events for */
760 )
761{
762 SCIP_CONSDATA* consdata;
763 assert(scip != NULL);
764 assert(cons != NULL);
765 assert(eventhdlr != NULL);
766
767 consdata = SCIPconsGetData(cons);
768 assert(consdata != NULL);
769
770 assert(0 <= pos && pos < consdata->nvars);
771 assert(consdata->vars[pos] != NULL);
772 assert(consdata->eventdata != NULL);
773 assert(consdata->eventdata[pos] != NULL);
774 assert(consdata->eventdata[pos]->cons == cons);
775 assert(consdata->eventdata[pos]->varpos == pos);
776
777 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[pos],
780 eventhdlr, consdata->eventdata[pos], consdata->eventdata[pos]->filterpos) );
781
782 SCIPfreeBlockMemory(scip, &consdata->eventdata[pos]); /*lint !e866*/
783
784 return SCIP_OKAY;
785}
786
787/** catches bound change events for all variables in transformed linear constraint */
788static
790 SCIP* scip, /**< SCIP data structure */
791 SCIP_CONS* cons, /**< linear constraint */
792 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
793 )
794{
795 SCIP_CONSDATA* consdata;
796 int i;
797
798 assert(scip != NULL);
799 assert(cons != NULL);
800
801 consdata = SCIPconsGetData(cons);
802 assert(consdata != NULL);
803 assert(consdata->eventdata == NULL);
804
805 /* allocate eventdata array */
806 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize) );
807 assert(consdata->eventdata != NULL);
808 BMSclearMemoryArray(consdata->eventdata, consdata->nvars);
809
810 /* catch event for every single variable */
811 for( i = 0; i < consdata->nvars; ++i )
812 {
813 SCIP_CALL( consCatchEvent(scip, cons, eventhdlr, i) );
814 }
815
816 return SCIP_OKAY;
817}
818
819/** drops bound change events for all variables in transformed linear constraint */
820static
822 SCIP* scip, /**< SCIP data structure */
823 SCIP_CONS* cons, /**< linear constraint */
824 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
825 )
826{
827 SCIP_CONSDATA* consdata;
828 int i;
829
830 assert(scip != NULL);
831 assert(cons != NULL);
832
833 consdata = SCIPconsGetData(cons);
834 assert(consdata != NULL);
835 assert(consdata->eventdata != NULL);
836
837 /* drop event of every single variable */
838 for( i = consdata->nvars - 1; i >= 0; --i )
839 {
840 SCIP_CALL( consDropEvent(scip, cons, eventhdlr, i) );
841 }
842
843 /* free eventdata array */
844 SCIPfreeBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize);
845 assert(consdata->eventdata == NULL);
846
847 return SCIP_OKAY;
848}
849
850/** creates a linear constraint data */
851static
853 SCIP* scip, /**< SCIP data structure */
854 SCIP_CONSDATA** consdata, /**< pointer to linear constraint data */
855 int nvars, /**< number of nonzeros in the constraint */
856 SCIP_VAR** vars, /**< array with variables of constraint entries */
857 SCIP_Real* vals, /**< array with coefficients of constraint entries */
858 SCIP_Real lhs, /**< left hand side of row */
859 SCIP_Real rhs /**< right hand side of row */
860 )
861{
862 int v;
863 SCIP_Real constant;
864
865 assert(scip != NULL);
866 assert(consdata != NULL);
867 assert(nvars == 0 || vars != NULL);
868 assert(nvars == 0 || vals != NULL);
869
870 if( SCIPisInfinity(scip, rhs) )
871 rhs = SCIPinfinity(scip);
872 else if( SCIPisInfinity(scip, -rhs) )
873 rhs = -SCIPinfinity(scip);
874
875 if( SCIPisInfinity(scip, -lhs) )
876 lhs = -SCIPinfinity(scip);
877 else if( SCIPisInfinity(scip, lhs) )
878 lhs = SCIPinfinity(scip);
879
880 if( SCIPisGT(scip, lhs, rhs) )
881 {
882 SCIPwarningMessage(scip, "left hand side of linear constraint greater than right hand side\n");
883 SCIPwarningMessage(scip, " -> lhs=%g, rhs=%g\n", lhs, rhs);
884 }
885
886 SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
887
888 (*consdata)->varssize = 0;
889 (*consdata)->nvars = nvars;
890 (*consdata)->hascontvar = FALSE;
891 (*consdata)->hasnonbinvar = FALSE;
892 (*consdata)->hasnonbinvalid = TRUE;
893 (*consdata)->vars = NULL;
894 (*consdata)->vals = NULL;
895
896 constant = 0.0;
897 if( nvars > 0 )
898 {
899 int k;
900
902 SCIP_Real* valsbuffer;
903
904 /* copy variables into temporary buffer */
907 k = 0;
908
909 /* loop over variables and sort out fixed ones */
910 for( v = 0; v < nvars; ++v )
911 {
912 SCIP_VAR* var;
913 SCIP_Real val;
914
915 var = vars[v];
916 val = vals[v];
917
918 assert(var != NULL);
919 if( !SCIPisZero(scip, val) )
920 {
921 /* treat fixed variable as a constant if problem compression is enabled */
923 {
924 constant += SCIPvarGetLbGlobal(var) * val;
925 }
926 else
927 {
928 varsbuffer[k] = var;
929 valsbuffer[k] = val;
930 k++;
931
932 /* update hascontvar and hasnonbinvar flags */
933 if( !(*consdata)->hascontvar )
934 {
936
937 if( vartype != SCIP_VARTYPE_BINARY )
938 {
939 (*consdata)->hasnonbinvar = TRUE;
940
941 if( vartype == SCIP_VARTYPE_CONTINUOUS )
942 (*consdata)->hascontvar = TRUE;
943 }
944 }
945 }
946 }
947 }
948 (*consdata)->nvars = k;
949
950 if( k > 0 )
951 {
952 /* copy the possibly reduced buffer arrays into block */
953 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, varsbuffer, k) );
954 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vals, valsbuffer, k) );
955 (*consdata)->varssize = k;
956 }
957 /* free temporary buffer */
960 }
961
962 (*consdata)->eventdata = NULL;
963
964 /* due to compressed copying, we may have fixed variables contributing to the left and right hand side */
965 if( !SCIPisZero(scip, constant) )
966 {
967 if( !SCIPisInfinity(scip, REALABS(lhs)) )
968 lhs -= constant;
969
970 if( !SCIPisInfinity(scip, REALABS(rhs)) )
971 rhs -= constant;
972 }
973
974 (*consdata)->row = NULL;
975 (*consdata)->nlrow = NULL;
976 (*consdata)->lhs = lhs;
977 (*consdata)->rhs = rhs;
978 (*consdata)->maxabsval = SCIP_INVALID;
979 (*consdata)->minabsval = SCIP_INVALID;
980 QUAD_ASSIGN((*consdata)->minactivity, SCIP_INVALID);
981 QUAD_ASSIGN((*consdata)->maxactivity, SCIP_INVALID);
982 (*consdata)->lastminactivity = SCIP_INVALID;
983 (*consdata)->lastmaxactivity = SCIP_INVALID;
984 (*consdata)->maxactdelta = SCIP_INVALID;
985 (*consdata)->maxactdeltavar = NULL;
986 (*consdata)->minactivityneginf = -1;
987 (*consdata)->minactivityposinf = -1;
988 (*consdata)->maxactivityneginf = -1;
989 (*consdata)->maxactivityposinf = -1;
990 (*consdata)->minactivityneghuge = -1;
991 (*consdata)->minactivityposhuge = -1;
992 (*consdata)->maxactivityneghuge = -1;
993 (*consdata)->maxactivityposhuge = -1;
994 QUAD_ASSIGN((*consdata)->glbminactivity, SCIP_INVALID);
995 QUAD_ASSIGN((*consdata)->glbmaxactivity, SCIP_INVALID);
996 (*consdata)->lastglbminactivity = SCIP_INVALID;
997 (*consdata)->lastglbmaxactivity = SCIP_INVALID;
998 (*consdata)->glbminactivityneginf = -1;
999 (*consdata)->glbminactivityposinf = -1;
1000 (*consdata)->glbmaxactivityneginf = -1;
1001 (*consdata)->glbmaxactivityposinf = -1;
1002 (*consdata)->glbminactivityneghuge = -1;
1003 (*consdata)->glbminactivityposhuge = -1;
1004 (*consdata)->glbmaxactivityneghuge = -1;
1005 (*consdata)->glbmaxactivityposhuge = -1;
1006 (*consdata)->possignature = 0;
1007 (*consdata)->negsignature = 0;
1008 (*consdata)->validmaxabsval = FALSE;
1009 (*consdata)->validminabsval = FALSE;
1010 (*consdata)->validactivities = FALSE;
1011 (*consdata)->validminact = FALSE;
1012 (*consdata)->validmaxact = FALSE;
1013 (*consdata)->validglbminact = FALSE;
1014 (*consdata)->validglbmaxact = FALSE;
1015 (*consdata)->boundstightened = 0;
1016 (*consdata)->presolved = FALSE;
1017 (*consdata)->removedfixings = FALSE;
1018 (*consdata)->validsignature = FALSE;
1019 (*consdata)->changed = TRUE;
1020 (*consdata)->normalized = FALSE;
1021 (*consdata)->upgradetried = FALSE;
1022 (*consdata)->upgraded = FALSE;
1023 (*consdata)->indexsorted = (nvars <= 1);
1024 (*consdata)->merged = (nvars <= 1);
1025 (*consdata)->cliquesadded = FALSE;
1026 (*consdata)->implsadded = FALSE;
1027 (*consdata)->coefsorted = FALSE;
1028 (*consdata)->nbinvars = -1;
1029 (*consdata)->varsdeleted = FALSE;
1030 (*consdata)->rangedrowpropagated = 0;
1031 (*consdata)->checkabsolute = FALSE;
1032
1033 if( SCIPisTransformed(scip) )
1034 {
1035 /* get transformed variables */
1036 SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
1037 }
1038
1039 /* capture variables */
1040 for( v = 0; v < (*consdata)->nvars; v++ )
1041 {
1042 /* likely implies a deleted variable */
1043 if( (*consdata)->vars[v] == NULL )
1044 {
1045 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
1046 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize);
1047 SCIPfreeBlockMemory(scip, consdata);
1048 return SCIP_INVALIDDATA;
1049 }
1050
1051 assert(!SCIPisZero(scip, (*consdata)->vals[v]));
1052 SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
1053 }
1054
1055 return SCIP_OKAY;
1056}
1057
1058/** frees a linear constraint data */
1059static
1061 SCIP* scip, /**< SCIP data structure */
1062 SCIP_CONSDATA** consdata /**< pointer to linear constraint data */
1063 )
1064{
1065 int v;
1066
1067 assert(scip != NULL);
1068 assert(consdata != NULL);
1069 assert(*consdata != NULL);
1070 assert((*consdata)->varssize >= 0);
1071
1072 /* release the row */
1073 if( (*consdata)->row != NULL )
1074 {
1075 SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) );
1076 }
1077
1078 /* release the nlrow */
1079 if( (*consdata)->nlrow != NULL )
1080 {
1081 SCIP_CALL( SCIPreleaseNlRow(scip, &(*consdata)->nlrow) );
1082 }
1083
1084 /* release variables */
1085 for( v = 0; v < (*consdata)->nvars; v++ )
1086 {
1087 assert((*consdata)->vars[v] != NULL);
1088 assert(!SCIPisZero(scip, (*consdata)->vals[v]));
1089 SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->vars[v])) );
1090 }
1091
1092 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
1093 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize);
1094 SCIPfreeBlockMemory(scip, consdata);
1095
1096 return SCIP_OKAY;
1097}
1098
1099/** prints linear constraint in CIP format to file stream */
1100static
1102 SCIP* scip, /**< SCIP data structure */
1103 SCIP_CONSDATA* consdata, /**< linear constraint data */
1104 FILE* file /**< output file (or NULL for standard output) */
1105 )
1106{
1107 assert(scip != NULL);
1108 assert(consdata != NULL);
1109
1110 /* print left hand side for ranged rows */
1111 if( !SCIPisInfinity(scip, -consdata->lhs)
1112 && !SCIPisInfinity(scip, consdata->rhs)
1113 && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1114 SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
1115
1116 /* print coefficients and variables */
1117 if( consdata->nvars == 0 )
1118 SCIPinfoMessage(scip, file, "0");
1119 else
1120 {
1121 /* post linear sum of the linear constraint */
1122 SCIP_CALL( SCIPwriteVarsLinearsum(scip, file, consdata->vars, consdata->vals, consdata->nvars, TRUE) );
1123 }
1124
1125 /* print right hand side */
1126 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1127 SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
1128 else if( !SCIPisInfinity(scip, consdata->rhs) )
1129 SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
1130 else if( !SCIPisInfinity(scip, -consdata->lhs) )
1131 SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
1132 else
1133 SCIPinfoMessage(scip, file, " [free]");
1134
1135 return SCIP_OKAY;
1136}
1137
1138/** prints linear constraint and contained solution values of variables to file stream */
1139static
1141 SCIP* scip, /**< SCIP data structure */
1142 SCIP_CONS* cons, /**< linear constraint */
1143 SCIP_SOL* sol, /**< solution to print */
1144 FILE* file /**< output file (or NULL for standard output) */
1145 )
1146{
1147 SCIP_CONSDATA* consdata;
1148
1149 assert(scip != NULL);
1150 assert(cons != NULL);
1151
1152 consdata = SCIPconsGetData(cons);
1153 assert(consdata != NULL);
1154
1156
1157 /* print left hand side for ranged rows */
1158 if( !SCIPisInfinity(scip, -consdata->lhs)
1159 && !SCIPisInfinity(scip, consdata->rhs)
1160 && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1161 SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
1162
1163 /* print coefficients and variables */
1164 if( consdata->nvars == 0 )
1165 SCIPinfoMessage(scip, file, "0");
1166 else
1167 {
1168 int v;
1169
1170 /* post linear sum of the linear constraint */
1171 for( v = 0; v < consdata->nvars; ++v )
1172 {
1173 if( consdata->vals != NULL )
1174 {
1175 if( consdata->vals[v] == 1.0 )
1176 {
1177 if( v > 0 )
1178 SCIPinfoMessage(scip, file, " +");
1179 }
1180 else if( consdata->vals[v] == -1.0 )
1181 SCIPinfoMessage(scip, file, " -");
1182 else
1183 SCIPinfoMessage(scip, file, " %+.9g", consdata->vals[v]);
1184 }
1185 else if( consdata->nvars > 0 )
1186 SCIPinfoMessage(scip, file, " +");
1187
1188 /* print variable name */
1189 SCIP_CALL( SCIPwriteVarName(scip, file, consdata->vars[v], TRUE) );
1190
1191 SCIPinfoMessage(scip, file, " (%+.9g)", SCIPgetSolVal(scip, sol, consdata->vars[v]));
1192 }
1193 }
1194
1195 /* print right hand side */
1196 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1197 SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
1198 else if( !SCIPisInfinity(scip, consdata->rhs) )
1199 SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
1200 else if( !SCIPisInfinity(scip, -consdata->lhs) )
1201 SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
1202 else
1203 SCIPinfoMessage(scip, file, " [free]");
1204
1205 SCIPinfoMessage(scip, file, ";\n");
1206
1207 return SCIP_OKAY;
1208}
1209
1210/** invalidates activity bounds, such that they are recalculated in next get */
1211static
1213 SCIP_CONSDATA* consdata /**< linear constraint */
1214 )
1215{
1216 assert(consdata != NULL);
1217
1218 consdata->validactivities = FALSE;
1219 consdata->validminact = FALSE;
1220 consdata->validmaxact = FALSE;
1221 consdata->validglbminact = FALSE;
1222 consdata->validglbmaxact = FALSE;
1223 consdata->validmaxabsval = FALSE;
1224 consdata->validminabsval = FALSE;
1225 consdata->hasnonbinvalid = FALSE;
1226 QUAD_ASSIGN(consdata->minactivity, SCIP_INVALID);
1227 QUAD_ASSIGN(consdata->maxactivity, SCIP_INVALID);
1228 consdata->lastminactivity = SCIP_INVALID;
1229 consdata->lastmaxactivity = SCIP_INVALID;
1230 consdata->maxabsval = SCIP_INVALID;
1231 consdata->minabsval = SCIP_INVALID;
1232 consdata->maxactdelta = SCIP_INVALID;
1233 consdata->maxactdeltavar = NULL;
1234 consdata->minactivityneginf = -1;
1235 consdata->minactivityposinf = -1;
1236 consdata->maxactivityneginf = -1;
1237 consdata->maxactivityposinf = -1;
1238 consdata->minactivityneghuge = -1;
1239 consdata->minactivityposhuge = -1;
1240 consdata->maxactivityneghuge = -1;
1241 consdata->maxactivityposhuge = -1;
1242 QUAD_ASSIGN(consdata->glbminactivity, SCIP_INVALID);
1243 QUAD_ASSIGN(consdata->glbmaxactivity, SCIP_INVALID);
1244 consdata->lastglbminactivity = SCIP_INVALID;
1245 consdata->lastglbmaxactivity = SCIP_INVALID;
1246 consdata->glbminactivityneginf = -1;
1247 consdata->glbminactivityposinf = -1;
1248 consdata->glbmaxactivityneginf = -1;
1249 consdata->glbmaxactivityposinf = -1;
1250 consdata->glbminactivityneghuge = -1;
1251 consdata->glbminactivityposhuge = -1;
1252 consdata->glbmaxactivityneghuge = -1;
1253 consdata->glbmaxactivityposhuge = -1;
1254}
1255
1256/** compute the pseudo activity of a constraint */
1257static
1259 SCIP* scip, /**< SCIP data structure */
1260 SCIP_CONSDATA* consdata /**< linear constraint data */
1261 )
1262{
1263 int i;
1266 SCIP_Real pseudoactivity;
1267 SCIP_Real bound;
1268 SCIP_Real val;
1269
1270 pseudoactivity = 0;
1273
1274 for( i = consdata->nvars - 1; i >= 0; --i )
1275 {
1276 val = consdata->vals[i];
1277 bound = (SCIPvarGetBestBoundType(consdata->vars[i]) == SCIP_BOUNDTYPE_LOWER) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1278 if( SCIPisInfinity(scip, bound) )
1279 {
1280 if( val > 0.0 )
1282 else
1284 }
1285 else
1286 {
1287 if( SCIPisInfinity(scip, -bound) )
1288 {
1289 if( val > 0.0 )
1291 else
1293 }
1294 else
1295 pseudoactivity += val * bound;
1296 }
1297 }
1298
1300 return SCIP_INVALID;
1301 else if( pseudoactivityneginf > 0 )
1302 return -SCIPinfinity(scip);
1303 else if( pseudoactivityposinf > 0 )
1304 return SCIPinfinity(scip);
1305
1306 return pseudoactivity;
1307}
1308
1309/** recompute the minactivity of a constraint */
1310static
1312 SCIP* scip, /**< SCIP data structure */
1313 SCIP_CONSDATA* consdata /**< linear constraint data */
1314 )
1315{
1316 int i;
1317 SCIP_Real bound;
1318
1319 QUAD_ASSIGN(consdata->minactivity, 0.0);
1320
1321 for( i = consdata->nvars - 1; i >= 0; --i )
1322 {
1323 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1325 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1326 SCIPquadprecSumQD(consdata->minactivity, consdata->minactivity, consdata->vals[i] * bound);
1327 }
1328
1329 /* the activity was just computed from scratch and is valid now */
1330 consdata->validminact = TRUE;
1331
1332 /* the activity was just computed from scratch, mark it to be reliable */
1333 consdata->lastminactivity = QUAD_TO_DBL(consdata->minactivity);
1334}
1335
1336/** recompute the maxactivity of a constraint */
1337static
1339 SCIP* scip, /**< SCIP data structure */
1340 SCIP_CONSDATA* consdata /**< linear constraint data */
1341 )
1342{
1343 int i;
1344 SCIP_Real bound;
1345
1346 QUAD_ASSIGN(consdata->maxactivity, 0.0);
1347
1348 for( i = consdata->nvars - 1; i >= 0; --i )
1349 {
1350 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbLocal(consdata->vars[i]) : SCIPvarGetLbLocal(consdata->vars[i]);
1352 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1353 SCIPquadprecSumQD(consdata->maxactivity, consdata->maxactivity, consdata->vals[i] * bound);
1354 }
1355
1356 /* the activity was just computed from scratch and is valid now */
1357 consdata->validmaxact = TRUE;
1358
1359 /* the activity was just computed from scratch, mark it to be reliable */
1360 consdata->lastmaxactivity = QUAD_TO_DBL(consdata->maxactivity);
1361}
1362
1363/** recompute the global minactivity of a constraint */
1364static
1366 SCIP* scip, /**< SCIP data structure */
1367 SCIP_CONSDATA* consdata /**< linear constraint data */
1368 )
1369{
1370 int i;
1371 SCIP_Real bound;
1372
1373 QUAD_ASSIGN(consdata->glbminactivity, 0.0);
1374
1375 for( i = consdata->nvars - 1; i >= 0; --i )
1376 {
1377 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbGlobal(consdata->vars[i]) : SCIPvarGetUbGlobal(consdata->vars[i]);
1379 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1380 SCIPquadprecSumQD(consdata->glbminactivity, consdata->glbminactivity, consdata->vals[i] * bound);
1381 }
1382
1383 /* the activity was just computed from scratch and is valid now */
1384 consdata->validglbminact = TRUE;
1385
1386 /* the activity was just computed from scratch, mark it to be reliable */
1387 consdata->lastglbminactivity = QUAD_TO_DBL(consdata->glbminactivity);
1388}
1389
1390/** recompute the global maxactivity of a constraint */
1391static
1393 SCIP* scip, /**< SCIP data structure */
1394 SCIP_CONSDATA* consdata /**< linear constraint data */
1395 )
1396{
1397 int i;
1398 SCIP_Real bound;
1399
1400 QUAD_ASSIGN(consdata->glbmaxactivity, 0.0);
1401
1402 for( i = consdata->nvars - 1; i >= 0; --i )
1403 {
1404 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbGlobal(consdata->vars[i]) : SCIPvarGetLbGlobal(consdata->vars[i]);
1406 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1407 SCIPquadprecSumQD(consdata->glbmaxactivity, consdata->glbmaxactivity, consdata->vals[i] * bound);
1408 }
1409
1410 /* the activity was just computed from scratch and is valid now */
1411 consdata->validglbmaxact = TRUE;
1412
1413 /* the activity was just computed from scratch, mark it to be reliable */
1414 consdata->lastglbmaxactivity = QUAD_TO_DBL(consdata->glbmaxactivity);
1415}
1416
1417/** calculates maximum absolute value of coefficients */
1418static
1420 SCIP_CONSDATA* consdata /**< linear constraint data */
1421 )
1422{
1423 SCIP_Real absval;
1424 int i;
1425
1426 assert(consdata != NULL);
1427 assert(!consdata->validmaxabsval);
1428 assert(consdata->maxabsval >= SCIP_INVALID);
1429
1430 consdata->validmaxabsval = TRUE;
1431 consdata->maxabsval = 0.0;
1432 for( i = 0; i < consdata->nvars; ++i )
1433 {
1434 absval = consdata->vals[i];
1436 if( absval > consdata->maxabsval )
1437 consdata->maxabsval = absval;
1438 }
1439}
1440
1441/** calculates minimum absolute value of coefficients */
1442static
1444 SCIP_CONSDATA* consdata /**< linear constraint data */
1445 )
1446{
1447 SCIP_Real absval;
1448 int i;
1449
1450 assert(consdata != NULL);
1451 assert(!consdata->validminabsval);
1452 assert(consdata->minabsval >= SCIP_INVALID);
1453
1454 consdata->validminabsval = TRUE;
1455
1456 if( consdata->nvars > 0 )
1457 consdata->minabsval = REALABS(consdata->vals[0]);
1458 else
1459 consdata->minabsval = 0.0;
1460
1461 for( i = 1; i < consdata->nvars; ++i )
1462 {
1463 absval = consdata->vals[i];
1465 if( absval < consdata->minabsval )
1466 consdata->minabsval = absval;
1467 }
1468}
1469
1470/** checks the type of all variables of the constraint and sets hasnonbinvar and hascontvar flags accordingly */
1471static
1473 SCIP_CONSDATA* consdata /**< linear constraint data */
1474 )
1475{
1476 int v;
1477
1478 assert(!consdata->hasnonbinvalid);
1479 consdata->hasnonbinvar = FALSE;
1480 consdata->hascontvar = FALSE;
1481
1482 for( v = consdata->nvars - 1; v >= 0; --v )
1483 {
1484 SCIP_VARTYPE vartype = SCIPvarGetType(consdata->vars[v]);
1485
1486 if( vartype != SCIP_VARTYPE_BINARY )
1487 {
1488 consdata->hasnonbinvar = TRUE;
1489
1490 if( vartype == SCIP_VARTYPE_CONTINUOUS )
1491 {
1492 consdata->hascontvar = TRUE;
1493 break;
1494 }
1495 }
1496 }
1497 assert(consdata->hascontvar || v < 0);
1498
1499 consdata->hasnonbinvalid = TRUE;
1500}
1501
1502
1503#ifdef CHECKMAXACTDELTA
1504/** checks that the stored maximal activity delta (if not invalid) is correct */
1505static
1507 SCIP* scip, /**< SCIP data structure */
1508 SCIP_CONSDATA* consdata /**< linear constraint data */
1509 )
1510{
1511 if( consdata->maxactdelta != SCIP_INVALID )
1512 {
1513 SCIP_Real maxactdelta = 0.0;
1514 SCIP_Real domain;
1515 SCIP_Real delta;
1516 SCIP_Real lb;
1517 SCIP_Real ub;
1518 int v;
1519
1520 for( v = consdata->nvars - 1; v >= 0; --v )
1521 {
1522 lb = SCIPvarGetLbLocal(consdata->vars[v]);
1523 ub = SCIPvarGetUbLocal(consdata->vars[v]);
1524
1525 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1526 {
1527 maxactdelta = SCIPinfinity(scip);
1528 break;
1529 }
1530
1531 domain = ub - lb;
1532 delta = REALABS(consdata->vals[v]) * domain;
1533
1534 if( delta > maxactdelta )
1535 {
1536 maxactdelta = delta;
1537 }
1538 }
1539 assert(SCIPisFeasEQ(scip, maxactdelta, consdata->maxactdelta));
1540 }
1541}
1542#else
1543#define checkMaxActivityDelta(scip, consdata) /**/
1544#endif
1545
1546/** recompute maximal activity contribution for a single variable */
1547static
1549 SCIP* scip, /**< SCIP data structure */
1550 SCIP_CONSDATA* consdata /**< linear constraint data */
1551 )
1552{
1553 SCIP_Real delta;
1554 int v;
1555
1556 consdata->maxactdelta = 0.0;
1557
1558 if( !consdata->hasnonbinvalid )
1559 consdataCheckNonbinvar(consdata);
1560
1561 /* easy case, the problem consists only of binary variables */
1562 if( !consdata->hasnonbinvar )
1563 {
1564 for( v = consdata->nvars - 1; v >= 0; --v )
1565 {
1566 if( SCIPvarGetLbLocal(consdata->vars[v]) < 0.5 && SCIPvarGetUbLocal(consdata->vars[v]) > 0.5 )
1567 {
1568 delta = REALABS(consdata->vals[v]);
1569
1570 if( delta > consdata->maxactdelta )
1571 {
1572 consdata->maxactdelta = delta;
1573 consdata->maxactdeltavar = consdata->vars[v];
1574 }
1575 }
1576 }
1577 return;
1578 }
1579
1580 for( v = consdata->nvars - 1; v >= 0; --v )
1581 {
1582 SCIP_Real domain;
1583 SCIP_Real lb;
1584 SCIP_Real ub;
1585
1586 lb = SCIPvarGetLbLocal(consdata->vars[v]);
1587 ub = SCIPvarGetUbLocal(consdata->vars[v]);
1588
1589 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1590 {
1591 consdata->maxactdelta = SCIPinfinity(scip);
1592 consdata->maxactdeltavar = consdata->vars[v];
1593 break;
1594 }
1595
1596 domain = ub - lb;
1597 delta = REALABS(consdata->vals[v]) * domain;
1598
1599 if( delta > consdata->maxactdelta )
1600 {
1601 consdata->maxactdelta = delta;
1602 consdata->maxactdeltavar = consdata->vars[v];
1603 }
1604 }
1605}
1606
1607
1608/** updates activities for a change in a bound */
1609static
1611 SCIP* scip, /**< SCIP data structure */
1612 SCIP_CONSDATA* consdata, /**< linear constraint data */
1613 SCIP_VAR* var, /**< variable that has been changed; can be NULL for global bound changes */
1614 SCIP_Real oldbound, /**< old bound of variable */
1615 SCIP_Real newbound, /**< new bound of variable */
1616 SCIP_Real val, /**< coefficient of constraint entry */
1617 SCIP_BOUNDTYPE boundtype, /**< type of the bound change */
1618 SCIP_Bool global, /**< is it a global or a local bound change? */
1619 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1620 )
1621{
1622 QUAD_MEMBER(SCIP_Real* activity);
1623 SCIP_Real* lastactivity;
1624 int* activityposinf;
1625 int* activityneginf;
1626 int* activityposhuge;
1627 int* activityneghuge;
1628 SCIP_Real oldcontribution;
1629 SCIP_Real newcontribution;
1630 SCIP_Real delta;
1631 SCIP_Bool validact;
1632 SCIP_Bool finitenewbound;
1633 SCIP_Bool hugevalnewcont;
1634
1635 assert(scip != NULL);
1636 assert(consdata != NULL);
1637 assert(global || (var != NULL));
1638 assert(consdata->validactivities);
1639 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
1640 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
1641 assert(consdata->lastminactivity < SCIP_INVALID);
1642 assert(consdata->lastmaxactivity < SCIP_INVALID);
1643 assert(consdata->minactivityneginf >= 0);
1644 assert(consdata->minactivityposinf >= 0);
1645 assert(consdata->maxactivityneginf >= 0);
1646 assert(consdata->maxactivityposinf >= 0);
1647 assert(consdata->minactivityneghuge >= 0);
1648 assert(consdata->minactivityposhuge >= 0);
1649 assert(consdata->maxactivityneghuge >= 0);
1650 assert(consdata->maxactivityposhuge >= 0);
1651 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
1652 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
1653 assert(consdata->lastglbminactivity < SCIP_INVALID);
1654 assert(consdata->lastglbmaxactivity < SCIP_INVALID);
1655 assert(consdata->glbminactivityneginf >= 0);
1656 assert(consdata->glbminactivityposinf >= 0);
1657 assert(consdata->glbmaxactivityneginf >= 0);
1658 assert(consdata->glbmaxactivityposinf >= 0);
1659 assert(consdata->glbminactivityneghuge >= 0);
1660 assert(consdata->glbminactivityposhuge >= 0);
1661 assert(consdata->glbmaxactivityneghuge >= 0);
1662 assert(consdata->glbmaxactivityposhuge >= 0);
1663
1664 delta = 0.0;
1665
1666 /* we are updating global activities */
1667 if( global )
1668 {
1669 /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1670 * lower bound + pos. coef: update minactivity
1671 * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1672 * upper bound + pos. coef: update maxactivity
1673 * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1674 */
1675 if( boundtype == SCIP_BOUNDTYPE_LOWER )
1676 {
1677 if( val > 0.0 )
1678 {
1679 QUAD_ASSIGN_Q(activity, &consdata->glbminactivity);
1680 lastactivity = &(consdata->lastglbminactivity);
1681 activityposinf = &(consdata->glbminactivityposinf);
1682 activityneginf = &(consdata->glbminactivityneginf);
1683 activityposhuge = &(consdata->glbminactivityposhuge);
1684 activityneghuge = &(consdata->glbminactivityneghuge);
1685 validact = consdata->validglbminact;
1686 }
1687 else
1688 {
1689 QUAD_ASSIGN_Q(activity, &consdata->glbmaxactivity);
1690 lastactivity = &(consdata->lastglbmaxactivity);
1691 activityposinf = &(consdata->glbmaxactivityneginf);
1692 activityneginf = &(consdata->glbmaxactivityposinf);
1693 activityposhuge = &(consdata->glbmaxactivityposhuge);
1694 activityneghuge = &(consdata->glbmaxactivityneghuge);
1695 validact = consdata->validglbmaxact;
1696 }
1697 }
1698 else
1699 {
1700 if( val > 0.0 )
1701 {
1702 QUAD_ASSIGN_Q(activity, &consdata->glbmaxactivity);
1703 lastactivity = &(consdata->lastglbmaxactivity);
1704 activityposinf = &(consdata->glbmaxactivityposinf);
1705 activityneginf = &(consdata->glbmaxactivityneginf);
1706 activityposhuge = &(consdata->glbmaxactivityposhuge);
1707 activityneghuge = &(consdata->glbmaxactivityneghuge);
1708 validact = consdata->validglbmaxact;
1709 }
1710 else
1711 {
1712 QUAD_ASSIGN_Q(activity, &consdata->glbminactivity);
1713 lastactivity = &(consdata->lastglbminactivity);
1714 activityposinf = &(consdata->glbminactivityneginf);
1715 activityneginf = &(consdata->glbminactivityposinf);
1716 activityposhuge = &(consdata->glbminactivityposhuge);
1717 activityneghuge = &(consdata->glbminactivityneghuge);
1718 validact = consdata->validglbminact;
1719 }
1720 }
1721 }
1722 /* we are updating local activities */
1723 else
1724 {
1725 /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1726 * lower bound + pos. coef: update minactivity
1727 * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1728 * upper bound + pos. coef: update maxactivity
1729 * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1730 */
1731 if( boundtype == SCIP_BOUNDTYPE_LOWER )
1732 {
1733 if( val > 0.0 )
1734 {
1735 QUAD_ASSIGN_Q(activity, &consdata->minactivity);
1736 lastactivity = &(consdata->lastminactivity);
1737 activityposinf = &(consdata->minactivityposinf);
1738 activityneginf = &(consdata->minactivityneginf);
1739 activityposhuge = &(consdata->minactivityposhuge);
1740 activityneghuge = &(consdata->minactivityneghuge);
1741 validact = consdata->validminact;
1742 }
1743 else
1744 {
1745 QUAD_ASSIGN_Q(activity, &consdata->maxactivity);
1746 lastactivity = &(consdata->lastmaxactivity);
1747 activityposinf = &(consdata->maxactivityneginf);
1748 activityneginf = &(consdata->maxactivityposinf);
1749 activityposhuge = &(consdata->maxactivityposhuge);
1750 activityneghuge = &(consdata->maxactivityneghuge);
1751 validact = consdata->validmaxact;
1752 }
1753 }
1754 else
1755 {
1756 if( val > 0.0 )
1757 {
1758 QUAD_ASSIGN_Q(activity, &consdata->maxactivity);
1759 lastactivity = &(consdata->lastmaxactivity);
1760 activityposinf = &(consdata->maxactivityposinf);
1761 activityneginf = &(consdata->maxactivityneginf);
1762 activityposhuge = &(consdata->maxactivityposhuge);
1763 activityneghuge = &(consdata->maxactivityneghuge);
1764 validact = consdata->validmaxact;
1765 }
1766 else
1767 {
1768 QUAD_ASSIGN_Q(activity, &consdata->minactivity);
1769 lastactivity = &(consdata->lastminactivity);
1770 activityposinf = &(consdata->minactivityneginf);
1771 activityneginf = &(consdata->minactivityposinf);
1772 activityposhuge = &(consdata->minactivityposhuge);
1773 activityneghuge = &(consdata->minactivityneghuge);
1774 validact = consdata->validminact;
1775 }
1776 }
1777 }
1778
1779 oldcontribution = val * oldbound;
1780 newcontribution = val * newbound;
1783
1784 if( SCIPisInfinity(scip, REALABS(oldbound)) )
1785 {
1786 /* old bound was +infinity */
1787 if( oldbound > 0.0 )
1788 {
1789 assert((*activityposinf) >= 1);
1790
1791 /* we only have to do something if the new bound is not again +infinity */
1792 if( finitenewbound || newbound < 0.0 )
1793 {
1794 /* decrease the counter for positive infinite contributions */
1795 (*activityposinf)--;
1796
1797 /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1798 if( !finitenewbound && newbound < 0.0 )
1799 (*activityneginf)++;
1800 else if( hugevalnewcont )
1801 {
1802 /* if the contribution of this variable is too large, increase the counter for huge values */
1803 if( newcontribution > 0.0 )
1804 (*activityposhuge)++;
1805 else
1806 (*activityneghuge)++;
1807 }
1808 /* "normal case": just add the contribution to the activity */
1809 else
1810 delta = newcontribution;
1811 }
1812 }
1813 /* old bound was -infinity */
1814 else
1815 {
1816 assert(oldbound < 0.0);
1817 assert((*activityneginf) >= 1);
1818
1819 /* we only have to do something ig the new bound is not again -infinity */
1820 if( finitenewbound || newbound > 0.0 )
1821 {
1822 /* decrease the counter for negative infinite contributions */
1823 (*activityneginf)--;
1824
1825 /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1826 if( !finitenewbound && newbound > 0.0 )
1827 (*activityposinf)++;
1828 else if( hugevalnewcont )
1829 {
1830 /* if the contribution of this variable is too large, increase the counter for huge values */
1831 if( newcontribution > 0.0 )
1832 (*activityposhuge)++;
1833 else
1834 (*activityneghuge)++;
1835 }
1836 /* "normal case": just add the contribution to the activity */
1837 else
1838 delta = newcontribution;
1839 }
1840 }
1841 }
1843 {
1844 /* old contribution was too large and positive */
1845 if( oldcontribution > 0.0 )
1846 {
1847 assert((*activityposhuge) >= 1);
1848
1849 /* decrease the counter for huge positive contributions; it might be increased again later,
1850 * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1851 */
1852 (*activityposhuge)--;
1853
1854 if( !finitenewbound )
1855 {
1856 /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1857 if( newbound > 0.0 )
1858 (*activityposinf)++;
1859 /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1860 else
1861 (*activityneginf)++;
1862 }
1863 else if( hugevalnewcont )
1864 {
1865 /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1866 if( newcontribution > 0.0 )
1867 (*activityposhuge)++;
1868 /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1869 else
1870 (*activityneghuge)++;
1871 }
1872 /* "normal case": just add the contribution to the activity */
1873 else
1874 delta = newcontribution;
1875 }
1876 /* old contribution was too large and negative */
1877 else
1878 {
1879 assert(oldcontribution < 0.0);
1880 assert((*activityneghuge) >= 1);
1881
1882 /* decrease the counter for huge negative contributions; it might be increased again later,
1883 * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1884 */
1885 (*activityneghuge)--;
1886
1887 if( !finitenewbound )
1888 {
1889 /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1890 if( newbound > 0.0 )
1891 (*activityposinf)++;
1892 /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1893 else
1894 (*activityneginf)++;
1895 }
1896 else if( hugevalnewcont )
1897 {
1898 /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1899 if( newcontribution > 0.0 )
1900 (*activityposhuge)++;
1901 /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1902 else
1903 (*activityneghuge)++;
1904 }
1905 /* "normal case": just add the contribution to the activity */
1906 else
1907 delta = newcontribution;
1908 }
1909 }
1910 /* old bound was finite and not too large */
1911 else
1912 {
1913 if( !finitenewbound )
1914 {
1915 /* if the new bound is +infinity, the old contribution has to be subtracted
1916 * and the counter for positive infinite contributions has to be increased
1917 */
1918 if( newbound > 0.0 )
1919 {
1920 (*activityposinf)++;
1921 delta = -oldcontribution;
1922 }
1923 /* if the new bound is -infinity, the old contribution has to be subtracted
1924 * and the counter for negative infinite contributions has to be increased
1925 */
1926 else
1927 {
1928 assert(newbound < 0.0 );
1929
1930 (*activityneginf)++;
1931 delta = -oldcontribution;
1932 }
1933 }
1934 /* if the contribution of this variable is too large, increase the counter for huge values */
1935 else if( hugevalnewcont )
1936 {
1937 if( newcontribution > 0.0 )
1938 {
1939 (*activityposhuge)++;
1940 delta = -oldcontribution;
1941 }
1942 else
1943 {
1944 (*activityneghuge)++;
1945 delta = -oldcontribution;
1946 }
1947 }
1948 /* "normal case": just update the activity */
1949 else
1951 }
1952
1953 /* update the activity, if the current value is valid and there was a change in the finite part */
1954 if( validact && (delta != 0.0) )
1955 {
1956 SCIP_Real curractivity;
1957
1958 /* if the absolute value of the activity is increased, this is regarded as reliable,
1959 * otherwise, we check whether we can still trust the updated value
1960 */
1961 SCIPquadprecSumQD(*activity, *activity, delta);
1962
1963 curractivity = QUAD_TO_DBL(*activity);
1965
1967 {
1968 (*lastactivity) = curractivity;
1969 }
1970 else
1971 {
1973 {
1974 SCIPdebugMsg(scip, "%s activity of linear constraint unreliable after update: %16.9g\n",
1975 (global ? "global " : ""), curractivity);
1976
1977 /* mark the activity that was just changed and is not reliable anymore to be invalid */
1978 if( global )
1979 {
1980 if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1981 consdata->validglbminact = FALSE;
1982 else
1983 consdata->validglbmaxact = FALSE;
1984 }
1985 else
1986 {
1987 if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1988 consdata->validminact = FALSE;
1989 else
1990 consdata->validmaxact = FALSE;
1991 }
1992 }
1993 }
1994 }
1995}
1996
1997/** updates minimum and maximum activity for a change in lower bound */
1998static
2000 SCIP* scip, /**< SCIP data structure */
2001 SCIP_CONSDATA* consdata, /**< linear constraint data */
2002 SCIP_VAR* var, /**< variable that has been changed */
2003 SCIP_Real oldlb, /**< old lower bound of variable */
2004 SCIP_Real newlb, /**< new lower bound of variable */
2005 SCIP_Real val, /**< coefficient of constraint entry */
2006 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2007 )
2008{
2009 assert(scip != NULL);
2010 assert(consdata != NULL);
2011 assert(var != NULL);
2012
2013 if( consdata->validactivities )
2014 {
2016
2017 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->minactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->minactivity)));
2018 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->maxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->maxactivity)));
2019 }
2020}
2021
2022/** updates minimum and maximum activity for a change in upper bound */
2023static
2025 SCIP* scip, /**< SCIP data structure */
2026 SCIP_CONSDATA* consdata, /**< linear constraint data */
2027 SCIP_VAR* var, /**< variable that has been changed */
2028 SCIP_Real oldub, /**< old upper bound of variable */
2029 SCIP_Real newub, /**< new upper bound of variable */
2030 SCIP_Real val, /**< coefficient of constraint entry */
2031 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2032 )
2033{
2034 assert(scip != NULL);
2035 assert(consdata != NULL);
2036 assert(var != NULL);
2037
2038 if( consdata->validactivities )
2039 {
2041
2042 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->minactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->minactivity)));
2043 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->maxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->maxactivity)));
2044 }
2045}
2046
2047/** updates minimum and maximum global activity for a change in the global lower bound */
2048static
2050 SCIP* scip, /**< SCIP data structure */
2051 SCIP_CONSDATA* consdata, /**< linear constraint data */
2052 SCIP_Real oldlb, /**< old lower bound of variable */
2053 SCIP_Real newlb, /**< new lower bound of variable */
2054 SCIP_Real val, /**< coefficient of constraint entry */
2055 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2056 )
2057{
2058 assert(scip != NULL);
2059 assert(consdata != NULL);
2060
2061 if( consdata->validactivities )
2062 {
2064
2065 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbminactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbminactivity)));
2066 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbmaxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbmaxactivity)));
2067 }
2068}
2069
2070/** updates minimum and maximum global activity for a change in global upper bound */
2071static
2073 SCIP* scip, /**< SCIP data structure */
2074 SCIP_CONSDATA* consdata, /**< linear constraint data */
2075 SCIP_Real oldub, /**< old upper bound of variable */
2076 SCIP_Real newub, /**< new upper bound of variable */
2077 SCIP_Real val, /**< coefficient of constraint entry */
2078 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2079 )
2080{
2081 assert(scip != NULL);
2082 assert(consdata != NULL);
2083
2084 if( consdata->validactivities )
2085 {
2087
2088 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbminactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbminactivity)));
2089 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbmaxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbmaxactivity)));
2090 }
2091}
2092
2093/** updates minimum and maximum activity and maximum absolute value for coefficient addition */
2094static
2096 SCIP* scip, /**< SCIP data structure */
2097 SCIP_CONSDATA* consdata, /**< linear constraint data */
2098 SCIP_VAR* var, /**< variable of constraint entry */
2099 SCIP_Real val, /**< coefficient of constraint entry */
2100 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2101 )
2102{
2103 assert(scip != NULL);
2104 assert(consdata != NULL);
2105 assert(var != NULL);
2106
2107 /* update maximum absolute value */
2108 if( consdata->validmaxabsval )
2109 {
2110 SCIP_Real absval;
2111
2112 assert(consdata->maxabsval < SCIP_INVALID);
2113
2114 absval = REALABS(val);
2115 consdata->maxabsval = MAX(consdata->maxabsval, absval);
2116 }
2117
2118 if( consdata->validminabsval )
2119 {
2120 SCIP_Real absval;
2121
2122 assert(consdata->minabsval < SCIP_INVALID);
2123
2124 absval = REALABS(val);
2125 consdata->minabsval = MIN(consdata->minabsval, absval);
2126 }
2127
2128 /* update minimal and maximal activity */
2129 if( consdata->validactivities )
2130 {
2131 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2132 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2133 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2134 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2135
2140 }
2141}
2142
2143/** updates minimum and maximum activity for coefficient deletion, invalidates maximum absolute value if necessary */
2144static
2146 SCIP* scip, /**< SCIP data structure */
2147 SCIP_CONSDATA* consdata, /**< linear constraint data */
2148 SCIP_VAR* var, /**< variable of constraint entry */
2149 SCIP_Real val, /**< coefficient of constraint entry */
2150 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2151 )
2152{
2153 assert(scip != NULL);
2154 assert(consdata != NULL);
2155 assert(var != NULL);
2156
2157 /* invalidate maximum absolute value, if this coefficient was the maximum */
2158 if( consdata->validmaxabsval )
2159 {
2160 SCIP_Real absval;
2161
2162 absval = REALABS(val);
2163
2164 if( SCIPisEQ(scip, absval, consdata->maxabsval) )
2165 {
2166 consdata->validmaxabsval = FALSE;
2167 consdata->maxabsval = SCIP_INVALID;
2168 }
2169 }
2170
2171 /* invalidate minimum absolute value, if this coefficient was the minimum */
2172 if( consdata->validminabsval )
2173 {
2174 SCIP_Real absval;
2175
2176 absval = REALABS(val);
2177
2178 if( SCIPisEQ(scip, absval, consdata->minabsval) )
2179 {
2180 consdata->validminabsval = FALSE;
2181 consdata->minabsval = SCIP_INVALID;
2182 }
2183 }
2184
2185 /* update minimal and maximal activity */
2186 if( consdata->validactivities )
2187 {
2188 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2189 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2190 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2191 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2192
2197 }
2198}
2199
2200/** updates minimum and maximum activity for coefficient change, invalidates maximum absolute value if necessary */
2201static
2203 SCIP* scip, /**< SCIP data structure */
2204 SCIP_CONSDATA* consdata, /**< linear constraint data */
2205 SCIP_VAR* var, /**< variable of constraint entry */
2206 SCIP_Real oldval, /**< old coefficient of constraint entry */
2207 SCIP_Real newval, /**< new coefficient of constraint entry */
2208 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2209 )
2210{
2211 assert(scip != NULL);
2212 assert(consdata != NULL);
2213 assert(var != NULL);
2214
2215 /* old zero coefficients should be handled by consdataUpdateAddCoef() */
2216 assert(!SCIPisZero(scip, oldval));
2217
2218 /* new zero coefficients should be handled by consdataUpdateDelCoef() */
2219 assert(!SCIPisZero(scip, newval));
2220
2221 /* update maximum absolute value */
2222 if( consdata->validmaxabsval )
2223 {
2224 SCIP_Real absval;
2225
2226 absval = REALABS(newval);
2227
2228 if( SCIPisGE(scip, absval, consdata->maxabsval) )
2229 {
2230 consdata->maxabsval = absval;
2231 }
2232 else
2233 {
2234 absval = REALABS(oldval);
2235
2236 /* invalidate maximum absolute value */
2237 if( SCIPisEQ(scip, absval, consdata->maxabsval) )
2238 {
2239 consdata->validmaxabsval = FALSE;
2240 consdata->maxabsval = SCIP_INVALID;
2241 }
2242 }
2243 }
2244
2245 /* update minimum absolute value */
2246 if( consdata->validminabsval )
2247 {
2248 SCIP_Real absval;
2249
2250 absval = REALABS(newval);
2251
2252 if( SCIPisLE(scip, absval, consdata->minabsval) )
2253 {
2254 consdata->minabsval = absval;
2255 }
2256 else
2257 {
2258 absval = REALABS(oldval);
2259
2260 /* invalidate minimum absolute value */
2261 if( SCIPisEQ(scip, absval, consdata->minabsval) )
2262 {
2263 consdata->validminabsval = FALSE;
2264 consdata->minabsval = SCIP_INVALID;
2265 }
2266 }
2267 }
2268
2269 /* update maximum activity delta */
2270 if( !SCIPisInfinity(scip, consdata->maxactdelta ) )
2271 {
2272 SCIP_Real domain;
2273 SCIP_Real delta;
2274
2277
2279 delta = REALABS(newval) * domain;
2280
2281 if( delta > consdata->maxactdelta )
2282 {
2283 consdata->maxactdelta = delta;
2284 consdata->maxactdeltavar = var;
2285 }
2286 else
2287 {
2288 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
2289 if( consdata->maxactdeltavar == var )
2290 consdata->maxactdelta = SCIP_INVALID;
2291 }
2292 }
2293
2294 /* @todo do something more clever here, e.g. if oldval * newval >= 0, do the update directly */
2295 consdataUpdateDelCoef(scip, consdata, var, oldval, checkreliability);
2296 consdataUpdateAddCoef(scip, consdata, var, newval, checkreliability);
2297}
2298
2299/** returns the maximum absolute value of all coefficients in the constraint */
2300static
2302 SCIP_CONSDATA* consdata /**< linear constraint data */
2303 )
2304{
2305 assert(consdata != NULL);
2306
2307 if( !consdata->validmaxabsval )
2308 consdataCalcMaxAbsval(consdata);
2309 assert(consdata->validmaxabsval);
2310 assert(consdata->maxabsval < SCIP_INVALID);
2311
2312 return consdata->maxabsval;
2313}
2314
2315/** returns the minimum absolute value of all coefficients in the constraint */
2316static
2318 SCIP_CONSDATA* consdata /**< linear constraint data */
2319 )
2320{
2321 assert(consdata != NULL);
2322
2323 if( !consdata->validminabsval )
2324 consdataCalcMinAbsval(consdata);
2325 assert(consdata->validminabsval);
2326 assert(consdata->minabsval < SCIP_INVALID);
2327
2328 return consdata->minabsval;
2329}
2330
2331/** calculates minimum and maximum local and global activity for constraint from scratch;
2332 * additionally recalculates maximum absolute value of coefficients
2333 */
2334static
2336 SCIP* scip, /**< SCIP data structure */
2337 SCIP_CONSDATA* consdata /**< linear constraint data */
2338 )
2339{
2340 int i;
2341
2342 assert(scip != NULL);
2343 assert(consdata != NULL);
2344 assert(!consdata->validactivities);
2345 assert(QUAD_TO_DBL(consdata->minactivity) >= SCIP_INVALID || consdata->validminact);
2346 assert(QUAD_TO_DBL(consdata->maxactivity) >= SCIP_INVALID || consdata->validmaxact);
2347 assert(QUAD_TO_DBL(consdata->glbminactivity) >= SCIP_INVALID || consdata->validglbminact);
2348 assert(QUAD_TO_DBL(consdata->glbmaxactivity) >= SCIP_INVALID || consdata->validglbmaxact);
2349
2350 consdata->validmaxabsval = TRUE;
2351 consdata->validminabsval = TRUE;
2352 consdata->validactivities = TRUE;
2353 consdata->validminact = TRUE;
2354 consdata->validmaxact = TRUE;
2355 consdata->validglbminact = TRUE;
2356 consdata->validglbmaxact = TRUE;
2357 consdata->maxabsval = 0.0;
2358 consdata->minabsval = (consdata->nvars == 0 ? 0.0 : REALABS(consdata->vals[0]));
2359 QUAD_ASSIGN(consdata->minactivity, 0.0);
2360 QUAD_ASSIGN(consdata->maxactivity, 0.0);
2361 consdata->lastminactivity = 0.0;
2362 consdata->lastmaxactivity = 0.0;
2363 consdata->minactivityneginf = 0;
2364 consdata->minactivityposinf = 0;
2365 consdata->maxactivityneginf = 0;
2366 consdata->maxactivityposinf = 0;
2367 consdata->minactivityneghuge = 0;
2368 consdata->minactivityposhuge = 0;
2369 consdata->maxactivityneghuge = 0;
2370 consdata->maxactivityposhuge = 0;
2371 QUAD_ASSIGN(consdata->glbminactivity, 0.0);
2372 QUAD_ASSIGN(consdata->glbmaxactivity, 0.0);
2373 consdata->lastglbminactivity = 0.0;
2374 consdata->lastglbmaxactivity = 0.0;
2375 consdata->glbminactivityneginf = 0;
2376 consdata->glbminactivityposinf = 0;
2377 consdata->glbmaxactivityneginf = 0;
2378 consdata->glbmaxactivityposinf = 0;
2379 consdata->glbminactivityneghuge = 0;
2380 consdata->glbminactivityposhuge = 0;
2381 consdata->glbmaxactivityneghuge = 0;
2382 consdata->glbmaxactivityposhuge = 0;
2383
2384 for( i = 0; i < consdata->nvars; ++i )
2385 consdataUpdateAddCoef(scip, consdata, consdata->vars[i], consdata->vals[i], FALSE);
2386
2387 consdata->lastminactivity = QUAD_TO_DBL(consdata->minactivity);
2388 consdata->lastmaxactivity = QUAD_TO_DBL(consdata->maxactivity);
2389 consdata->lastglbminactivity = QUAD_TO_DBL(consdata->glbminactivity);
2390 consdata->lastglbmaxactivity = QUAD_TO_DBL(consdata->glbmaxactivity);
2391}
2392
2393/** gets minimal activity for constraint and given values of counters for infinite and huge contributions
2394 * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2395 */
2396static
2398 SCIP* scip, /**< SCIP data structure */
2399 SCIP_CONSDATA* consdata, /**< linear constraint */
2400 int posinf, /**< number of coefficients contributing pos. infinite value */
2401 int neginf, /**< number of coefficients contributing neg. infinite value */
2402 int poshuge, /**< number of coefficients contributing huge pos. value */
2403 int neghuge, /**< number of coefficients contributing huge neg. value */
2404 SCIP_Real delta, /**< value to subtract from stored minactivity
2405 * (contribution of the variable set to zero when getting residual activity) */
2406 SCIP_Bool global, /**< should the global or local minimal activity be returned? */
2407 SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2408 SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2409 SCIP_Bool* isrelax, /**< pointer to store whether the activity is a relaxation,
2410 * i.e. is <= the exact minactivity (in case of huge contributing values) */
2411 SCIP_Bool* issettoinfinity /**< pointer to store whether minactivity was set to infinity or calculated */
2412 )
2413{
2414 assert(scip != NULL);
2415 assert(consdata != NULL);
2416 assert(posinf >= 0);
2417 assert(neginf >= 0);
2418 assert(poshuge >= 0);
2419 assert(neghuge >= 0);
2420 assert(minactivity != NULL);
2421 assert(isrelax != NULL);
2423
2424 /* if we have pos. infinite contributions, the minactivity is +infty */
2425 if( posinf > 0 )
2426 {
2427 *minactivity = SCIPinfinity(scip);
2429 *isrelax = FALSE;
2430 }
2431 /* if we have neg. (and no pos.) infinite contributions, the minactivity is -infty */
2432 else if( neginf > 0 )
2433 {
2434 *minactivity = -SCIPinfinity(scip);
2436 *isrelax = FALSE;
2437 }
2438 /* if we have neg. huge contributions, we only know that -infty is a relaxation of the minactivity */
2439 else if( neghuge > 0 )
2440 {
2441 *minactivity = -SCIPinfinity(scip);
2443 *isrelax = TRUE;
2444 }
2445 /* we do not need a good relaxation and we have positive huge contributions, so we just return -infty as activity */
2446 else if( !goodrelax && poshuge > 0 )
2447 {
2448 *minactivity = -SCIPinfinity(scip);
2450 *isrelax = TRUE;
2451 }
2452 else
2453 {
2454 SCIP_Real tmpactivity;
2455
2456 /* recompute minactivity if it is not valid */
2457 if( global )
2458 {
2459 if( !consdata->validglbminact )
2461 assert(consdata->validglbminact);
2462
2463 tmpactivity = QUAD_TO_DBL(consdata->glbminactivity);
2464 }
2465 else
2466 {
2467 if( !consdata->validminact )
2469 assert(consdata->validminact);
2470
2471 tmpactivity = QUAD_TO_DBL(consdata->minactivity);
2472 }
2473
2474 /* we have no infinite and no neg. huge contributions, but pos. huge contributions;
2475 * a feasible relaxation of the minactivity is the number of positive huge contributions
2476 * times the minimum value counting as "huge" plus finite (and non-huge) part of minactivity - delta
2477 */
2478 if( poshuge > 0 )
2479 {
2480 *minactivity = 1.0 * poshuge * SCIPgetHugeValue(scip) + (tmpactivity - delta);
2482 *isrelax = TRUE;
2483 }
2484 /* all counters are zero, so the minactivity is just stored and we subtract the delta */
2485 else
2486 {
2487 *minactivity = tmpactivity - delta;
2489 *isrelax = FALSE;
2490 }
2491 }
2492}
2493
2494/** gets maximal activity for constraint and given values of counters for infinite and huge contributions
2495 * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2496 */
2497static
2499 SCIP* scip, /**< SCIP data structure */
2500 SCIP_CONSDATA* consdata, /**< linear constraint */
2501 int posinf, /**< number of coefficients contributing pos. infinite value */
2502 int neginf, /**< number of coefficients contributing neg. infinite value */
2503 int poshuge, /**< number of coefficients contributing huge pos. value */
2504 int neghuge, /**< number of coefficients contributing huge neg. value */
2505 SCIP_Real delta, /**< value to subtract from stored maxactivity
2506 * (contribution of the variable set to zero when getting residual activity) */
2507 SCIP_Bool global, /**< should the global or local maximal activity be returned? */
2508 SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2509 SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2510 SCIP_Bool* isrelax, /**< pointer to store whether the activity is a relaxation,
2511 * i.e. is >= the exact maxactivity (in case of huge contributing values) */
2512 SCIP_Bool* issettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2513 )
2514{
2515 assert(scip != NULL);
2516 assert(consdata != NULL);
2517 assert(posinf >= 0);
2518 assert(neginf >= 0);
2519 assert(poshuge >= 0);
2520 assert(neghuge >= 0);
2521 assert(maxactivity != NULL);
2522 assert(isrelax != NULL);
2524
2525 /* if we have neg. infinite contributions, the maxactivity is -infty */
2526 if( neginf > 0 )
2527 {
2528 *maxactivity = -SCIPinfinity(scip);
2530 *isrelax = FALSE;
2531 }
2532 /* if we have pos. (and no neg.) infinite contributions, the maxactivity is +infty */
2533 else if( posinf > 0 )
2534 {
2535 *maxactivity = SCIPinfinity(scip);
2537 *isrelax = FALSE;
2538 }
2539 /* if we have pos. huge contributions, we only know that +infty is a relaxation of the maxactivity */
2540 else if( poshuge > 0 )
2541 {
2542 *maxactivity = SCIPinfinity(scip);
2544 *isrelax = TRUE;
2545 }
2546 /* we do not need a good relaxation and we have positve huge contributions, so we just return +infty as activity */
2547 else if( !goodrelax && neghuge > 0 )
2548 {
2549 *maxactivity = SCIPinfinity(scip);
2551 *isrelax = TRUE;
2552 }
2553 else
2554 {
2555 SCIP_Real tmpactivity;
2556
2557 /* recompute maxactivity if it is not valid */
2558 if( global )
2559 {
2560 if( !consdata->validglbmaxact )
2562 assert(consdata->validglbmaxact);
2563
2564 tmpactivity = QUAD_TO_DBL(consdata->glbmaxactivity);
2565 }
2566 else
2567 {
2568 if( !consdata->validmaxact )
2570 assert(consdata->validmaxact);
2571
2572 tmpactivity = QUAD_TO_DBL(consdata->maxactivity);
2573 }
2574
2575 /* we have no infinite, and no pos. huge contributions, but neg. huge contributions;
2576 * a feasible relaxation of the maxactivity is minus the number of negative huge contributions
2577 * times the minimum value counting as "huge" plus the finite (and non-huge) part of maxactivity minus delta
2578 */
2579 if( neghuge > 0 )
2580 {
2581 *maxactivity = -1.0 * neghuge * SCIPgetHugeValue(scip) + tmpactivity - delta;
2583 *isrelax = TRUE;
2584 }
2585 /* all counters are zero, so the maxactivity is just stored and we subtract the delta */
2586 else
2587 {
2588 *maxactivity = tmpactivity - delta;
2590 *isrelax = FALSE;
2591 }
2592 }
2593}
2594
2595/** gets activity bounds for constraint */
2596static
2598 SCIP* scip, /**< SCIP data structure */
2599 SCIP_CONSDATA* consdata, /**< linear constraint */
2600 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2601 * relaxed activities ignored, anyway? */
2602 SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2603 SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2604 SCIP_Bool* minisrelax, /**< pointer to store whether the returned minactivity is just a relaxation,
2605 * i.e. <= the exact minactivity (in case of huge contributions),
2606 * or equal to the exact minimal activity */
2607 SCIP_Bool* maxisrelax, /**< pointer to store whether the returned maxactivity is just a relaxation,
2608 * i.e. >= the exact maxactivity (in case of huge contributions),
2609 * or equal to the exact maximal activity */
2610 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minactivity was set to infinity or calculated */
2611 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2612
2613 )
2614{
2615 assert(scip != NULL);
2616 assert(consdata != NULL);
2617 assert(minactivity != NULL);
2618 assert(maxactivity != NULL);
2621
2622 if( !consdata->validactivities )
2623 {
2624 consdataCalcActivities(scip, consdata);
2625 assert(consdata->validminact);
2626 assert(consdata->validmaxact);
2627 }
2628 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2629 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2630 assert(consdata->minactivityneginf >= 0);
2631 assert(consdata->minactivityposinf >= 0);
2632 assert(consdata->maxactivityneginf >= 0);
2633 assert(consdata->maxactivityposinf >= 0);
2634
2635 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2636 consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2637 minactivity, minisrelax, isminsettoinfinity);
2638
2639 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2640 consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2641 maxactivity, maxisrelax, ismaxsettoinfinity);
2642}
2643
2644/** calculates activity bounds for constraint after setting variable to zero */
2645static
2647 SCIP* scip, /**< SCIP data structure */
2648 SCIP_CONSDATA* consdata, /**< linear constraint */
2649 SCIP_VAR* cancelvar, /**< variable to calculate activity residual for */
2650 SCIP_Real* resactivity, /**< pointer to store the residual activity */
2651 SCIP_Bool isminresact, /**< should minimal or maximal residual activity be calculated? */
2652 SCIP_Bool useglobalbounds /**< should global or local bounds be used? */
2653 )
2654{
2655 SCIP_VAR* var;
2656 SCIP_Real val;
2657 SCIP_Real lb;
2658 SCIP_Real ub;
2659 int v;
2660
2661 assert(scip != NULL);
2662 assert(consdata != NULL);
2663 assert(cancelvar != NULL);
2665
2666 *resactivity = 0.0;
2667
2668 for( v = 0; v < consdata->nvars; ++v )
2669 {
2670 var = consdata->vars[v];
2671 assert(var != NULL);
2672 if( var == cancelvar )
2673 continue;
2674
2675 val = consdata->vals[v];
2676
2677 if( useglobalbounds )
2678 {
2679 lb = SCIPvarGetLbGlobal(var);
2680 ub = SCIPvarGetUbGlobal(var);
2681 }
2682 else
2683 {
2684 lb = SCIPvarGetLbLocal(var);
2685 ub = SCIPvarGetUbLocal(var);
2686 }
2687
2688 assert(!SCIPisZero(scip, val));
2689 assert(SCIPisLE(scip, lb, ub));
2690
2691 if( val > 0.0 )
2692 {
2693 if( isminresact )
2694 {
2695 assert(!SCIPisInfinity(scip, -lb));
2696 assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2697 *resactivity += val*lb;
2698 }
2699 else
2700 {
2701 assert(!SCIPisInfinity(scip, ub));
2702 assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2703 *resactivity += val*ub;
2704 }
2705 }
2706 else
2707 {
2708 if( isminresact)
2709 {
2710 assert(!SCIPisInfinity(scip, ub));
2711 assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2712 *resactivity += val*ub;
2713 }
2714 else
2715 {
2716 assert(!SCIPisInfinity(scip, -lb));
2717 assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2718 *resactivity += val*lb;
2719 }
2720 }
2721 }
2723}
2724
2725/** gets activity bounds for constraint after setting variable to zero */
2726static
2728 SCIP* scip, /**< SCIP data structure */
2729 SCIP_CONSDATA* consdata, /**< linear constraint */
2730 SCIP_VAR* var, /**< variable to calculate activity residual for */
2731 SCIP_Real val, /**< coefficient value of variable in linear constraint */
2732 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2733 * relaxed acticities ignored, anyway? */
2734 SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity */
2735 SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity */
2736 SCIP_Bool* minisrelax, /**< pointer to store whether the returned residual minactivity is just a
2737 * relaxation, i.e. <= the exact residual minactivity (in case of huge
2738 * contributions), or equal to the exact residual minactivity */
2739 SCIP_Bool* maxisrelax, /**< pointer to store whether the returned residual maxactivity is just a
2740 * relaxation, i.e. <= the exact residual maxactivity (in case of huge
2741 * contributions), or equal to the exact residual minactivity */
2742 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2743 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2744 )
2745{
2746 SCIP_Real minactbound;
2747 SCIP_Real maxactbound;
2748 SCIP_Real absval;
2749
2750 assert(scip != NULL);
2751 assert(consdata != NULL);
2752 assert(var != NULL);
2759
2760 /* get activity bounds of linear constraint */
2761 if( !consdata->validactivities )
2762 {
2763 consdataCalcActivities(scip, consdata);
2764 assert(consdata->validminact);
2765 assert(consdata->validmaxact);
2766 }
2767 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2768 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2769 assert(consdata->minactivityneginf >= 0);
2770 assert(consdata->minactivityposinf >= 0);
2771 assert(consdata->maxactivityneginf >= 0);
2772 assert(consdata->maxactivityposinf >= 0);
2773 assert(consdata->minactivityneghuge >= 0);
2774 assert(consdata->minactivityposhuge >= 0);
2775 assert(consdata->maxactivityneghuge >= 0);
2776 assert(consdata->maxactivityposhuge >= 0);
2777
2778 if( val > 0.0 )
2779 {
2782 absval = val;
2783 }
2784 else
2785 {
2788 absval = -val;
2789 }
2790
2791 /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2792 * and contribution of variable set to zero that has to be subtracted from finite part of activity
2793 */
2795 {
2796 assert(consdata->minactivityposinf >= 1);
2797
2798 getMinActivity(scip, consdata, consdata->minactivityposinf - 1, consdata->minactivityneginf,
2799 consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2801 }
2802 else if( SCIPisInfinity(scip, -minactbound) )
2803 {
2804 assert(consdata->minactivityneginf >= 1);
2805
2806 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf - 1,
2807 consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2809 }
2810 else if( SCIPisHugeValue(scip, minactbound * absval) )
2811 {
2812 assert(consdata->minactivityposhuge >= 1);
2813
2814 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2815 consdata->minactivityposhuge - 1, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2817 }
2818 else if( SCIPisHugeValue(scip, -minactbound * absval) )
2819 {
2820 assert(consdata->minactivityneghuge >= 1);
2821
2822 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2823 consdata->minactivityposhuge, consdata->minactivityneghuge - 1, 0.0, FALSE, goodrelax,
2825 }
2826 else
2827 {
2828 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2829 consdata->minactivityposhuge, consdata->minactivityneghuge, absval * minactbound, FALSE, goodrelax,
2831 }
2832
2833 /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
2834 * and contribution of variable set to zero that has to be subtracted from finite part of activity
2835 */
2837 {
2838 assert(consdata->maxactivityneginf >= 1);
2839
2840 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf - 1,
2841 consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2843 }
2844 else if( SCIPisInfinity(scip, maxactbound) )
2845 {
2846 assert(consdata->maxactivityposinf >= 1);
2847
2848 getMaxActivity(scip, consdata, consdata->maxactivityposinf - 1, consdata->maxactivityneginf,
2849 consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2851 }
2852 else if( SCIPisHugeValue(scip, absval * maxactbound) )
2853 {
2854 assert(consdata->maxactivityposhuge >= 1);
2855
2856 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2857 consdata->maxactivityposhuge - 1, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2859 }
2860 else if( SCIPisHugeValue(scip, -absval * maxactbound) )
2861 {
2862 assert(consdata->maxactivityneghuge >= 1);
2863
2864 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2865 consdata->maxactivityposhuge, consdata->maxactivityneghuge - 1, 0.0, FALSE, goodrelax,
2867 }
2868 else
2869 {
2870 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2871 consdata->maxactivityposhuge, consdata->maxactivityneghuge, absval * maxactbound, FALSE, goodrelax,
2873 }
2874}
2875
2876/** gets global activity bounds for constraint */
2877static
2879 SCIP* scip, /**< SCIP data structure */
2880 SCIP_CONSDATA* consdata, /**< linear constraint */
2881 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2882 * relaxed acticities ignored, anyway? */
2883 SCIP_Real* glbminactivity, /**< pointer to store the minimal activity, or NULL, if not needed */
2884 SCIP_Real* glbmaxactivity, /**< pointer to store the maximal activity, or NULL, if not needed */
2885 SCIP_Bool* minisrelax, /**< pointer to store whether the returned minactivity is just a relaxation,
2886 * i.e. <= the exact minactivity (in case of huge contributions),
2887 * or equal to the exact minimal activity */
2888 SCIP_Bool* maxisrelax, /**< pointer to store whether the returned maxactivity is just a relaxation,
2889 * i.e. >= the exact maxactivity (in case of huge contributions),
2890 * or equal to the exact maximal activity */
2891 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2892 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2893 )
2894{
2895 assert(scip != NULL);
2896 assert(consdata != NULL);
2899
2900 if( !consdata->validactivities )
2901 {
2902 consdataCalcActivities(scip, consdata);
2903 assert(consdata->validglbminact);
2904 assert(consdata->validglbmaxact);
2905 }
2906 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2907 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2908 assert(consdata->glbminactivityneginf >= 0);
2909 assert(consdata->glbminactivityposinf >= 0);
2910 assert(consdata->glbmaxactivityneginf >= 0);
2911 assert(consdata->glbmaxactivityposinf >= 0);
2912 assert(consdata->glbminactivityneghuge >= 0);
2913 assert(consdata->glbminactivityposhuge >= 0);
2914 assert(consdata->glbmaxactivityneghuge >= 0);
2915 assert(consdata->glbmaxactivityposhuge >= 0);
2916
2917 if( glbminactivity != NULL )
2918 {
2921
2922 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2923 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2925 }
2926
2927 if( glbmaxactivity != NULL )
2928 {
2931
2932 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2933 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2935 }
2936}
2937
2938/** gets global activity bounds for constraint after setting variable to zero */
2939static
2941 SCIP* scip, /**< SCIP data structure */
2942 SCIP_CONSDATA* consdata, /**< linear constraint */
2943 SCIP_VAR* var, /**< variable to calculate activity residual for */
2944 SCIP_Real val, /**< coefficient value of variable in linear constraint */
2945 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2946 * relaxed acticities ignored, anyway? */
2947 SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity, or NULL, if not needed */
2948 SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity, or NULL, if not needed */
2949 SCIP_Bool* minisrelax, /**< pointer to store whether the returned residual minactivity is just a
2950 * relaxation, i.e. <= the exact residual minactivity (in case of huge
2951 * contributions), or equal to the exact residual minactivity */
2952 SCIP_Bool* maxisrelax, /**< pointer to store whether the returned residual maxactivity is just a
2953 * relaxation, i.e. <= the exact residual maxactivity (in case of huge
2954 * contributions), or equal to the exact residual minactivity */
2955 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2956 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2957 )
2958{
2959 SCIP_Real minactbound;
2960 SCIP_Real maxactbound;
2961 SCIP_Real absval;
2962
2963 assert(scip != NULL);
2964 assert(consdata != NULL);
2965 assert(var != NULL);
2968
2969 /* get activity bounds of linear constraint */
2970 if( !consdata->validactivities )
2971 consdataCalcActivities(scip, consdata);
2972
2973 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2974 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2975 assert(consdata->glbminactivityneginf >= 0);
2976 assert(consdata->glbminactivityposinf >= 0);
2977 assert(consdata->glbmaxactivityneginf >= 0);
2978 assert(consdata->glbmaxactivityposinf >= 0);
2979
2980 if( val > 0.0 )
2981 {
2984 absval = val;
2985 }
2986 else
2987 {
2990 absval = -val;
2991 }
2992
2993 if( minresactivity != NULL )
2994 {
2997
2998 /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2999 * and contribution of variable set to zero that has to be subtracted from finite part of activity
3000 */
3002 {
3003 assert(consdata->glbminactivityposinf >= 1);
3004
3005 getMinActivity(scip, consdata, consdata->glbminactivityposinf - 1, consdata->glbminactivityneginf,
3006 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
3008 }
3009 else if( SCIPisInfinity(scip, -minactbound) )
3010 {
3011 assert(consdata->glbminactivityneginf >= 1);
3012
3013 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf - 1,
3014 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
3016 }
3017 else if( SCIPisHugeValue(scip, minactbound * absval) )
3018 {
3019 assert(consdata->glbminactivityposhuge >= 1);
3020
3021 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
3022 consdata->glbminactivityposhuge - 1, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
3024 }
3025 else if( SCIPisHugeValue(scip, -minactbound * absval) )
3026 {
3027 assert(consdata->glbminactivityneghuge >= 1);
3028
3029 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
3030 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge - 1, 0.0, TRUE, goodrelax,
3032 }
3033 else
3034 {
3035 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
3036 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, absval * minactbound, TRUE,
3038 }
3039 }
3040
3041 if( maxresactivity != NULL )
3042 {
3045
3046 /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
3047 * and contribution of variable set to zero that has to be subtracted from finite part of activity
3048 */
3050 {
3051 assert(consdata->glbmaxactivityneginf >= 1);
3052
3053 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf - 1,
3054 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3056 }
3057 else if( SCIPisInfinity(scip, maxactbound) )
3058 {
3059 assert(consdata->glbmaxactivityposinf >= 1);
3060
3061 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf - 1, consdata->glbmaxactivityneginf,
3062 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3064 }
3065 else if( SCIPisHugeValue(scip, absval * maxactbound) )
3066 {
3067 assert(consdata->glbmaxactivityposhuge >= 1);
3068
3069 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3070 consdata->glbmaxactivityposhuge - 1, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3072 }
3073 else if( SCIPisHugeValue(scip, -absval * maxactbound) )
3074 {
3075 assert(consdata->glbmaxactivityneghuge >= 1);
3076
3077 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3078 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge - 1, 0.0, TRUE, goodrelax,
3080 }
3081 else
3082 {
3083 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3084 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, absval * maxactbound, TRUE,
3086 }
3087 }
3088}
3089
3090/** calculates the activity of the linear constraint for given solution */
3091static
3093 SCIP* scip, /**< SCIP data structure */
3094 SCIP_CONSDATA* consdata, /**< linear constraint data */
3095 SCIP_SOL* sol /**< solution to get activity for, NULL to current solution */
3096 )
3097{
3098 SCIP_Real activity;
3099
3100 assert(scip != NULL);
3101 assert(consdata != NULL);
3102
3103 if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
3104 activity = consdataComputePseudoActivity(scip, consdata);
3105 else
3106 {
3107 SCIP_Real solval;
3108 int nposinf;
3109 int nneginf;
3110 SCIP_Bool negsign;
3111 int v;
3112
3113 activity = 0.0;
3114 nposinf = 0;
3115 nneginf = 0;
3116
3117 for( v = 0; v < consdata->nvars; ++v )
3118 {
3119 solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
3120
3121 if( consdata->vals[v] < 0 )
3122 negsign = TRUE;
3123 else
3124 negsign = FALSE;
3125
3126 if( (SCIPisInfinity(scip, solval) && !negsign) || (SCIPisInfinity(scip, -solval) && negsign) )
3127 ++nposinf;
3128 else if( (SCIPisInfinity(scip, solval) && negsign) || (SCIPisInfinity(scip, -solval) && !negsign) )
3129 ++nneginf;
3130 else
3131 activity += consdata->vals[v] * solval;
3132 }
3133 assert(nneginf >= 0 && nposinf >= 0);
3134
3135 SCIPdebugMsg(scip, "activity of linear constraint: %.15g, %d positive infinity values, %d negative infinity values \n", activity, nposinf, nneginf);
3136
3137 /* check for amount of infinity values and correct the activity */
3138 if( nposinf > 0 && nneginf > 0 )
3139 activity = (consdata->rhs + consdata->lhs) / 2;
3140 else if( nposinf > 0 )
3141 activity = SCIPinfinity(scip);
3142 else if( nneginf > 0 )
3143 activity = -SCIPinfinity(scip);
3144
3145 SCIPdebugMsg(scip, "corrected activity of linear constraint: %.15g\n", activity);
3146 }
3147
3148 if( activity == SCIP_INVALID ) /*lint !e777*/
3149 return activity;
3150 else if( activity < 0 )
3151 activity = MAX(activity, -SCIPinfinity(scip)); /*lint !e666*/
3152 else
3153 activity = MIN(activity, SCIPinfinity(scip)); /*lint !e666*/
3154
3155 return activity;
3156}
3157
3158/** calculates the feasibility of the linear constraint for given solution */
3159static
3161 SCIP* scip, /**< SCIP data structure */
3162 SCIP_CONSDATA* consdata, /**< linear constraint data */
3163 SCIP_SOL* sol /**< solution to get feasibility for, NULL to current solution */
3164 )
3165{
3166 SCIP_Real activity;
3167
3168 assert(scip != NULL);
3169 assert(consdata != NULL);
3170
3171 activity = consdataGetActivity(scip, consdata, sol);
3172
3173 if( activity == SCIP_INVALID ) /*lint !e777*/
3174 return -SCIPinfinity(scip);
3175
3176 return MIN(consdata->rhs - activity, activity - consdata->lhs);
3177}
3178
3179/** updates bit signatures after adding a single coefficient */
3180static
3182 SCIP_CONSDATA* consdata, /**< linear constraint data */
3183 int pos /**< position of coefficient to update signatures for */
3184 )
3185{
3186 uint64_t varsignature;
3187 SCIP_Real lb;
3188 SCIP_Real ub;
3189 SCIP_Real val;
3190
3191 assert(consdata != NULL);
3192 assert(consdata->validsignature);
3193
3194 varsignature = SCIPhashSignature64(SCIPvarGetIndex(consdata->vars[pos]));
3195 lb = SCIPvarGetLbGlobal(consdata->vars[pos]);
3196 ub = SCIPvarGetUbGlobal(consdata->vars[pos]);
3197 val = consdata->vals[pos];
3198 if( (val > 0.0 && ub > 0.0) || (val < 0.0 && lb < 0.0) )
3199 consdata->possignature |= varsignature;
3200 if( (val > 0.0 && lb < 0.0) || (val < 0.0 && ub > 0.0) )
3201 consdata->negsignature |= varsignature;
3202}
3203
3204/** calculates the bit signatures of the given constraint data */
3205static
3207 SCIP_CONSDATA* consdata /**< linear constraint data */
3208 )
3209{
3210 assert(consdata != NULL);
3211
3212 if( !consdata->validsignature )
3213 {
3214 int i;
3215
3216 consdata->validsignature = TRUE;
3217 consdata->possignature = 0;
3218 consdata->negsignature = 0;
3219 for( i = 0; i < consdata->nvars; ++i )
3220 consdataUpdateSignatures(consdata, i);
3221 }
3222}
3223
3224/** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3225static
3227{ /*lint --e{715}*/
3228 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3229 SCIP_VAR* var1;
3230 SCIP_VAR* var2;
3231
3232 assert(consdata != NULL);
3235
3236 var1 = consdata->vars[ind1];
3237 var2 = consdata->vars[ind2];
3238
3239 /* exactly one variable is binary */
3241 {
3242 return (SCIPvarIsBinary(var1) ? -1 : +1);
3243 }
3244 /* both variables are binary */
3245 else if( SCIPvarIsBinary(var1) )
3246 {
3247 return SCIPvarCompare(var1, var2);
3248 }
3249 else
3250 {
3253
3254 if( vartype1 < vartype2 )
3255 return -1;
3256 else if( vartype1 > vartype2 )
3257 return +1;
3258 else
3259 return SCIPvarCompare(var1, var2);
3260 }
3261}
3262
3263/** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3264static
3266{ /*lint --e{715}*/
3267 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3268 SCIP_VAR* var1;
3269 SCIP_VAR* var2;
3270
3271 assert(consdata != NULL);
3274
3275 var1 = consdata->vars[ind1];
3276 var2 = consdata->vars[ind2];
3277
3278 /* exactly one variable is binary */
3280 {
3281 return (SCIPvarIsBinary(var1) ? -1 : +1);
3282 }
3283 /* both variables are binary */
3284 else if( SCIPvarIsBinary(var1) )
3285 {
3286 SCIP_Real abscoef1 = REALABS(consdata->vals[ind1]);
3287 SCIP_Real abscoef2 = REALABS(consdata->vals[ind2]);
3288
3289 if( EPSGT(abscoef1, abscoef2, 1e-9) )
3290 return -1;
3291 else if( EPSGT(abscoef2, abscoef1, 1e-9) )
3292 return +1;
3293 else
3295 }
3296 else
3297 {
3300
3301 if( vartype1 < vartype2 )
3302 {
3303 return -1;
3304 }
3305 else if( vartype1 > vartype2 )
3306 {
3307 return +1;
3308 }
3309 else
3310 {
3311 /* both variables are continuous */
3312 if( !SCIPvarIsIntegral(var1) )
3313 {
3316 }
3317 else
3318 {
3319 SCIP_Real abscont1 = REALABS(consdata->vals[ind1] * (SCIPvarGetUbGlobal(var1) - SCIPvarGetLbGlobal(var1)));
3320 SCIP_Real abscont2 = REALABS(consdata->vals[ind2] * (SCIPvarGetUbGlobal(var2) - SCIPvarGetLbGlobal(var2)));
3321
3322 if( EPSGT(abscont1, abscont2, 1e-9) )
3323 return -1;
3324 else if( EPSGT(abscont2, abscont1, 1e-9) )
3325 return +1;
3326 else
3328 }
3329 }
3330 }
3331}
3332
3333/** permutes the constraint's variables according to a given permutation. */
3334static
3336 SCIP_CONSDATA* consdata, /**< the constraint data */
3337 int* perm, /**< the target permutation */
3338 int nvars /**< the number of variables */
3339 )
3340{ /*lint --e{715}*/
3341 SCIP_VAR* varv;
3343 SCIP_Real valv;
3344 int v;
3345 int i;
3346 int nexti;
3347
3348 assert(perm != NULL);
3349 assert(consdata != NULL);
3350
3351 /* permute the variables in the linear constraint according to the target permutation */
3352 eventdatav = NULL;
3353 for( v = 0; v < nvars; ++v )
3354 {
3355 if( perm[v] != v )
3356 {
3357 varv = consdata->vars[v];
3358 valv = consdata->vals[v];
3359 if( consdata->eventdata != NULL )
3360 eventdatav = consdata->eventdata[v];
3361 i = v;
3362 do
3363 {
3364 assert(0 <= perm[i] && perm[i] < nvars);
3365 assert(perm[i] != i);
3366 consdata->vars[i] = consdata->vars[perm[i]];
3367 consdata->vals[i] = consdata->vals[perm[i]];
3368 if( consdata->eventdata != NULL )
3369 {
3370 consdata->eventdata[i] = consdata->eventdata[perm[i]];
3371 consdata->eventdata[i]->varpos = i;
3372 }
3373 nexti = perm[i];
3374 perm[i] = i;
3375 i = nexti;
3376 }
3377 while( perm[i] != v );
3378 consdata->vars[i] = varv;
3379 consdata->vals[i] = valv;
3380 if( consdata->eventdata != NULL )
3381 {
3382 consdata->eventdata[i] = eventdatav;
3383 consdata->eventdata[i]->varpos = i;
3384 }
3385 perm[i] = i;
3386 }
3387 }
3388#ifdef SCIP_DEBUG
3389 /* check sorting */
3390 for( v = 0; v < nvars; ++v )
3391 {
3392 assert(perm[v] == v);
3393 assert(consdata->eventdata == NULL || consdata->eventdata[v]->varpos == v);
3394 }
3395#endif
3396}
3397
3398/** sorts linear constraint's variables depending on the stage of the solving process:
3399 * - during PRESOLVING
3400 * sorts variables by binaries, integers, implicit integers, and continuous variables,
3401 * and the variables of the same type by non-decreasing variable index
3402 *
3403 * - during SOLVING
3404 * sorts variables of the remaining problem by binaries, integers, implicit integers, and continuous variables,
3405 * and binary and integer variables by their global max activity delta (within each group),
3406 * ties within a group are broken by problem index of the variable.
3407 *
3408 * This fastens the propagation time of the constraint handler.
3409 */
3410static
3412 SCIP* scip, /**< SCIP data structure */
3413 SCIP_CONSDATA* consdata /**< linear constraint data */
3414 )
3415{
3416 assert(scip != NULL);
3417 assert(consdata != NULL);
3418
3419 /* check if there are variables for sorting */
3420 if( consdata->nvars <= 1 )
3421 {
3422 consdata->indexsorted = TRUE;
3423 consdata->coefsorted = TRUE;
3424 consdata->nbinvars = (consdata->nvars == 1 ? (int)SCIPvarIsBinary(consdata->vars[0]) : 0);
3425 }
3426 else if( (!consdata->indexsorted && SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE)
3427 || (!consdata->coefsorted && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE) )
3428 {
3429 int* perm;
3430 int v;
3431
3432 /* get temporary memory to store the sorted permutation */
3433 SCIP_CALL( SCIPallocBufferArray(scip, &perm, consdata->nvars) );
3434
3435 /* call sorting method */
3437 SCIPsort(perm, consdataCompVar, (void*)consdata, consdata->nvars);
3438 else
3439 SCIPsort(perm, consdataCompVarProp, (void*)consdata, consdata->nvars);
3440
3441 permSortConsdata(consdata, perm, consdata->nvars);
3442
3443 /* free temporary memory */
3444 SCIPfreeBufferArray(scip, &perm);
3445
3447 {
3448 consdata->indexsorted = FALSE;
3449 consdata->coefsorted = TRUE;
3450
3451 /* count binary variables in the sorted vars array */
3452 consdata->nbinvars = 0;
3453 for( v = 0; v < consdata->nvars; ++v )
3454 {
3455 if( SCIPvarIsBinary(consdata->vars[v]) )
3456 ++consdata->nbinvars;
3457 else
3458 break;
3459 }
3460 }
3461 else
3462 {
3463 consdata->indexsorted = TRUE;
3464 consdata->coefsorted = FALSE;
3465 }
3466 }
3467
3468 return SCIP_OKAY;
3469}
3470
3471
3472/*
3473 * local linear constraint handler methods
3474 */
3475
3476/** sets left hand side of linear constraint */
3477static
3479 SCIP* scip, /**< SCIP data structure */
3480 SCIP_CONS* cons, /**< linear constraint */
3481 SCIP_Real lhs /**< new left hand side */
3482 )
3483{
3484 SCIP_CONSDATA* consdata;
3485 SCIP_Bool locked;
3486 int i;
3487
3488 assert(scip != NULL);
3489 assert(cons != NULL);
3490 assert(!SCIPisInfinity(scip, lhs));
3491
3492 /* adjust value to not be smaller than -inf */
3493 if ( SCIPisInfinity(scip, -lhs) )
3494 lhs = -SCIPinfinity(scip);
3495
3496 consdata = SCIPconsGetData(cons);
3497 assert(consdata != NULL);
3498 assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3499 assert(!SCIPisInfinity(scip, consdata->lhs));
3500
3501 /* check whether the side is not changed */
3502 if( SCIPisEQ(scip, consdata->lhs, lhs) )
3503 return SCIP_OKAY;
3504
3505 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3506 if( SCIPisEQ(scip, lhs, consdata->rhs) )
3507 {
3508 consdata->rhs = lhs;
3509 assert(consdata->row == NULL);
3510 }
3511
3512 locked = FALSE;
3513 for( i = 0; i < NLOCKTYPES && !locked; i++ )
3514 locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3515
3516 /* if necessary, update the rounding locks of variables */
3517 if( locked )
3518 {
3519 if( SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, -lhs) )
3520 {
3521 SCIP_VAR** vars;
3522 SCIP_Real* vals;
3523 int v;
3524
3525 /* the left hand side switched from -infinity to a non-infinite value -> install rounding locks */
3526 vars = consdata->vars;
3527 vals = consdata->vals;
3528
3529 for( v = 0; v < consdata->nvars; ++v )
3530 {
3531 assert(vars[v] != NULL);
3532 assert(!SCIPisZero(scip, vals[v]));
3533
3534 if( SCIPisPositive(scip, vals[v]) )
3535 {
3536 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3537 }
3538 else
3539 {
3540 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3541 }
3542 }
3543 }
3544 else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -lhs) )
3545 {
3546 SCIP_VAR** vars;
3547 SCIP_Real* vals;
3548 int v;
3549
3550 /* the left hand side switched from a non-infinite value to -infinity -> remove rounding locks */
3551 vars = consdata->vars;
3552 vals = consdata->vals;
3553
3554 for( v = 0; v < consdata->nvars; ++v )
3555 {
3556 assert(vars[v] != NULL);
3557 assert(!SCIPisZero(scip, vals[v]));
3558
3559 if( SCIPisPositive(scip, vals[v]) )
3560 {
3562 }
3563 else
3564 {
3566 }
3567 }
3568 }
3569 }
3570
3571 /* 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 */
3572 if( !SCIPisInfinity(scip, -lhs) && SCIPisGT(scip, lhs, consdata->lhs) )
3573 {
3574 consdata->boundstightened = 0;
3575 consdata->presolved = FALSE;
3576 consdata->cliquesadded = FALSE;
3577 consdata->implsadded = FALSE;
3578
3579 /* mark the constraint for propagation */
3580 if( SCIPconsIsTransformed(cons) )
3581 {
3583 }
3584 }
3585
3586 /* set new left hand side and update constraint data */
3587 consdata->lhs = lhs;
3588 consdata->changed = TRUE;
3589 consdata->normalized = FALSE;
3590 consdata->upgradetried = FALSE;
3591 consdata->rangedrowpropagated = 0;
3592
3593 /* update the lhs of the LP row */
3594 if( consdata->row != NULL )
3595 {
3596 SCIP_CALL( SCIPchgRowLhs(scip, consdata->row, lhs) );
3597 }
3598
3599 return SCIP_OKAY;
3600}
3601
3602/** sets right hand side of linear constraint */
3603static
3605 SCIP* scip, /**< SCIP data structure */
3606 SCIP_CONS* cons, /**< linear constraint */
3607 SCIP_Real rhs /**< new right hand side */
3608 )
3609{
3610 SCIP_CONSDATA* consdata;
3611 SCIP_Bool locked;
3612 int i;
3613
3614 assert(scip != NULL);
3615 assert(cons != NULL);
3616 assert(!SCIPisInfinity(scip, -rhs));
3617
3618 /* adjust value to not be larger than inf */
3619 if ( SCIPisInfinity(scip, rhs) )
3620 rhs = SCIPinfinity(scip);
3621
3622 consdata = SCIPconsGetData(cons);
3623 assert(consdata != NULL);
3624 assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3625 assert(!SCIPisInfinity(scip, -consdata->rhs));
3626
3627 /* check whether the side is not changed */
3628 if( SCIPisEQ(scip, consdata->rhs, rhs) )
3629 return SCIP_OKAY;
3630
3631 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3632 if( SCIPisEQ(scip, rhs, consdata->lhs) )
3633 {
3634 consdata->lhs = rhs;
3635 assert(consdata->row == NULL);
3636 }
3637
3638 locked = FALSE;
3639 for( i = 0; i < NLOCKTYPES && !locked; i++ )
3640 locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3641
3642 /* if necessary, update the rounding locks of variables */
3643 if( locked )
3644 {
3646
3647 if( SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, rhs) )
3648 {
3649 SCIP_VAR** vars;
3650 SCIP_Real* vals;
3651 int v;
3652
3653 /* the right hand side switched from infinity to a non-infinite value -> install rounding locks */
3654 vars = consdata->vars;
3655 vals = consdata->vals;
3656
3657 for( v = 0; v < consdata->nvars; ++v )
3658 {
3659 assert(vars[v] != NULL);
3660 assert(!SCIPisZero(scip, vals[v]));
3661
3662 if( SCIPisPositive(scip, vals[v]) )
3663 {
3664 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3665 }
3666 else
3667 {
3668 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3669 }
3670 }
3671 }
3672 else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, rhs) )
3673 {
3674 SCIP_VAR** vars;
3675 SCIP_Real* vals;
3676 int v;
3677
3678 /* the right hand side switched from a non-infinite value to infinity -> remove rounding locks */
3679 vars = consdata->vars;
3680 vals = consdata->vals;
3681
3682 for( v = 0; v < consdata->nvars; ++v )
3683 {
3684 assert(vars[v] != NULL);
3685 assert(!SCIPisZero(scip, vals[v]));
3686
3687 if( SCIPisPositive(scip, vals[v]) )
3688 {
3690 }
3691 else
3692 {
3694 }
3695 }
3696 }
3697 }
3698
3699 /* 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 */
3700 if( !SCIPisInfinity(scip, rhs) && SCIPisLT(scip, rhs, consdata->rhs) )
3701 {
3702 consdata->boundstightened = 0;
3703 consdata->presolved = FALSE;
3704 consdata->cliquesadded = FALSE;
3705 consdata->implsadded = FALSE;
3706
3707 /* mark the constraint for propagation */
3708 if( SCIPconsIsTransformed(cons) )
3709 {
3711 }
3712 }
3713
3714 /* set new right hand side and update constraint data */
3715 consdata->rhs = rhs;
3716 consdata->changed = TRUE;
3717 consdata->normalized = FALSE;
3718 consdata->upgradetried = FALSE;
3719 consdata->rangedrowpropagated = 0;
3720
3721 /* update the rhs of the LP row */
3722 if( consdata->row != NULL )
3723 {
3724 SCIP_CALL( SCIPchgRowRhs(scip, consdata->row, rhs) );
3725 }
3726
3727 return SCIP_OKAY;
3728}
3729
3730/** adds coefficient in linear constraint */
3731static
3733 SCIP* scip, /**< SCIP data structure */
3734 SCIP_CONS* cons, /**< linear constraint */
3735 SCIP_VAR* var, /**< variable of constraint entry */
3736 SCIP_Real val /**< coefficient of constraint entry */
3737 )
3738{
3739 SCIP_CONSDATA* consdata;
3740 SCIP_Bool transformed;
3741
3742 assert(scip != NULL);
3743 assert(cons != NULL);
3744 assert(var != NULL);
3745
3746 /* relaxation-only variables must not be used in checked or enforced constraints */
3748
3749 /* ignore coefficient if it is nearly zero */
3750 if( SCIPisZero(scip, val) )
3751 return SCIP_OKAY;
3752
3753 consdata = SCIPconsGetData(cons);
3754 assert(consdata != NULL);
3755
3756 /* are we in the transformed problem? */
3757 transformed = SCIPconsIsTransformed(cons);
3758
3759 /* always use transformed variables in transformed constraints */
3760 if( transformed )
3761 {
3763 }
3764 assert(var != NULL);
3765 assert(transformed == SCIPvarIsTransformed(var));
3766
3767 SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
3768 consdata->vars[consdata->nvars] = var;
3769 consdata->vals[consdata->nvars] = val;
3770 consdata->nvars++;
3771
3772 /* capture variable */
3774
3775 /* if we are in transformed problem, the variable needs an additional event data */
3776 if( transformed )
3777 {
3778 if( consdata->eventdata != NULL )
3779 {
3780 SCIP_CONSHDLR* conshdlr;
3781 SCIP_CONSHDLRDATA* conshdlrdata;
3782
3783 /* check for event handler */
3784 conshdlr = SCIPconsGetHdlr(cons);
3785 conshdlrdata = SCIPconshdlrGetData(conshdlr);
3786 assert(conshdlrdata != NULL);
3787 assert(conshdlrdata->eventhdlr != NULL);
3788
3789 /* initialize eventdata array */
3790 consdata->eventdata[consdata->nvars-1] = NULL;
3791
3792 /* catch bound change events of variable */
3793 SCIP_CALL( consCatchEvent(scip, cons, conshdlrdata->eventhdlr, consdata->nvars-1) );
3794 }
3795
3796 /* update minimum and maximum activities */
3797 consdataUpdateAddCoef(scip, consdata, var, val, FALSE);
3798
3799 /* update maximum activity delta */
3800 if( !SCIPisInfinity(scip, consdata->maxactdelta ) )
3801 {
3802 SCIP_Real lb;
3803 SCIP_Real ub;
3804
3805 lb = SCIPvarGetLbLocal(var);
3806 ub = SCIPvarGetUbLocal(var);
3807
3808 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
3809 {
3810 consdata->maxactdelta = SCIPinfinity(scip);
3811 consdata->maxactdeltavar = var;
3812 }
3813 else
3814 {
3815 SCIP_Real domain = ub - lb;
3816 SCIP_Real delta = REALABS(val) * domain;
3817
3818 if( delta > consdata->maxactdelta )
3819 {
3820 consdata->maxactdelta = delta;
3821 consdata->maxactdeltavar = var;
3822 }
3823 }
3824 }
3825 }
3826
3827 /* install rounding locks for new variable */
3828 SCIP_CALL( lockRounding(scip, cons, var, val) );
3829
3830 /* mark the constraint for propagation */
3831 if( transformed )
3832 {
3834 }
3835
3836 consdata->boundstightened = 0;
3837 consdata->presolved = FALSE;
3838 consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(var);
3839
3840 if( consdata->validsignature )
3841 consdataUpdateSignatures(consdata, consdata->nvars-1);
3842
3843 consdata->changed = TRUE;
3844 consdata->normalized = FALSE;
3845 consdata->upgradetried = FALSE;
3846 consdata->cliquesadded = FALSE;
3847 consdata->implsadded = FALSE;
3848 consdata->rangedrowpropagated = 0;
3849
3850 if( consdata->nvars == 1 )
3851 {
3852 consdata->indexsorted = TRUE;
3853 consdata->coefsorted = TRUE;
3854 consdata->merged = TRUE;
3855 }
3856 else
3857 {
3858 consdata->merged = FALSE;
3859
3861 {
3862 consdata->indexsorted = consdata->indexsorted && (consdataCompVar((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0);
3863 consdata->coefsorted = FALSE;
3864 }
3865 else
3866 {
3867 consdata->indexsorted = FALSE;
3868 consdata->coefsorted = consdata->coefsorted && (consdataCompVarProp((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0);
3869 }
3870 }
3871
3872 /* update hascontvar and hasnonbinvar flags */
3873 if( consdata->hasnonbinvalid && !consdata->hascontvar )
3874 {
3875 SCIP_VARTYPE vartype = SCIPvarGetType(var);
3876
3877 if( vartype != SCIP_VARTYPE_BINARY )
3878 {
3879 consdata->hasnonbinvar = TRUE;
3880
3881 if( vartype == SCIP_VARTYPE_CONTINUOUS )
3882 consdata->hascontvar = TRUE;
3883 }
3884 }
3885
3886 /* add the new coefficient to the LP row */
3887 if( consdata->row != NULL )
3888 {
3889 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, val) );
3890 }
3891
3892 return SCIP_OKAY;
3893}
3894
3895/** deletes coefficient at given position from linear constraint data */
3896static
3898 SCIP* scip, /**< SCIP data structure */
3899 SCIP_CONS* cons, /**< linear constraint */
3900 int pos /**< position of coefficient to delete */
3901 )
3902{
3903 SCIP_CONSDATA* consdata;
3904 SCIP_VAR* var;
3905 SCIP_Real val;
3906
3907 assert(scip != NULL);
3908 assert(cons != NULL);
3909
3910 consdata = SCIPconsGetData(cons);
3911 assert(consdata != NULL);
3912 assert(0 <= pos && pos < consdata->nvars);
3913
3914 var = consdata->vars[pos];
3915 val = consdata->vals[pos];
3916 assert(var != NULL);
3917
3918 /* remove rounding locks for deleted variable */
3919 SCIP_CALL( unlockRounding(scip, cons, var, val) );
3920
3921 /* if we are in transformed problem, delete the event data of the variable */
3922 if( SCIPconsIsTransformed(cons) )
3923 {
3924 SCIP_CONSHDLR* conshdlr;
3925 SCIP_CONSHDLRDATA* conshdlrdata;
3926
3927 /* check for event handler */
3928 conshdlr = SCIPconsGetHdlr(cons);
3929 conshdlrdata = SCIPconshdlrGetData(conshdlr);
3930 assert(conshdlrdata != NULL);
3931 assert(conshdlrdata->eventhdlr != NULL);
3932
3933 /* drop bound change events of variable */
3934 if( consdata->eventdata != NULL )
3935 {
3936 SCIP_CALL( consDropEvent(scip, cons, conshdlrdata->eventhdlr, pos) );
3937 assert(consdata->eventdata[pos] == NULL);
3938 }
3939 }
3940
3941 /* move the last variable to the free slot */
3942 if( pos != consdata->nvars - 1 )
3943 {
3944 consdata->vars[pos] = consdata->vars[consdata->nvars-1];
3945 consdata->vals[pos] = consdata->vals[consdata->nvars-1];
3946
3947 if( consdata->eventdata != NULL )
3948 {
3949 consdata->eventdata[pos] = consdata->eventdata[consdata->nvars-1];
3950 assert(consdata->eventdata[pos] != NULL);
3951 consdata->eventdata[pos]->varpos = pos;
3952 }
3953
3954 consdata->indexsorted = consdata->indexsorted && (pos + 2 >= consdata->nvars);
3955 consdata->coefsorted = consdata->coefsorted && (pos + 2 >= consdata->nvars);
3956 }
3957 consdata->nvars--;
3958
3959 /* if at most one variable is left, the activities should be recalculated (to correspond exactly to the bounds
3960 * of the remaining variable, or give exactly 0.0)
3961 */
3962 if( consdata->nvars <= 1 )
3964 else
3965 {
3966 if( SCIPconsIsTransformed(cons) )
3967 {
3968 /* if we are in transformed problem, update minimum and maximum activities */
3969 consdataUpdateDelCoef(scip, consdata, var, val, TRUE);
3970
3971 /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
3972 * delta needs to be recalculated on the next real propagation
3973 */
3974 if( consdata->maxactdeltavar == var )
3975 {
3976 consdata->maxactdelta = SCIP_INVALID;
3977 consdata->maxactdeltavar = NULL;
3978 }
3979 }
3980 }
3981
3982 /* mark the constraint for propagation */
3983 if( SCIPconsIsTransformed(cons) )
3984 {
3986 }
3987
3988 consdata->boundstightened = 0;
3989 consdata->presolved = FALSE;
3990 consdata->validsignature = FALSE;
3991 consdata->changed = TRUE;
3992 consdata->normalized = FALSE;
3993 consdata->upgradetried = FALSE;
3994 consdata->cliquesadded = FALSE;
3995 consdata->implsadded = FALSE;
3996 consdata->rangedrowpropagated = 0;
3997
3998 /* check if hasnonbinvar flag might be incorrect now */
3999 if( consdata->hasnonbinvar && SCIPvarGetType(var) != SCIP_VARTYPE_BINARY )
4000 {
4001 consdata->hasnonbinvalid = FALSE;
4002 }
4003
4004 /* delete coefficient from the LP row */
4005 if( consdata->row != NULL )
4006 {
4007 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, -val) );
4008 }
4009
4010 /* release variable */
4012
4013 return SCIP_OKAY;
4014}
4015
4016/** changes coefficient value at given position of linear constraint data */
4017static
4019 SCIP* scip, /**< SCIP data structure */
4020 SCIP_CONS* cons, /**< linear constraint */
4021 int pos, /**< position of coefficient to delete */
4022 SCIP_Real newval /**< new value of coefficient */
4023 )
4024{
4025 SCIP_CONSDATA* consdata;
4026 SCIP_VAR* var;
4027 SCIP_Real val;
4028 SCIP_Bool locked;
4029 int i;
4030
4031 assert(scip != NULL);
4032 assert(cons != NULL);
4033 assert(!SCIPisZero(scip, newval));
4034
4035 consdata = SCIPconsGetData(cons);
4036 assert(consdata != NULL);
4037 assert(0 <= pos && pos < consdata->nvars);
4038 assert(!SCIPisZero(scip, newval));
4039
4040 var = consdata->vars[pos];
4041 val = consdata->vals[pos];
4042 assert(var != NULL);
4044
4045 locked = FALSE;
4046 for( i = 0; i < NLOCKTYPES && !locked; i++ )
4047 locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
4048
4049 /* if necessary, update the rounding locks of the variable */
4050 if( locked && newval * val < 0.0 )
4051 {
4053
4054 /* remove rounding locks for variable with old coefficient */
4055 SCIP_CALL( unlockRounding(scip, cons, var, val) );
4056
4057 /* install rounding locks for variable with new coefficient */
4058 SCIP_CALL( lockRounding(scip, cons, var, newval) );
4059 }
4060
4061 /* change the value */
4062 consdata->vals[pos] = newval;
4063
4064 if( consdata->coefsorted )
4065 {
4066 if( pos > 0 )
4067 consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos - 1, pos) <= 0);
4068 if( consdata->coefsorted && pos < consdata->nvars - 1 )
4069 consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos, pos + 1) <= 0);
4070 }
4071
4072 /* update minimum and maximum activities */
4073 if( SCIPconsIsTransformed(cons) )
4074 consdataUpdateChgCoef(scip, consdata, var, val, newval, TRUE);
4075
4076 /* mark the constraint for propagation */
4077 if( SCIPconsIsTransformed(cons) )
4078 {
4080 }
4081
4082 consdata->boundstightened = 0;
4083 consdata->presolved = FALSE;
4084 consdata->validsignature = consdata->validsignature && (newval * val > 0.0);
4085 consdata->changed = TRUE;
4086 consdata->normalized = FALSE;
4087 consdata->upgradetried = FALSE;
4088 consdata->cliquesadded = FALSE;
4089 consdata->implsadded = FALSE;
4090 consdata->rangedrowpropagated = 0;
4091
4092 return SCIP_OKAY;
4093}
4094
4095/** scales a linear constraint with a constant scalar */
4096static
4098 SCIP* scip, /**< SCIP data structure */
4099 SCIP_CONS* cons, /**< linear constraint to scale */
4100 SCIP_Real scalar /**< value to scale constraint with */
4101 )
4102{
4103 SCIP_CONSDATA* consdata;
4104 SCIP_Real newval;
4105 SCIP_Real absscalar;
4106 int i;
4107
4108 assert(scip != NULL);
4109 assert(cons != NULL);
4110
4111 consdata = SCIPconsGetData(cons);
4112 assert(consdata != NULL);
4113 assert(consdata->row == NULL);
4114 assert(!SCIPisEQ(scip, scalar, 1.0));
4115
4116 if( (!SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -consdata->lhs * scalar))
4117 || (!SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, consdata->rhs * scalar)) )
4118 {
4119 SCIPwarningMessage(scip, "skipped scaling for linear constraint <%s> to avoid numerical troubles (scalar: %.15g)\n",
4120 SCIPconsGetName(cons), scalar);
4121
4122 return SCIP_OKAY;
4123 }
4124
4125 /* scale the coefficients */
4126 for( i = consdata->nvars - 1; i >= 0; --i )
4127 {
4128 newval = scalar * consdata->vals[i];
4129
4130 /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4131 * flooring down our new value
4132 */
4133 if( SCIPisScalingIntegral(scip, consdata->vals[i], scalar) )
4134 newval = SCIPfeasFloor(scip, newval + 0.5);
4135
4136 if( SCIPisZero(scip, newval) )
4137 {
4138 SCIPwarningMessage(scip, "coefficient %.15g of variable <%s> in linear constraint <%s> scaled to zero (scalar: %.15g)\n",
4139 consdata->vals[i], SCIPvarGetName(consdata->vars[i]), SCIPconsGetName(cons), scalar);
4140 SCIP_CALL( delCoefPos(scip, cons, i) );
4141 }
4142 else
4143 consdata->vals[i] = newval;
4144 }
4145
4146 /* scale the sides */
4147 if( scalar < 0.0 )
4148 {
4149 SCIP_Real lhs;
4150
4151 lhs = consdata->lhs;
4152 consdata->lhs = -consdata->rhs;
4153 consdata->rhs = -lhs;
4154 }
4155 absscalar = REALABS(scalar);
4156 if( !SCIPisInfinity(scip, -consdata->lhs) )
4157 {
4158 newval = absscalar * consdata->lhs;
4159
4160 /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4161 * flooring down our new value
4162 */
4163 if( SCIPisScalingIntegral(scip, consdata->lhs, absscalar) )
4164 consdata->lhs = SCIPfeasFloor(scip, newval + 0.5);
4165 else
4166 consdata->lhs = newval;
4167 }
4168 if( !SCIPisInfinity(scip, consdata->rhs) )
4169 {
4170 newval = absscalar * consdata->rhs;
4171
4172 /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasCeil, we subtract 0.5 before ceiling up
4173 * our new value
4174 */
4175 if( SCIPisScalingIntegral(scip, consdata->rhs, absscalar) )
4176 consdata->rhs = SCIPfeasCeil(scip, newval - 0.5);
4177 else
4178 consdata->rhs = newval;
4179 }
4180
4182 consdata->cliquesadded = FALSE;
4183 consdata->implsadded = FALSE;
4184
4185 return SCIP_OKAY;
4186}
4187
4188/** perform deletion of variables in all constraints of the constraint handler */
4189static
4191 SCIP* scip, /**< SCIP data structure */
4192 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4193 SCIP_CONS** conss, /**< array of constraints */
4194 int nconss /**< number of constraints */
4195 )
4196{
4197 SCIP_CONSDATA* consdata;
4198 int i;
4199 int v;
4200
4201 assert(scip != NULL);
4202 assert(conshdlr != NULL);
4203 assert(conss != NULL);
4204 assert(nconss >= 0);
4206
4207 /* iterate over all constraints */
4208 for( i = 0; i < nconss; i++ )
4209 {
4210 consdata = SCIPconsGetData(conss[i]);
4211
4212 /* constraint is marked, that some of its variables were deleted */
4213 if( consdata->varsdeleted )
4214 {
4215 /* iterate over all variables of the constraint and delete them from the constraint */
4216 for( v = consdata->nvars - 1; v >= 0; --v )
4217 {
4218 if( SCIPvarIsDeleted(consdata->vars[v]) )
4219 {
4220 SCIP_CALL( delCoefPos(scip, conss[i], v) );
4221 }
4222 }
4223 consdata->varsdeleted = FALSE;
4224 }
4225 }
4226
4227 return SCIP_OKAY;
4228}
4229
4230
4231/** normalizes a linear constraint with the following rules:
4232 * - if all coefficients have them same absolute value, change them to (-)1.0
4233 * - multiplication with +1 or -1:
4234 * Apply the following rules in the given order, until the sign of the factor is determined. Later rules only apply,
4235 * if the current rule doesn't determine the sign):
4236 * 1. the right hand side must not be negative
4237 * 2. the right hand side must not be infinite
4238 * 3. the absolute value of the right hand side must be greater than that of the left hand side
4239 * 4. the number of positive coefficients must not be smaller than the number of negative coefficients
4240 * 5. multiply with +1
4241 * - rationals to integrals
4242 * Try to identify a rational representation of the fractional coefficients, and multiply all coefficients
4243 * by the smallest common multiple of all denominators to get integral coefficients.
4244 * Forbid large denominators due to numerical stability.
4245 * - division by greatest common divisor
4246 * If all coefficients are integral, divide them by the greatest common divisor.
4247 */
4248static
4250 SCIP* scip, /**< SCIP data structure */
4251 SCIP_CONS* cons, /**< linear constraint to normalize */
4252 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
4253 )
4254{
4255 SCIP_CONSDATA* consdata;
4256 SCIP_Real* vals;
4257 SCIP_Longint scm;
4258 SCIP_Longint nominator;
4259 SCIP_Longint denominator;
4260 SCIP_Longint gcd;
4261 SCIP_Longint maxmult;
4262 SCIP_Real epsilon;
4263 SCIP_Real feastol;
4264 SCIP_Real maxabsval;
4265 SCIP_Real minabsval;
4266 SCIP_Bool success;
4267 SCIP_Bool onlyintegral;
4268 int nvars;
4269 int mult;
4270 int nposcoeffs;
4271 int nnegcoeffs;
4272 int i;
4273 int v;
4274
4275 assert(scip != NULL);
4276 assert(cons != NULL);
4277 assert(infeasible != NULL);
4278
4279 *infeasible = FALSE;
4280
4281 /* we must not change a modifiable constraint in any way */
4282 if( SCIPconsIsModifiable(cons) )
4283 return SCIP_OKAY;
4284
4285 /* get constraint data */
4286 consdata = SCIPconsGetData(cons);
4287 assert(consdata != NULL);
4288
4289 /* check, if the constraint is already normalized */
4290 if( consdata->normalized )
4291 return SCIP_OKAY;
4292
4293 /* get coefficient arrays */
4294 vals = consdata->vals;
4295 nvars = consdata->nvars;
4296 assert(nvars == 0 || vals != NULL);
4297
4298 if( nvars == 0 )
4299 {
4300 consdata->normalized = TRUE;
4301 return SCIP_OKAY;
4302 }
4303
4304 assert(vals != NULL);
4305
4306 /* get maximal and minimal absolute coefficient */
4307 maxabsval = consdataGetMaxAbsval(consdata);
4308 minabsval = consdataGetMinAbsval(consdata);
4309
4310 /* return if scaling by maxval will eliminate coefficients */
4311 if( SCIPisZero(scip, minabsval/maxabsval) )
4312 return SCIP_OKAY;
4313
4314 /* check if all coefficients are in absolute value equal, and not 1.0 */
4315 if( !SCIPisEQ(scip, maxabsval, 1.0) )
4316 {
4317 SCIP_Bool abscoefsequ;
4318
4319 abscoefsequ = TRUE;
4320
4321 for( v = nvars - 1; v >= 0; --v )
4322 {
4323 if( !SCIPisEQ(scip, REALABS(vals[v]), maxabsval) )
4324 {
4326 break;
4327 }
4328 }
4329
4330 /* all coefficients are in absolute value equal, so change them to (-)1.0 */
4331 if( abscoefsequ )
4332 {
4333 SCIPdebugMsg(scip, "divide linear constraint with %g, because all coefficients are in absolute value the same\n", maxabsval);
4335 SCIP_CALL( scaleCons(scip, cons, 1/maxabsval) );
4336
4337 if( consdata->validmaxabsval )
4338 {
4339 if( !SCIPisEQ(scip, consdata->maxabsval, 1.0) )
4340 consdata->maxabsval = 1.0;
4341 if( !SCIPisEQ(scip, consdata->minabsval, 1.0) )
4342 consdata->minabsval = 1.0;
4343
4344 maxabsval = 1.0;
4345 }
4346 else
4347 {
4348 /* get maximal absolute coefficient */
4349 maxabsval = consdataGetMaxAbsval(consdata);
4350 }
4351
4352 /* get new consdata information, because scaleCons() might have deleted variables */
4353 vals = consdata->vals;
4354 nvars = consdata->nvars;
4355
4356 assert(nvars == 0 || vals != NULL);
4357 }
4358 }
4359
4360 /* nvars might have changed */
4361 if( nvars == 0 )
4362 {
4363 consdata->normalized = TRUE;
4364 return SCIP_OKAY;
4365 }
4366
4367 assert(vals != NULL);
4368
4369 /* calculate the maximal multiplier for common divisor calculation:
4370 * |p/q - val| < epsilon and q < feastol/epsilon => |p - q*val| < feastol
4371 * which means, a value of feastol/epsilon should be used as maximal multiplier;
4372 * additionally, we don't want to scale the constraint if this would lead to too
4373 * large coefficients
4374 */
4375 epsilon = SCIPepsilon(scip) * 0.9; /* slightly decrease epsilon to be safe in rational conversion below */
4376 feastol = SCIPfeastol(scip);
4377 maxmult = (SCIP_Longint)(feastol/epsilon + feastol);
4378
4379 if( !consdata->hasnonbinvalid )
4380 consdataCheckNonbinvar(consdata);
4381
4382 /* if all variables are of integral type we will allow a greater multiplier */
4383 if( !consdata->hascontvar )
4384 maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEFINTEGER / MAX(maxabsval, 1.0))); /*lint !e835*/
4385 else
4386 maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEF / MAX(maxabsval, 1.0))); /*lint !e835*/
4387
4388 /*
4389 * multiplication with +1 or -1
4390 */
4391 mult = 0;
4392
4393 /* 1. the right hand side must not be negative */
4394 if( SCIPisPositive(scip, consdata->lhs) )
4395 mult = +1;
4396 else if( SCIPisNegative(scip, consdata->rhs) )
4397 mult = -1;
4398
4399 if( mult == 0 )
4400 {
4401 /* 2. the right hand side must not be infinite */
4402 if( SCIPisInfinity(scip, -consdata->lhs) )
4403 mult = +1;
4404 else if( SCIPisInfinity(scip, consdata->rhs) )
4405 mult = -1;
4406 }
4407
4408 if( mult == 0 )
4409 {
4410 /* 3. the absolute value of the right hand side must be greater than that of the left hand side */
4411 if( SCIPisGT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4412 mult = +1;
4413 else if( SCIPisLT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4414 mult = -1;
4415 }
4416
4417 if( mult == 0 )
4418 {
4419 /* 4. the number of positive coefficients must not be smaller than the number of negative coefficients */
4420 nposcoeffs = 0;
4421 nnegcoeffs = 0;
4422 for( i = 0; i < nvars; ++i )
4423 {
4424 if( vals[i] > 0.0 )
4425 nposcoeffs++;
4426 else
4427 nnegcoeffs++;
4428 }
4429 if( nposcoeffs > nnegcoeffs )
4430 mult = +1;
4431 else if( nposcoeffs < nnegcoeffs )
4432 mult = -1;
4433 }
4434
4435 if( mult == 0 )
4436 {
4437 /* 5. multiply with +1 */
4438 mult = +1;
4439 }
4440
4441 assert(mult == +1 || mult == -1);
4442 if( mult == -1 )
4443 {
4444 /* scale the constraint with -1 */
4445 SCIPdebugMsg(scip, "multiply linear constraint with -1.0\n");
4447 SCIP_CALL( scaleCons(scip, cons, -1.0) );
4448
4449 /* scalecons() can delete variables, but scaling with -1 should not do that */
4450 assert(nvars == consdata->nvars);
4451 }
4452
4453 /*
4454 * rationals to integrals
4455 *
4456 * @todo try scaling only on behalf of non-continuous variables
4457 */
4458 success = TRUE;
4459 scm = 1;
4460 for( i = 0; i < nvars && success && scm <= maxmult; ++i )
4461 {
4462 if( !SCIPisIntegral(scip, vals[i]) )
4463 {
4464 /* epsilon has been slightly decreased above - to be on the safe side */
4465 success = SCIPrealToRational(vals[i], -epsilon, epsilon , maxmult, &nominator, &denominator);
4466 if( success )
4468 }
4469 }
4470 assert(scm >= 1);
4471
4472 /* it might be that we have really big coefficients, but all are integral, in that case we want to divide them by
4473 * their greatest common divisor
4474 */
4476 if( scm == 1 )
4477 {
4478 for( i = nvars - 1; i >= 0; --i )
4479 {
4480 if( !SCIPisIntegral(scip, vals[i]) )
4481 {
4483 break;
4484 }
4485 }
4486 }
4487
4488 success = success && (scm <= maxmult || (scm == 1 && onlyintegral));
4489 if( success && scm != 1 )
4490 {
4491 /* scale the constraint with the smallest common multiple of all denominators */
4492 SCIPdebugMsg(scip, "scale linear constraint with %" SCIP_LONGINT_FORMAT " to make coefficients integral\n", scm);
4494 SCIP_CALL( scaleCons(scip, cons, (SCIP_Real)scm) );
4495
4496 if( consdata->validmaxabsval )
4497 {
4498 consdata->maxabsval *= REALABS((SCIP_Real)scm);
4499 if( !SCIPisIntegral(scip, consdata->maxabsval) )
4500 {
4501 consdata->validmaxabsval = FALSE;
4502 consdata->maxabsval = SCIP_INVALID;
4503 consdataCalcMaxAbsval(consdata);
4504 }
4505 }
4506
4507 if( consdata->validminabsval )
4508 {
4509 consdata->minabsval *= REALABS((SCIP_Real)scm);
4510 if( !SCIPisIntegral(scip, consdata->minabsval) )
4511 {
4512 consdata->validminabsval = FALSE;
4513 consdata->minabsval = SCIP_INVALID;
4514 consdataCalcMinAbsval(consdata);
4515 }
4516 }
4517
4518 /* get new consdata information, because scalecons() might have deleted variables */
4519 vals = consdata->vals;
4520 nvars = consdata->nvars;
4521 assert(nvars == 0 || vals != NULL);
4522 }
4523
4524 /*
4525 * division by greatest common divisor
4526 */
4527 if( success && nvars >= 1 )
4528 {
4529 /* all coefficients are integral: divide them by their greatest common divisor */
4530 assert(SCIPisIntegral(scip, vals[0]));
4531
4532 gcd = (SCIP_Longint)(REALABS(vals[0]) + feastol);
4533 for( i = 1; i < nvars && gcd > 1; ++i )
4534 {
4535 assert(SCIPisIntegral(scip, vals[i]));
4536 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[i]) + feastol));
4537 }
4538
4539 if( gcd > 1 )
4540 {
4541 /* since the lhs/rhs is not respected for gcd calculation it can happen that we detect infeasibility */
4542 if( !consdata->hascontvar && onlyintegral )
4543 {
4544 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) && !SCIPisFeasIntegral(scip, consdata->rhs / gcd) )
4545 {
4546 *infeasible = TRUE;
4547
4548 SCIPdebugMsg(scip, "detected infeasibility of constraint after scaling with gcd=%" SCIP_LONGINT_FORMAT ":\n", gcd);
4550
4551 return SCIP_OKAY;
4552 }
4553 }
4554
4555 /* divide the constraint by the greatest common divisor of the coefficients */
4556 SCIPdebugMsg(scip, "divide linear constraint by greatest common divisor %" SCIP_LONGINT_FORMAT "\n", gcd);
4558 SCIP_CALL( scaleCons(scip, cons, 1.0/(SCIP_Real)gcd) );
4559
4560 if( consdata->validmaxabsval )
4561 {
4562 consdata->maxabsval /= REALABS((SCIP_Real)gcd);
4563 }
4564 if( consdata->validminabsval )
4565 {
4566 consdata->minabsval /= REALABS((SCIP_Real)gcd);
4567 }
4568 }
4569 }
4570
4571 /* mark constraint to be normalized */
4572 consdata->normalized = TRUE;
4573
4574 SCIPdebugMsg(scip, "normalized constraint:\n");
4576
4577 return SCIP_OKAY;
4578}
4579
4580/** replaces multiple occurrences of a variable by a single coefficient */
4581static
4583 SCIP* scip, /**< SCIP data structure */
4584 SCIP_CONS* cons /**< linear constraint */
4585 )
4586{
4587 SCIP_CONSDATA* consdata;
4588 SCIP_VAR* var;
4589 SCIP_Real valsum;
4590 int v;
4591
4592 assert(scip != NULL);
4593 assert(cons != NULL);
4594
4595 consdata = SCIPconsGetData(cons);
4596 assert(consdata != NULL);
4597
4598 if( consdata->merged )
4599 return SCIP_OKAY;
4600
4601 /* sort the constraint */
4602 SCIP_CALL( consdataSort(scip, consdata) );
4603
4604 /* go backwards through the constraint looking for multiple occurrences of the same variable;
4605 * backward direction is necessary, since delCoefPos() modifies the given position and
4606 * the subsequent ones
4607 */
4608 v = consdata->nvars-1;
4609 while( v >= 1 )
4610 {
4611 var = consdata->vars[v];
4612 if( consdata->vars[v-1] == var )
4613 {
4614 valsum = consdata->vals[v];
4615 do
4616 {
4617 SCIP_CALL( delCoefPos(scip, cons, v) );
4618 --v;
4619 valsum += consdata->vals[v];
4620 }
4621 while( v >= 1 && consdata->vars[v-1] == var );
4622
4623 /* modify the last existing occurrence of the variable */
4624 assert(consdata->vars[v] == var);
4625 if( SCIPisZero(scip, valsum) )
4626 {
4627 SCIP_CALL( delCoefPos(scip, cons, v) );
4628
4629 /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
4630 * delta needs to be recalculated on the next real propagation
4631 */
4632 if( consdata->maxactdeltavar == var )
4633 {
4634 consdata->maxactdelta = SCIP_INVALID;
4635 consdata->maxactdeltavar = NULL;
4636 }
4637 }
4638 else
4639 {
4640 SCIP_CALL( chgCoefPos(scip, cons, v, valsum) );
4641 }
4642 }
4643 --v;
4644 }
4645
4646 consdata->merged = TRUE;
4647
4648 return SCIP_OKAY;
4649}
4650
4651/** replaces all fixed and aggregated variables by their non-fixed counterparts */
4652static
4654 SCIP* scip, /**< SCIP data structure */
4655 SCIP_CONS* cons, /**< linear constraint */
4656 SCIP_Bool* infeasible /**< pointer to store if infeasibility is detected; or NULL if this
4657 * information is not needed; in this case, we apply all fixings
4658 * instead of stopping after the first infeasible one */
4659 )
4660{
4661 SCIP_CONSDATA* consdata;
4662 SCIP_VAR* var;
4664 SCIP_Real val;
4665 SCIP_Real* aggrscalars;
4666 SCIP_Real fixedval;
4667 SCIP_Real aggrconst;
4668 int v;
4669 int naggrvars;
4670 int i;
4671
4672 assert(scip != NULL);
4673 assert(cons != NULL);
4674
4675 if( infeasible != NULL )
4676 *infeasible = FALSE;
4677
4678 consdata = SCIPconsGetData(cons);
4679 assert(consdata != NULL);
4680
4681 if( consdata->eventdata == NULL )
4682 {
4683 SCIP_CONSHDLR* conshdlr;
4684 SCIP_CONSHDLRDATA* conshdlrdata;
4685
4686 conshdlr = SCIPconsGetHdlr(cons);
4687 assert(conshdlr != NULL);
4688
4689 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4690 assert(conshdlrdata != NULL);
4691
4692 /* catch bound change events of variables */
4693 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
4694 assert(consdata->eventdata != NULL);
4695 }
4696
4697 if( !consdata->removedfixings )
4698 {
4699 SCIP_Real lhssubtrahend;
4700 SCIP_Real rhssubtrahend;
4701
4702 /* if an unmodifiable row has been added to the LP, then we cannot apply fixing anymore (cannot change a row)
4703 * this should not happen, as applyFixings is called in addRelaxation() before creating and adding a row
4704 */
4705 assert(consdata->row == NULL || !SCIProwIsInLP(consdata->row) || SCIProwIsModifiable(consdata->row));
4706
4707 lhssubtrahend = 0.0;
4708 rhssubtrahend = 0.0;
4709
4710 SCIPdebugMsg(scip, "applying fixings:\n");
4712
4713 v = 0;
4714 while( v < consdata->nvars )
4715 {
4716 var = consdata->vars[v];
4717 val = consdata->vals[v];
4719
4720 switch( SCIPvarGetStatus(var) )
4721 {
4723 SCIPerrorMessage("original variable in transformed linear constraint\n");
4724 return SCIP_INVALIDDATA;
4725
4728 ++v;
4729 break;
4730
4734 if( !SCIPisInfinity(scip, -consdata->lhs) )
4735 {
4737 {
4738 if( val * fixedval > 0.0 )
4739 {
4740 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
4741 }
4742 else
4743 {
4744 if( infeasible != NULL )
4745 {
4746 /* if lhs gets infinity it means that the problem is infeasible */
4747 *infeasible = TRUE;
4748 return SCIP_OKAY;
4749 }
4750 else
4751 {
4753 }
4754 }
4755 }
4756 else
4757 lhssubtrahend += val * fixedval;
4758 }
4759 if( !SCIPisInfinity(scip, consdata->rhs) )
4760 {
4762 {
4763 if( val * fixedval > 0.0 )
4764 {
4765 if( infeasible != NULL )
4766 {
4767 /* if rhs gets -infinity it means that the problem is infeasible */
4768 *infeasible = TRUE;
4769 return SCIP_OKAY;
4770 }
4771 else
4772 {
4773 SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
4774 }
4775 }
4776 else
4777 {
4779 }
4780 }
4781 else
4782 rhssubtrahend += val * fixedval;
4783 }
4784 SCIP_CALL( delCoefPos(scip, cons, v) );
4785 break;
4786
4788 {
4790 SCIP_Real activescalar = val * SCIPvarGetAggrScalar(var);
4791 SCIP_Real activeconstant = val * SCIPvarGetAggrConstant(var);
4792
4793 assert(activevar != NULL);
4795 assert(activevar != NULL);
4796
4798 {
4800 }
4801
4803 {
4804 if( !SCIPisInfinity(scip, -consdata->lhs) )
4806 if( !SCIPisInfinity(scip, consdata->rhs) )
4808 }
4809
4810 SCIP_CALL( delCoefPos(scip, cons, v) );
4811 break;
4812 }
4815 naggrvars = SCIPvarGetMultaggrNVars(var);
4818 for( i = 0; i < naggrvars; ++i )
4819 {
4820 SCIP_CALL( addCoef(scip, cons, aggrvars[i], val * aggrscalars[i]) );
4821 }
4823
4824 if( !SCIPisInfinity(scip, -consdata->lhs) )
4825 lhssubtrahend += val * aggrconst;
4826 if( !SCIPisInfinity(scip, consdata->rhs) )
4827 rhssubtrahend += val * aggrconst;
4828
4829 SCIP_CALL( delCoefPos(scip, cons, v) );
4830 break;
4831
4835
4836 if( !SCIPisInfinity(scip, -consdata->lhs) )
4837 lhssubtrahend += val * aggrconst;
4838 if( !SCIPisInfinity(scip, consdata->rhs) )
4839 rhssubtrahend += val * aggrconst;
4840
4841 SCIP_CALL( delCoefPos(scip, cons, v) );
4842 break;
4843
4844 default:
4845 SCIPerrorMessage("unknown variable status\n");
4846 SCIPABORT();
4847 return SCIP_INVALIDDATA; /*lint !e527*/
4848 }
4849 }
4850
4851 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->lhs) )
4852 {
4853 /* for large numbers that are relatively equal, substraction can lead to cancellation,
4854 * causing wrong fixings of other variables --> better use a real zero here;
4855 * for small numbers, polishing the difference might lead to wrong results -->
4856 * better use the exact difference in this case
4857 */
4858 if( SCIPisEQ(scip, lhssubtrahend, consdata->lhs) && SCIPisFeasGE(scip, REALABS(lhssubtrahend), 1.0) )
4859 {
4860 SCIP_CALL( chgLhs(scip, cons, 0.0) );
4861 }
4862 else
4863 {
4864 SCIP_CALL( chgLhs(scip, cons, consdata->lhs - lhssubtrahend) );
4865 }
4866 }
4867 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs))
4868 {
4869 /* for large numbers that are relatively equal, substraction can lead to cancellation,
4870 * causing wrong fixings of other variables --> better use a real zero here;
4871 * for small numbers, polishing the difference might lead to wrong results -->
4872 * better use the exact difference in this case
4873 */
4874 if( SCIPisEQ(scip, rhssubtrahend, consdata->rhs ) && SCIPisFeasGE(scip, REALABS(rhssubtrahend), 1.0) )
4875 {
4876 SCIP_CALL( chgRhs(scip, cons, 0.0) );
4877 }
4878 else
4879 {
4880 SCIP_CALL( chgRhs(scip, cons, consdata->rhs - rhssubtrahend) );
4881 }
4882 }
4883 consdata->removedfixings = TRUE;
4884
4885 SCIPdebugMsg(scip, "after fixings:\n");
4887
4888 /* if aggregated variables have been replaced, multiple entries of the same variable are possible and we have
4889 * to clean up the constraint
4890 */
4891 SCIP_CALL( mergeMultiples(scip, cons) );
4892
4893 SCIPdebugMsg(scip, "after merging:\n");
4895 }
4896 assert(consdata->removedfixings);
4897
4898#ifndef NDEBUG
4899 /* check, if all fixings are applied */
4900 for( v = 0; v < consdata->nvars; ++v )
4901 assert(SCIPvarIsActive(consdata->vars[v]));
4902#endif
4903
4904 return SCIP_OKAY;
4905}
4906
4907/** for each variable in the linear constraint, except the inferred variable, adds one bound to the conflict analysis'
4908 * candidate store (bound depends on sign of coefficient and whether the left or right hand side was the reason for the
4909 * inference variable's bound change); the conflict analysis can be initialized with the linear constraint being the
4910 * conflict detecting constraint by using NULL as inferred variable
4911 */
4912static
4914 SCIP* scip, /**< SCIP data structure */
4915 SCIP_CONS* cons, /**< constraint that inferred the bound change */
4916 SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
4917 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4918 int inferpos, /**< position of the inferred variable in the vars array */
4919 SCIP_Bool reasonisrhs /**< is the right hand side responsible for the bound change? */
4920 )
4921{
4922 SCIP_CONSDATA* consdata;
4923 SCIP_VAR** vars;
4924 SCIP_Real* vals;
4925 int nvars;
4926 int i;
4927
4928 assert(scip != NULL);
4929 assert(cons != NULL);
4930
4931 consdata = SCIPconsGetData(cons);
4932
4933 assert(consdata != NULL);
4934
4935 vars = consdata->vars;
4936 vals = consdata->vals;
4937 nvars = consdata->nvars;
4938
4939 assert(vars != NULL || nvars == 0);
4940 assert(vals != NULL || nvars == 0);
4941
4942 assert(-1 <= inferpos && inferpos < nvars);
4943 assert((infervar == NULL) == (inferpos == -1));
4944 assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
4945
4946 /* for each variable, add the bound to the conflict queue, that is responsible for the minimal or maximal
4947 * residual value, depending on whether the left or right hand side is responsible for the bound change:
4948 * - if the right hand side is the reason, the minimal residual activity is responsible
4949 * - if the left hand side is the reason, the maximal residual activity is responsible
4950 */
4951
4952 /* if the variable is integral we only need to add reason bounds until the propagation could be applied */
4954 {
4955 SCIP_Real minresactivity;
4956 SCIP_Real maxresactivity;
4957 SCIP_Bool minisrelax;
4958 SCIP_Bool maxisrelax;
4959 SCIP_Bool isminsettoinfinity;
4960 SCIP_Bool ismaxsettoinfinity;
4961
4964
4965 /* calculate the minimal and maximal global activity of all other variables involved in the constraint */
4966 if( infervar != NULL )
4967 {
4968 assert(vals != NULL); /* for flexelint */
4969 if( reasonisrhs )
4972 else
4975 }
4976 else
4977 {
4978 if( reasonisrhs )
4981 else
4984 }
4985
4986 /* we can only do something clever, if the residual activity is finite and not relaxed */
4987 if( (reasonisrhs && !isminsettoinfinity && !minisrelax) || (!reasonisrhs && !ismaxsettoinfinity && !maxisrelax) ) /*lint !e644*/
4988 {
4989 SCIP_Real rescap;
4990 SCIP_Bool resactisinf;
4991
4993
4994 /* calculate the residual capacity that would be left, if the variable would be set to one more / one less
4995 * than its inferred bound
4996 */
4997 if( infervar != NULL )
4998 {
4999 assert(vals != NULL); /* for flexelint */
5000
5001 if( reasonisrhs )
5002 {
5003 if( SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
5004 {
5007 resactisinf = TRUE;
5008 }
5009 rescap = consdata->rhs - minresactivity;
5010 }
5011 else
5012 {
5013 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
5014 {
5017 resactisinf = TRUE;
5018 }
5019 rescap = consdata->lhs - maxresactivity;
5020 }
5021
5022 if( reasonisrhs == (vals[inferpos] > 0.0) )
5023 rescap -= vals[inferpos] * (SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) + 1.0);
5024 else
5025 rescap -= vals[inferpos] * (SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) - 1.0);
5026 }
5027 else
5028 rescap = (reasonisrhs ? consdata->rhs - minresactivity : consdata->lhs - maxresactivity);
5029
5030 if( !resactisinf )
5031 {
5032 /* now add bounds as reasons until the residual capacity is exceeded */
5033 for( i = 0; i < nvars; ++i )
5034 {
5035 assert( vars != NULL && vals != NULL ); /* for lint */
5036
5037 /* zero coefficients and the inferred variable can be ignored */
5038 if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
5039 continue;
5040
5041 /* check if the residual capacity is exceeded */
5044 break;
5045
5046 /* update the residual capacity due to the local bound of this variable */
5047 if( reasonisrhs == (vals[i] > 0.0) )
5048 {
5049 /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound */
5050 SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
5051 rescap -= vals[i] * (SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetLbGlobal(vars[i]));
5052 }
5053 else
5054 {
5055 /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound */
5056 SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
5057 rescap -= vals[i] * (SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetUbGlobal(vars[i]));
5058 }
5059 }
5060 return SCIP_OKAY;
5061 }
5062 }
5063 }
5064
5065 /* for a bound change on a continuous variable, all locally changed bounds are responsible */
5066 for( i = 0; i < nvars; ++i )
5067 {
5068 assert(vars != NULL); /* for flexelint */
5069 assert(vals != NULL); /* for flexelint */
5070
5071 /* zero coefficients and the inferred variable can be ignored */
5072 if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
5073 continue;
5074
5075 if( reasonisrhs == (vals[i] > 0.0) )
5076 {
5077 /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound is responsible */
5078 SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
5079 }
5080 else
5081 {
5082 /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound is responsible */
5083 SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
5084 }
5085 }
5086
5087 return SCIP_OKAY;
5088}
5089
5090/** for each variable in the linear ranged row constraint, except the inferred variable, adds the bounds of all fixed
5091 * variables to the conflict analysis' candidate store; the conflict analysis can be initialized
5092 * with the linear constraint being the conflict detecting constraint by using NULL as inferred variable
5093 */
5094static
5096 SCIP* scip, /**< SCIP data structure */
5097 SCIP_CONS* cons, /**< constraint that inferred the bound change */
5098 SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
5099 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
5100 int inferpos /**< position of the inferred variable in the vars array, or -1 */
5101 )
5102{
5103 SCIP_CONSDATA* consdata;
5104 SCIP_VAR** vars;
5105 int nvars;
5106 int v;
5107
5108 assert(scip != NULL);
5109 assert(cons != NULL);
5110
5111 consdata = SCIPconsGetData(cons);
5112 assert(consdata != NULL);
5113 vars = consdata->vars;
5114 nvars = consdata->nvars;
5115 assert(vars != NULL || nvars == 0);
5116 assert(-1 <= inferpos && inferpos < nvars);
5117 assert((infervar == NULL) == (inferpos == -1));
5118 assert(inferpos == -1 || vars != NULL);
5119 assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
5120
5121 /* collect all fixed variables */
5122 for( v = nvars - 1; v >= 0; --v )
5123 {
5124 assert(vars != NULL); /* for flexelint */
5125
5126 /* need to add old bounds before propagation of inferrence variable */
5127 if( vars[v] == infervar )
5128 {
5129 assert(vars[v] != NULL);
5130
5132 {
5133 /* @todo get boundchange index before this last boundchange and correct the index */
5134 SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5135 }
5136
5138 {
5139 /* @todo get boundchange index before this last boundchange and correct the index */
5140 SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5141 }
5142
5143 continue;
5144 }
5145
5146 /* check for fixed variables */
5147 if( SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE)) )
5148 {
5149 /* add all bounds of fixed variables which lead to the boundchange of the given inference variable */
5150 SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5151 SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5152 }
5153 }
5154
5155 return SCIP_OKAY;
5156}
5157
5158/** add reasoning variables to conflict candidate queue which led to the conflict */
5159static
5161 SCIP* scip, /**< SCIP data structure */
5162 SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5163 int nvars, /**< number of variables reasoning the infeasibility */
5164 SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5165 SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5166 )
5167{
5168 int v;
5169
5170 assert(scip != NULL);
5171
5172 /* collect all variables for which the local bounds differ from their global bounds */
5173 for( v = nvars - 1; v >= 0; --v )
5174 {
5175 assert(vars != NULL);
5176
5177 /* check for local bound changes variables */
5179 {
5180 /* add conflict bound */
5182 }
5183
5185 {
5187 }
5188 }
5189
5190 if( var != NULL )
5191 {
5192 if( bound < SCIPvarGetLbLocal(var) )
5193 {
5195 }
5196
5197 if( bound > SCIPvarGetUbLocal(var) )
5198 {
5200 }
5201 }
5202
5203 return SCIP_OKAY;
5204}
5205
5206/** resolves a propagation on the given variable by supplying the variables needed for applying the corresponding
5207 * propagation rule (see propagateCons()):
5208 * (1) activity residuals of all other variables tighten bounds of single variable
5209 */
5210static
5212 SCIP* scip, /**< SCIP data structure */
5213 SCIP_CONS* cons, /**< constraint that inferred the bound change */
5214 SCIP_VAR* infervar, /**< variable that was deduced */
5215 INFERINFO inferinfo, /**< inference information */
5216 SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
5217 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
5218 SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
5219 )
5220{
5221 SCIP_CONSDATA* consdata;
5222 SCIP_VAR** vars;
5223#ifndef NDEBUG
5224 SCIP_Real* vals;
5225#endif
5226 int nvars;
5227 int inferpos;
5228
5229 assert(scip != NULL);
5230 assert(cons != NULL);
5231 assert(result != NULL);
5232
5233 consdata = SCIPconsGetData(cons);
5234 assert(consdata != NULL);
5235 vars = consdata->vars;
5236 nvars = consdata->nvars;
5237#ifndef NDEBUG
5238 vals = consdata->vals;
5239 assert(vars != NULL);
5240 assert(vals != NULL);
5241#endif
5242
5243 /* get the position of the inferred variable in the vars array */
5244 inferpos = inferInfoGetPos(inferinfo);
5245 if( inferpos >= nvars || vars[inferpos] != infervar )
5246 {
5247 /* find inference variable in constraint */
5248 /**@todo use a binary search here; the variables can be sorted by variable index */
5249 for( inferpos = 0; inferpos < nvars && vars[inferpos] != infervar; ++inferpos )
5250 {}
5251 }
5254 assert(!SCIPisZero(scip, vals[inferpos]));
5255
5256 switch( inferInfoGetProprule(inferinfo) )
5257 {
5258 case PROPRULE_1_RHS:
5259 /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5260 * constraint (only taking the other variables into account) didn't leave enough space for a larger
5261 * domain in order to not exceed the right hand side of the inequality
5262 */
5263 assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_UPPER));
5264 SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, TRUE) );
5266 break;
5267
5268 case PROPRULE_1_LHS:
5269 /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5270 * constraint (only taking the other variables into account) didn't leave enough space for a larger
5271 * domain in order to not fall below the left hand side of the inequality
5272 */
5273 assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_LOWER));
5274 SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, FALSE) );
5276 break;
5277
5279 /* the bound of the variable was tightened, because some variables were already fixed and the leftover only allow
5280 * the given inference variable to their bounds in this given ranged row
5281 */
5282
5283 /* check that we really have a ranged row here */
5284 assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5285 SCIP_CALL( addConflictFixedVars(scip, cons, infervar, bdchgidx, inferpos) );
5287 break;
5288
5289 case PROPRULE_INVALID:
5290 default:
5291 SCIPerrorMessage("invalid inference information %d in linear constraint <%s> at position %d for %s bound of variable <%s>\n",
5292 inferInfoGetProprule(inferinfo), SCIPconsGetName(cons), inferInfoGetPos(inferinfo),
5293 boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(infervar));
5294 SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
5295 SCIPinfoMessage(scip, NULL, ";\n");
5296 return SCIP_INVALIDDATA;
5297 }
5298
5299 return SCIP_OKAY;
5300}
5301
5302/** analyzes conflicting bounds on given constraint, and adds conflict constraint to problem */
5303static
5305 SCIP* scip, /**< SCIP data structure */
5306 SCIP_CONS* cons, /**< conflict detecting constraint */
5307 SCIP_Bool reasonisrhs /**< is the right hand side responsible for the conflict? */
5308 )
5309{
5310 /* conflict analysis can only be applied in solving stage and if it is turned on */
5312 return SCIP_OKAY;
5313
5314 /* initialize conflict analysis */
5316
5317 /* add the conflicting bound for each variable of infeasible constraint to conflict candidate queue */
5319
5320 /* analyze the conflict */
5322
5323 return SCIP_OKAY;
5324}
5325
5326/** check if there is any hope of tightening some bounds */
5327static
5329 SCIP_CONS* cons /**< linear constraint */
5330 )
5331{
5332 SCIP_CONSDATA* consdata;
5333 int infcountmin;
5334 int infcountmax;
5335
5336 consdata = SCIPconsGetData(cons);
5337 assert(consdata != NULL);
5338
5339 infcountmin = consdata->minactivityneginf
5340 + consdata->minactivityposinf
5341 + consdata->minactivityneghuge
5342 + consdata->minactivityposhuge;
5343 infcountmax = consdata->maxactivityneginf
5344 + consdata->maxactivityposinf
5345 + consdata->maxactivityneghuge
5346 + consdata->maxactivityposhuge;
5347
5348 if( infcountmin > 1 && infcountmax > 1 )
5349 return FALSE;
5350
5351 return TRUE;
5352}
5353
5354/** tighten upper bound */
5355static
5357 SCIP* scip, /**< SCIP data structure */
5358 SCIP_CONS* cons, /**< linear constraint */
5359 int pos, /**< variable position */
5360 PROPRULE proprule, /**< propagation rule that deduced the value */
5361 SCIP_Real newub, /**< new upper bound */
5362 SCIP_Real oldub, /**< old upper bound */
5363 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5364 int* nchgbds, /**< pointer to count the total number of tightened bounds */
5365 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5366 )
5367{
5368 SCIP_CONSDATA* consdata;
5369 SCIP_VAR* var;
5370 SCIP_Real lb;
5371 SCIP_Bool infeasible;
5372 SCIP_Bool tightened;
5373
5374 assert(cons != NULL);
5376
5377 consdata = SCIPconsGetData(cons);
5378 assert(consdata != NULL);
5379 var = consdata->vars[pos];
5380 assert(var != NULL);
5381
5382 lb = SCIPvarGetLbLocal(var);
5384
5385 if( force || SCIPisUbBetter(scip, newub, lb, oldub) )
5386 {
5387 SCIP_VARTYPE vartype;
5388
5389 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
5390 SCIPconsGetName(cons), SCIPvarGetName(var), lb, oldub, consdata->vals[pos],
5391 QUAD_TO_DBL(consdata->minactivity), QUAD_TO_DBL(consdata->maxactivity), consdata->lhs, consdata->rhs, newub);
5392
5393 vartype = SCIPvarGetType(var);
5394
5395 /* tighten upper bound */
5396 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5397
5398 if( infeasible )
5399 {
5400 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5402
5403 /* analyze conflict */
5405
5406 *cutoff = TRUE;
5407 }
5408 else if( tightened )
5409 {
5411 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5413
5414 (*nchgbds)++;
5415
5416 /* if variable type was changed we might be able to upgrade the constraint */
5417 if( vartype != SCIPvarGetType(var) )
5418 consdata->upgradetried = FALSE;
5419 }
5420 }
5421 return SCIP_OKAY;
5422}
5423
5424/** tighten lower bound */
5425static
5427 SCIP* scip, /**< SCIP data structure */
5428 SCIP_CONS* cons, /**< linear constraint */
5429 int pos, /**< variable position */
5430 PROPRULE proprule, /**< propagation rule that deduced the value */
5431 SCIP_Real newlb, /**< new lower bound */
5432 SCIP_Real oldlb, /**< old lower bound */
5433 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5434 int* nchgbds, /**< pointer to count the total number of tightened bounds */
5435 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5436 )
5437{
5438 SCIP_CONSDATA* consdata;
5439 SCIP_VAR* var;
5440 SCIP_Real ub;
5441 SCIP_Bool infeasible;
5442 SCIP_Bool tightened;
5443
5444 assert(cons != NULL);
5446
5447 consdata = SCIPconsGetData(cons);
5448 assert(consdata != NULL);
5449 var = consdata->vars[pos];
5450 assert(var != NULL);
5451
5452 ub = SCIPvarGetUbLocal(var);
5454
5455 if( force || SCIPisLbBetter(scip, newlb, oldlb, ub) )
5456 {
5457 SCIP_VARTYPE vartype;
5458
5459 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
5460 SCIPconsGetName(cons), SCIPvarGetName(var), oldlb, ub, consdata->vals[pos],
5461 QUAD_TO_DBL(consdata->minactivity), QUAD_TO_DBL(consdata->maxactivity), consdata->lhs, consdata->rhs, newlb);
5462
5463 vartype = SCIPvarGetType(var);
5464
5465 /* tighten lower bound */
5466 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5467
5468 if( infeasible )
5469 {
5470 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5472
5473 /* analyze conflict */
5475
5476 *cutoff = TRUE;
5477 }
5478 else if( tightened )
5479 {
5481 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5483
5484 (*nchgbds)++;
5485
5486 /* if variable type was changed we might be able to upgrade the constraint */
5487 if( vartype != SCIPvarGetType(var) )
5488 consdata->upgradetried = FALSE;
5489 }
5490 }
5491 return SCIP_OKAY;
5492}
5493
5494/** tightens bounds of a single variable due to activity bounds (easy case) */
5495static
5497 SCIP* scip, /**< SCIP data structure */
5498 SCIP_CONS* cons, /**< linear constraint */
5499 int pos, /**< position of the variable in the vars array */
5500 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5501 int* nchgbds, /**< pointer to count the total number of tightened bounds */
5502 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5503 )
5504{
5505 SCIP_CONSDATA* consdata;
5506 SCIP_VAR* var;
5507 SCIP_Real val;
5508 SCIP_Real lb;
5509 SCIP_Real ub;
5510 SCIP_Real lhs;
5511 SCIP_Real rhs;
5512
5513 assert(scip != NULL);
5514 assert(cons != NULL);
5515 assert(cutoff != NULL);
5516 assert(nchgbds != NULL);
5517
5518 /* we cannot tighten variables' bounds, if the constraint may be not complete */
5519 if( SCIPconsIsModifiable(cons) )
5520 return SCIP_OKAY;
5521
5522 consdata = SCIPconsGetData(cons);
5523 assert(consdata != NULL);
5524 assert(0 <= pos && pos < consdata->nvars);
5525
5526 *cutoff = FALSE;
5527
5528 var = consdata->vars[pos];
5529 assert(var != NULL);
5530
5531 /* we cannot tighten bounds of multi-aggregated variables */
5533 return SCIP_OKAY;
5534
5535 val = consdata->vals[pos];
5536 lhs = consdata->lhs;
5537 rhs = consdata->rhs;
5538 assert(!SCIPisZero(scip, val));
5539 assert(!SCIPisInfinity(scip, lhs));
5540 assert(!SCIPisInfinity(scip, -rhs));
5541
5542 lb = SCIPvarGetLbLocal(var);
5543 ub = SCIPvarGetUbLocal(var);
5544 assert(SCIPisLE(scip, lb, ub));
5545
5546 /* recompute activities if needed */
5547 if( !consdata->validactivities )
5548 consdataCalcActivities(scip, consdata);
5549 assert(consdata->validactivities);
5550 if( !consdata->validminact )
5552 assert(consdata->validminact);
5553
5554 if( val > 0.0 )
5555 {
5556 /* check, if we can tighten the variable's upper bound */
5557 if( !SCIPisInfinity(scip, rhs) )
5558 {
5559 SCIP_Real slack;
5560 SCIP_Real alpha;
5561
5562 /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
5563 assert(consdata->validminact);
5564
5565 /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5566 if( SCIPisFeasLT(scip, rhs, QUAD_TO_DBL(consdata->minactivity)) )
5567 {
5568 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5569 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->minactivity), rhs);
5570
5571 *cutoff = TRUE;
5572 return SCIP_OKAY;
5573 }
5574
5575 slack = rhs - QUAD_TO_DBL(consdata->minactivity);
5576
5577 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5578 * it to zero
5579 */
5580 if( !SCIPisPositive(scip, slack) )
5581 slack = 0.0;
5582
5583 alpha = val * (ub - lb);
5585
5586 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5587 {
5588 SCIP_Real newub;
5589
5590 /* compute new upper bound */
5591 newub = lb + (slack / val);
5592
5593 SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_RHS, newub, ub, cutoff, nchgbds, force) );
5594
5595 if( *cutoff )
5596 {
5597 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5599
5600 return SCIP_OKAY;
5601 }
5602
5603 /* collect the new upper bound which is needed for the lower bound computation */
5604 ub = SCIPvarGetUbLocal(var);
5605 }
5606 }
5607
5608 /* check, if we can tighten the variable's lower bound */
5609 if( !SCIPisInfinity(scip, -lhs) )
5610 {
5611 SCIP_Real slack;
5612 SCIP_Real alpha;
5613
5614 /* make sure the max activity is reliable */
5615 if( !consdata->validmaxact )
5616 {
5618 }
5619 assert(consdata->validmaxact);
5620
5621 /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5622 if( SCIPisFeasLT(scip, QUAD_TO_DBL(consdata->maxactivity), lhs) )
5623 {
5624 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5625 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->maxactivity), lhs);
5626
5627 *cutoff = TRUE;
5628 return SCIP_OKAY;
5629 }
5630
5631 slack = QUAD_TO_DBL(consdata->maxactivity) - lhs;
5632
5633 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5634 * it to zero
5635 */
5636 if( !SCIPisPositive(scip, slack) )
5637 slack = 0.0;
5638
5639 alpha = val * (ub - lb);
5641
5642 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5643 {
5644 SCIP_Real newlb;
5645
5646 /* compute new lower bound */
5647 newlb = ub - (slack / val);
5648
5649 SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_LHS, newlb, lb, cutoff, nchgbds, force) );
5650
5651 if( *cutoff )
5652 {
5653 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5655
5656 return SCIP_OKAY;
5657 }
5658 }
5659 }
5660 }
5661 else
5662 {
5663 /* check, if we can tighten the variable's lower bound */
5664 if( !SCIPisInfinity(scip, rhs) )
5665 {
5666 SCIP_Real slack;
5667 SCIP_Real alpha;
5668
5669 /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
5670 assert(consdata->validminact);
5671
5672 /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5673 if( SCIPisFeasLT(scip, rhs, QUAD_TO_DBL(consdata->minactivity)) )
5674 {
5675 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5676 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->minactivity), rhs);
5677
5678 *cutoff = TRUE;
5679 return SCIP_OKAY;
5680 }
5681
5682 slack = rhs - QUAD_TO_DBL(consdata->minactivity);
5683
5684 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5685 * it to zero
5686 */
5687 if( !SCIPisPositive(scip, slack) )
5688 slack = 0.0;
5689
5690 alpha = val * (lb - ub);
5692
5693 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5694 {
5695 SCIP_Real newlb;
5696
5697 /* compute new lower bound */
5698 newlb = ub + slack / val;
5699
5700 SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_RHS, newlb, lb, cutoff, nchgbds, force) );
5701
5702 if( *cutoff )
5703 {
5704 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5706
5707 return SCIP_OKAY;
5708 }
5709 /* collect the new lower bound which is needed for the upper bound computation */
5710 lb = SCIPvarGetLbLocal(var);
5711 }
5712 }
5713
5714 /* check, if we can tighten the variable's upper bound */
5715 if( !SCIPisInfinity(scip, -lhs) )
5716 {
5717 SCIP_Real slack;
5718 SCIP_Real alpha;
5719
5720 /* make sure the max activity is reliable */
5721 if( !consdata->validmaxact )
5722 {
5724 }
5725 assert(consdata->validmaxact);
5726
5727 /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5728 if( SCIPisFeasLT(scip, QUAD_TO_DBL(consdata->maxactivity), lhs) )
5729 {
5730 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5731 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->maxactivity), lhs);
5732
5733 *cutoff = TRUE;
5734 return SCIP_OKAY;
5735 }
5736
5737 slack = QUAD_TO_DBL(consdata->maxactivity) - lhs;
5738
5739 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5740 * it to zero
5741 */
5742 if( !SCIPisPositive(scip, slack) )
5743 slack = 0.0;
5744
5745 alpha = val * (lb - ub);
5747
5748 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5749 {
5750 SCIP_Real newub;
5751
5752 /* compute new upper bound */
5753 newub = lb - (slack / val);
5754
5755 SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_LHS, newub, ub, cutoff, nchgbds, force) );
5756
5757 if( *cutoff )
5758 {
5759 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5761
5762 return SCIP_OKAY;
5763 }
5764 }
5765 }
5766 }
5767
5768 return SCIP_OKAY;
5769}
5770
5771/** analyzes conflicting bounds on given ranged row constraint, and adds conflict constraint to problem */
5772static
5774 SCIP* scip, /**< SCIP data structure */
5775 SCIP_CONS* cons, /**< conflict detecting constraint */
5776 SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5777 int nvars, /**< number of variables reasoning the infeasibility */
5778 SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5779 SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5780 )
5781{
5782#ifndef NDEBUG
5783 SCIP_CONSDATA* consdata;
5784
5785 assert(scip != NULL);
5786 assert(cons != NULL);
5787
5788 consdata = SCIPconsGetData(cons);
5789 assert(consdata != NULL);
5790 assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5791#endif
5792
5793 /* conflict analysis can only be applied in solving stage and if it is turned on */
5795 return SCIP_OKAY;
5796
5797 /* initialize conflict analysis */
5799
5800 /* add the conflicting fixed variables of this ranged row constraint to conflict candidate queue */
5802
5803 /* add reasoning variables to conflict candidate queue which led to the conflict */
5805
5806 /* analyze the conflict */
5808
5809 return SCIP_OKAY;
5810}
5811
5812/** propagate ranged rows
5813 *
5814 * Check ranged rows for possible solutions, possibly detect infeasibility, fix variables due to having only one possible
5815 * solution, tighten bounds if having only two possible solutions or add constraints which propagate a subset of
5816 * variables better.
5817 *
5818 * Example:
5819 * c1: 12 x1 + 9 x2 - x3 = 0 with x1, x2 free and 1 <= x3 <= 2
5820 *
5821 * x3 needs to be a multiple of 3, so the instance is infeasible.
5822 *
5823 * Example:
5824 * c1: 12 x1 + 9 x2 - x3 = 1 with x1, x2 free and 1 <= x3 <= 2
5825 *
5826 * The only possible value for x3 is 2, so the variable will be fixed.
5827 *
5828 * @todo add holes if possible
5829 */
5830static
5832 SCIP* scip, /**< SCIP data structure */
5833 SCIP_CONS* cons, /**< linear constraint */
5834 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
5835 int* nfixedvars, /**< pointer to count number of fixed variables */
5836 int* nchgbds, /**< pointer to count the number of bound changes */
5837 int* naddconss /**< pointer to count number of added constraints */
5838 )
5839{
5840 SCIP_CONSHDLRDATA* conshdlrdata;
5841 SCIP_CONSHDLR* conshdlr;
5842 SCIP_CONSDATA* consdata;
5844 SCIP_Real* infcheckvals;
5845 SCIP_Real minactinfvars;
5846 SCIP_Real maxactinfvars;
5847 SCIP_Real lb;
5848 SCIP_Real ub;
5849 SCIP_Real feastol;
5850 SCIP_Real fixedact;
5851 SCIP_Real lhs;
5852 SCIP_Real rhs;
5853 SCIP_Real absminbincoef;
5854 SCIP_Longint gcd;
5855 SCIP_Longint gcdtmp;
5856 SCIP_Bool minactinfvarsinvalid;
5857 SCIP_Bool maxactinfvarsinvalid;
5858 SCIP_Bool possiblegcd;
5859 SCIP_Bool gcdisone;
5860 SCIP_Bool addartconss;
5861 int ninfcheckvars;
5862 int nunfixedvars;
5863 int nfixedconsvars;
5864 int ncontvars;
5865 int pos;
5866 int v;
5867
5868 assert(scip != NULL);
5869 assert(cons != NULL);
5870 assert(cutoff != NULL);
5871 assert(nfixedvars != NULL);
5872 assert(nchgbds != NULL);
5873 assert(naddconss != NULL);
5874
5875 /* modifiable constraint can be changed so we do not have all necessary information */
5876 if( SCIPconsIsModifiable(cons) )
5877 return SCIP_OKAY;
5878
5879 consdata = SCIPconsGetData(cons);
5880 assert(consdata != NULL);
5881
5882 /* we already did full ranged row propagation */
5883 if( consdata->rangedrowpropagated == 2 )
5884 return SCIP_OKAY;
5885
5886 /* at least three variables are needed */
5887 if( consdata->nvars < 3 )
5888 return SCIP_OKAY;
5889
5890 /* do nothing on normal inequalities */
5891 if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
5892 return SCIP_OKAY;
5893
5894 /* get constraint handler data */
5895 conshdlr = SCIPconsGetHdlr(cons);
5896 assert(conshdlr != NULL);
5897 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5898 assert(conshdlrdata != NULL);
5899
5900 addartconss = conshdlrdata->rangedrowartcons && SCIPgetDepth(scip) < 1 && !SCIPinProbing(scip) && !SCIPinRepropagation(scip);
5901
5902 /* we may add artificial constraints */
5903 if( addartconss )
5904 consdata->rangedrowpropagated = 2;
5905 /* we are not allowed to add artificial constraints during propagation; if nothing changed on this constraint since
5906 * the last rangedrowpropagation, we can stop; otherwise, we mark this constraint to be rangedrowpropagated without
5907 * artificial constraints
5908 */
5909 else
5910 {
5911 if( consdata->rangedrowpropagated > 0 )
5912 return SCIP_OKAY;
5913
5914 consdata->rangedrowpropagated = 1;
5915 }
5916 fixedact = 0;
5917 nfixedconsvars = 0;
5918 /* calculate fixed activity and number of fixed variables */
5919 for( v = consdata->nvars - 1; v >= 0; --v )
5920 {
5921 /* all zero coefficients should be eliminated */
5922 assert(!SCIPisZero(scip, consdata->vals[v]));
5923
5924 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5925 {
5926 fixedact += SCIPvarGetLbLocal(consdata->vars[v]) * consdata->vals[v];
5928 }
5929 }
5930
5931 /* do not work with huge fixed activities */
5933 return SCIP_OKAY;
5934
5935 /* compute lhs and rhs for unfixed variables only and get number of unfixed variables */
5937 lhs = consdata->lhs - fixedact;
5938 rhs = consdata->rhs - fixedact;
5939 nunfixedvars = consdata->nvars - nfixedconsvars;
5940
5941 /* allocate temporary memory for variables and coefficients which may lead to infeasibility */
5944
5946 ncontvars = 0;
5947 gcdisone = TRUE;
5948 possiblegcd = TRUE;
5949
5950 /* we now partition all unfixed variables in two groups:
5951 *
5952 * the first one contains all integral variable with integral
5953 * coefficient so that all variables in this group will have a gcd greater than 1, this group will be implicitly
5954 * given
5955 *
5956 * the second group will contain all left unfixed variables and will be saved as infcheckvars with corresponding
5957 * coefficients as infcheckvals, the order of these variables should be the same as in the consdata object
5958 */
5959
5960 /* find first integral variables with integral coefficient greater than 1, thereby collecting all other unfixed
5961 * variables
5962 */
5963 ninfcheckvars = 0;
5964 v = -1;
5965 pos = -1;
5966 do
5967 {
5968 ++v;
5969
5970 /* partition the variables, do not change the order of collection, because it might be used later on */
5971 while( v < consdata->nvars && (SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
5972 !SCIPisIntegral(scip, consdata->vals[v]) || SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0)) )
5973 {
5974 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5975 {
5976 if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
5977 {
5978 ++ncontvars;
5979 }
5980 else if( SCIPvarIsBinary(consdata->vars[v]) )
5981 {
5982 SCIP_Real absval;
5983
5984 absval = REALABS(consdata->vals[v]);
5985
5986 if( absminbincoef > absval )
5988 }
5989
5990 gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5992 infcheckvars[ninfcheckvars] = consdata->vars[v];
5993 infcheckvals[ninfcheckvars] = consdata->vals[v];
5994 ++ninfcheckvars;
5995
5996 if( pos == -1 )
5997 pos = v;
5998 }
5999 ++v;
6000 }
6001 }
6002 while( v < consdata->nvars && SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) );
6003
6004 /* if the first group of variables is empty, we stop */
6005 /* @todo try to propagate/split up a constraint of the form:
6006 * x_1 + ... + x_m + a_1*y_1 + ... + a_n*y_n = k + c,
6007 * 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]
6008 */
6009 if( v == consdata->nvars )
6010 goto TERMINATE;
6011
6012 /* we need at least two non-continuous variables */
6013 if( ncontvars + 2 > nunfixedvars )
6014 goto TERMINATE;
6015
6016 assert(!SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])));
6017 assert(SCIPisIntegral(scip, consdata->vals[v]) && SCIPvarGetType(consdata->vars[v]) != SCIP_VARTYPE_CONTINUOUS && REALABS(consdata->vals[v]) > 1.5);
6018
6019 feastol = SCIPfeastol(scip);
6020
6021 gcd = (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol);
6022 assert(gcd >= 2);
6023
6024 /* go on to partition the variables, do not change the order of collection, because it might be used later on;
6025 * calculate gcd over the first part of variables */
6026 for( ; v < consdata->nvars; ++v )
6027 {
6028 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6029 continue;
6030
6031 if( SCIPvarIsBinary(consdata->vars[v]) )
6032 {
6033 SCIP_Real absval;
6034
6035 absval = REALABS(consdata->vals[v]);
6036
6037 if( absminbincoef > absval )
6039 }
6040
6041 if( !SCIPisIntegral(scip, consdata->vals[v]) || SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
6042 SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0) )
6043 {
6044 if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
6045 ++ncontvars;
6046
6047 gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
6049 infcheckvars[ninfcheckvars] = consdata->vars[v];
6050 infcheckvals[ninfcheckvars] = consdata->vals[v];
6051
6052 ++ninfcheckvars;
6053
6054 if( pos == -1 )
6055 pos = v;
6056 }
6057 else
6058 {
6059 assert(REALABS(consdata->vals[v]) > 1.5);
6060
6061 gcdtmp = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol));
6062 assert(gcdtmp >= 1);
6063
6064 if( gcdtmp == 1 )
6065 {
6066 infcheckvars[ninfcheckvars] = consdata->vars[v];
6067 infcheckvals[ninfcheckvars] = consdata->vals[v];
6068
6069 ++ninfcheckvars;
6070
6071 if( pos == -1 )
6072 pos = v;
6073 }
6074 else
6075 gcd = gcdtmp;
6076 }
6077 }
6078 assert(gcd >= 2);
6079
6080 /* it should not happen that all variables are of integral type and have a gcd >= 2, this should be done by
6081 * normalizeCons() */
6082 if( ninfcheckvars == 0 )
6083 goto TERMINATE;
6084
6085 assert(pos >= 0);
6086
6089 maxactinfvars = 0.0;
6090 minactinfvars = 0.0;
6091
6092 /* calculate activities over all infcheckvars */
6093 for( v = ninfcheckvars - 1; v >= 0; --v )
6094 {
6097
6098 if( SCIPisInfinity(scip, -lb) )
6099 {
6100 if( infcheckvals[v] < 0.0 )
6102 else
6104 }
6105 else
6106 {
6107 if( infcheckvals[v] < 0.0 )
6108 maxactinfvars += infcheckvals[v] * lb;
6109 else
6110 minactinfvars += infcheckvals[v] * lb;
6111 }
6112
6113 if( SCIPisInfinity(scip, ub) )
6114 {
6115 if( infcheckvals[v] > 0.0 )
6117 else
6119 }
6120 else
6121 {
6122 if( infcheckvals[v] > 0.0 )
6123 maxactinfvars += infcheckvals[v] * ub;
6124 else
6125 minactinfvars += infcheckvals[v] * ub;
6126 }
6127
6128 /* better abort on to big values */
6133
6135 goto TERMINATE;
6136 }
6138
6139 SCIPdebugMsg(scip, "minactinfvarsinvalid = %u, minactinfvars = %g, maxactinfvarsinvalid = %u, maxactinfvars = %g, gcd = %lld, ninfcheckvars = %d, ncontvars = %d\n",
6141
6142 /* @todo maybe we took the wrong variables as infcheckvars we could try to exchange integer variables */
6143 /* @todo if minactinfvarsinvalid or maxactinfvarsinvalid are true, try to exchange both partitions to maybe get valid
6144 * activities */
6145 /* @todo calculate minactivity and maxactivity for all non-intcheckvars, and use this for better bounding,
6146 * !!!note!!!
6147 * that therefore the conflict variables in addConflictFixedVars() need to be extended by all variables which
6148 * are not at their global bound
6149 */
6150
6151 /* check if between left hand side and right hand side exist a feasible point, if not the constraint leads to
6152 * infeasibility */
6153 if( !SCIPisIntegral(scip, (lhs - maxactinfvars) / gcd) &&
6154 SCIPisGT(scip, SCIPceil(scip, (lhs - maxactinfvars) / gcd) * gcd, rhs - minactinfvars) )
6155 {
6156 SCIPdebugMsg(scip, "no feasible value exist, constraint <%s> lead to infeasibility", SCIPconsGetName(cons));
6158
6159 /* start conflict analysis */
6160 /* @todo improve conflict analysis by adding relaxed bounds */
6162
6163 *cutoff = TRUE;
6164 }
6165 else if( ncontvars == 0 )
6166 {
6167 SCIP_Longint gcdinfvars = -1;
6168
6169 /* check for gcd over all infcheckvars */
6170 if( possiblegcd )
6171 {
6172 v = ninfcheckvars - 1;
6173 gcdinfvars = (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol);
6174 assert(gcdinfvars >= 2);
6175
6176 for( ; v >= 0 && gcdinfvars >= 2; --v )
6177 {
6178 gcdinfvars = SCIPcalcGreComDiv(gcdinfvars, (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol));
6179 }
6180 }
6181 else if( gcdisone )
6182 gcdinfvars = 1;
6183
6184 SCIPdebugMsg(scip, "gcdinfvars =%lld, possiblegcd = %u\n", gcdinfvars, possiblegcd);
6185
6186 /* compute solutions for this ranged row, if all variables are of integral type with integral coefficients */
6187 if( gcdinfvars >= 1 )
6188 {
6189 SCIP_Real value;
6190 SCIP_Real value2;
6191 SCIP_Real minvalue = SCIP_INVALID;
6192 SCIP_Real maxvalue = SCIP_INVALID;
6193 int nsols = 0;
6194
6196
6197 /* check how many possible solutions exist */
6198 while( SCIPisLE(scip, value, maxactinfvars) )
6199 {
6200 value2 = value + gcd * (SCIPceil(scip, (lhs - value) / gcd));
6201
6202 /* value2 might violate lhs due to numerics, in this case take the next divisible number */
6203 if( !SCIPisGE(scip, value2, lhs) )
6204 {
6205 value2 += gcd;
6206 }
6207
6208 if( SCIPisLE(scip, value2, rhs) )
6209 {
6210 ++nsols;
6211
6212 /* early termination if we found more than two solutions */
6213 if( nsols == 3 )
6214 break;
6215
6216 if( minvalue == SCIP_INVALID ) /*lint !e777*/
6217 minvalue = value;
6218
6219 maxvalue = value;
6220 }
6221 value += gcdinfvars;
6222 }
6223 assert(nsols < 2 || minvalue <= maxvalue);
6224
6225 /* determine last possible solution for better bounding */
6226 if( nsols == 3 )
6227 {
6228#ifndef NDEBUG
6229 SCIP_Real secondsolval = maxvalue;
6230#endif
6232
6233 /* check how many possible solutions exist */
6234 while( SCIPisGE(scip, value, minactinfvars) )
6235 {
6236 value2 = value + gcd * (SCIPfloor(scip, (rhs - value) / gcd));
6237
6238 /* value2 might violate rhs due to numerics, in this case take the next divisible number */
6239 if( !SCIPisLE(scip, value2, rhs) )
6240 {
6241 value2 -= gcd;
6242 }
6243
6244 if( SCIPisGE(scip, value2, lhs) )
6245 {
6246 maxvalue = value;
6247 assert(maxvalue > minvalue);
6248 break;
6249 }
6250 value -= gcdinfvars;
6251 }
6252 assert(maxvalue > secondsolval);
6253 }
6254
6255 SCIPdebugMsg(scip, "here nsols %s %d, minsolvalue = %g, maxsolvalue = %g, ninfcheckvars = %d, nunfixedvars = %d\n",
6256 nsols > 2 ? ">=" : "=", nsols, minvalue, maxvalue, ninfcheckvars, nunfixedvars);
6257
6258 /* no possible solution found */
6259 if( nsols == 0 )
6260 {
6261 SCIPdebugMsg(scip, "gcdinfvars = %lld, gcd = %lld, correctedlhs = %g, correctedrhs = %g\n",
6262 gcdinfvars, gcd, lhs, rhs);
6263 SCIPdebugMsg(scip, "no solution found; constraint <%s> lead to infeasibility\n", SCIPconsGetName(cons));
6265
6266 /* start conflict analysis */
6267 /* @todo improve conflict analysis by adding relaxed bounds */
6269
6270 *cutoff = TRUE;
6271 }
6272 /* if only one solution exist we can extract a new constraint or fix variables */
6273 else if( nsols == 1 )
6274 {
6275 assert(minvalue == maxvalue); /*lint !e777*/
6276
6277 /* we can fix the only variable in our second set of variables */
6278 if( ninfcheckvars == 1 )
6279 {
6280 SCIP_Bool fixed;
6281
6283
6284 SCIPdebugMsg(scip, "fixing single variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6287
6288 /* fix variable to only possible value */
6291
6292 if( *cutoff )
6293 {
6294 /* start conflict analysis */
6295 /* @todo improve conflict analysis by adding relaxed bounds */
6297 }
6298
6299 if( fixed )
6300 ++(*nfixedvars);
6301 }
6302 else
6303 {
6304 /* check for exactly one unfixed variable which is not part of the infcheckvars */
6305 if( ninfcheckvars == nunfixedvars - 1 )
6306 {
6307 SCIP_Real bound;
6308 SCIP_Bool foundvar = FALSE;
6309 SCIP_Bool fixed;
6310 int w = 0;
6311
6312 assert(ninfcheckvars > 0);
6313
6314 /* find variable which is not an infcheckvar and fix it */
6315 for( v = 0; v < consdata->nvars - 1; ++v )
6316 {
6317 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6318 {
6319 if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6320 {
6321#ifndef NDEBUG
6322 int v2 = v + 1;
6323 int w2 = w;
6324
6325 assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6326
6327 for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6328 {
6329 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6330 continue;
6331
6332 assert(consdata->vars[v2] == infcheckvars[w2]);
6333 ++w2;
6334 }
6336#endif
6337 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6338
6339 foundvar = TRUE;
6340
6341 if( consdata->vals[v] < 0 )
6342 {
6343 bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6344 }
6345 else
6346 {
6347 bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6348 }
6349
6350 SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6351 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6352 SCIPvarGetUbLocal(consdata->vars[v]), bound);
6353
6354 /* fix variable to only possible value */
6355 SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6357
6358 if( *cutoff )
6359 {
6360 /* start conflict analysis */
6361 /* @todo improve conflict analysis by adding relaxed bounds */
6363 consdata->vars[v], bound) );
6364 }
6365
6366 if( fixed )
6367 ++(*nfixedvars);
6368
6369 break;
6370 }
6371
6372 ++w;
6373 }
6374 }
6375
6376 /* maybe last variable was the not infcheckvar */
6377 if( !foundvar )
6378 {
6379 assert(v == consdata->nvars - 1);
6380 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6381
6382 if( consdata->vals[v] < 0 )
6383 {
6384 bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6385 }
6386 else
6387 {
6388 bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6389 }
6390
6391 SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6392 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6393 SCIPvarGetUbLocal(consdata->vars[v]), bound);
6394
6395 /* fix variable to only possible value */
6396 SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6398
6399 if( *cutoff )
6400 {
6401 /* start conflict analysis */
6402 /* @todo improve conflict analysis by adding relaxed bounds */
6404 consdata->vars[v], bound) );
6405 }
6406
6407 if( fixed )
6408 ++(*nfixedvars);
6409 }
6410 }
6411 else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6412 {
6413 /* aggregation possible if we have two variables, but this will be done later on */
6415 char name[SCIP_MAXSTRLEN];
6416
6417 /* create, add, and release new artificial constraint */
6418 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6419 ++conshdlrdata->naddconss;
6420
6421 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6422
6424 maxvalue, maxvalue, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6426
6428
6430
6431 ++(*naddconss);
6432 }
6433 }
6434 }
6435 /* at least two solutions */
6436 else
6437 {
6438 /* @todo if we found more then one solution, we may reduced domains due to dualpresolving? */
6439
6440 /* only one variable in the second set, so we can bound this variables */
6441 if( ninfcheckvars == 1 )
6442 {
6443 SCIP_Bool tightened;
6444 SCIP_Real newlb;
6445 SCIP_Real newub;
6446
6448
6449 if( infcheckvals[0] < 0 )
6450 {
6451 newlb = maxvalue/infcheckvals[0];
6452 newub = minvalue/infcheckvals[0];
6453 }
6454 else
6455 {
6456 newlb = minvalue/infcheckvals[0];
6457 newub = maxvalue/infcheckvals[0];
6458 }
6459 assert(newlb < newub);
6460
6462 {
6463 /* update lower bound of variable */
6464 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6466
6467 /* tighten variable lower bound to minimal possible value */
6469 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6470
6471 if( *cutoff )
6472 {
6473 /* start conflict analysis */
6474 /* @todo improve conflict analysis by adding relaxed bounds */
6476 }
6477
6478 if( tightened )
6479 ++(*nchgbds);
6480 }
6481
6483 {
6484 /* update upper bound of variable */
6485 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6487
6488 /* tighten variable upper bound to maximal possible value */
6490 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6491
6492 if( *cutoff )
6493 {
6494 /* start conflict analysis */
6495 /* @todo improve conflict analysis by adding relaxed bounds */
6497 }
6498
6499 if( tightened )
6500 ++(*nchgbds);
6501 }
6502 }
6503 /* check if we have only one not infcheckvars, if so we can tighten this variable */
6504 else if( ninfcheckvars == nunfixedvars - 1 )
6505 {
6506 SCIP_Bool foundvar = FALSE;
6507 SCIP_Bool tightened;
6508 SCIP_Real newlb;
6509 SCIP_Real newub;
6510 int w = 0;
6511
6512 assert(ninfcheckvars > 0);
6513 assert(minvalue < maxvalue);
6514
6515 /* find variable which is not an infcheckvar and fix it */
6516 for( v = 0; v < consdata->nvars - 1; ++v )
6517 {
6518 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6519 {
6520 if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6521 {
6522#ifndef NDEBUG
6523 int v2 = v + 1;
6524 int w2 = w;
6525
6526 assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6527
6528 for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6529 {
6530 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6531 continue;
6532
6533 assert(consdata->vars[v2] == infcheckvars[w2]);
6534 ++w2;
6535 }
6537#endif
6538
6539 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6540 foundvar = TRUE;
6541
6542 if( consdata->vals[v] < 0 )
6543 {
6544 newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6545 newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6546 }
6547 else
6548 {
6549 newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6550 newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6551 }
6553
6554 if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6555 {
6556 /* update lower bound of variable */
6557 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6558 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6559
6560 /* tighten variable lower bound to minimal possible value */
6561 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6562 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6563
6564 if( *cutoff )
6565 {
6566 /* start conflict analysis */
6567 /* @todo improve conflict analysis by adding relaxed bounds */
6569 consdata->vars[v], newlb) );
6570 }
6571
6572 if( tightened )
6573 ++(*nchgbds);
6574 }
6575
6576 if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6577 {
6578 /* update upper bound of variable */
6579 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6580 SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6581
6582 /* tighten variable upper bound to maximal possible value */
6583 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6584 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6585
6586 if( *cutoff )
6587 {
6588 /* start conflict analysis */
6589 /* @todo improve conflict analysis by adding relaxed bounds */
6591 consdata->vars[v], newub) );
6592 }
6593
6594 if( tightened )
6595 ++(*nchgbds);
6596 }
6597
6598 break;
6599 }
6600
6601 ++w;
6602 }
6603 }
6604
6605 /* maybe last variable was the not infcheckvar */
6606 if( !foundvar )
6607 {
6608 assert(v == consdata->nvars - 1);
6609 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6610
6611 if( consdata->vals[v] < 0 )
6612 {
6613 newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6614 newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6615 }
6616 else
6617 {
6618 newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6619 newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6620 }
6622
6623 if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6624 {
6625 /* update lower bound of variable */
6626 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6627 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6628
6629 /* tighten variable lower bound to minimal possible value */
6630 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6631 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6632
6633 if( *cutoff )
6634 {
6635 /* start conflict analysis */
6636 /* @todo improve conflict analysis by adding relaxed bounds */
6638 }
6639
6640 if( tightened )
6641 ++(*nchgbds);
6642 }
6643
6644 if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6645 {
6646 /* update upper bound of variable */
6647 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6648 SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6649
6650 /* tighten variable upper bound to maximal possible value */
6651 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6652 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6653
6654 if( *cutoff )
6655 {
6656 /* start conflict analysis */
6657 /* @todo improve conflict analysis by adding relaxed bounds */
6659 }
6660
6661 if( tightened )
6662 ++(*nchgbds);
6663 }
6664 }
6665 }
6666 /* at least two solutions and more than one variable, so we add a new constraint which bounds the feasible
6667 * region for our infcheckvars, if possible
6668 */
6669 else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6670 {
6672 char name[SCIP_MAXSTRLEN];
6673 SCIP_Real newlhs;
6674 SCIP_Real newrhs;
6675
6676 assert(maxvalue > minvalue);
6677
6678 if( SCIPisGT(scip, minvalue, minactinfvars) )
6679 newlhs = minvalue;
6680 else
6682
6683 if( SCIPisLT(scip, maxvalue, maxactinfvars) )
6684 newrhs = maxvalue;
6685 else
6687
6689 {
6690 /* create, add, and release new artificial constraint */
6691 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons1_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6692 ++conshdlrdata->naddconss;
6693
6694 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6695
6699
6702
6703 ++(*naddconss);
6704 }
6705 /* @todo maybe add constraint for all variables which are not infcheckvars, lhs should be minvalue, rhs
6706 * should be maxvalue */
6707 }
6708 }
6709 }
6710 }
6711 else if( addartconss && ncontvars < ninfcheckvars )
6712 {
6713 SCIP_Real maxact = 0.0;
6714 SCIP_Real minact = 0.0;
6715 int w = 0;
6716
6717 /* compute activities of non-infcheckvars */
6718 for( v = 0; v < consdata->nvars; ++v )
6719 {
6721 {
6722 ++w;
6723 continue;
6724 }
6725
6726 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6727 {
6728 if( SCIPvarIsBinary(consdata->vars[v]) )
6729 {
6730 if( consdata->vals[v] > 0.0 )
6731 maxact += consdata->vals[v];
6732 else
6733 minact += consdata->vals[v];
6734 }
6735 else
6736 {
6737 SCIP_Real tmpval;
6738
6739 assert(SCIPvarIsIntegral(consdata->vars[v]));
6740
6741 if( consdata->vals[v] > 0.0 )
6742 {
6743 tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6744
6745 if( SCIPisHugeValue(scip, -tmpval) )
6746 break;
6747
6748 minact += tmpval;
6749
6750 tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6751
6753 break;
6754
6755 maxact += tmpval;
6756 }
6757 else
6758 {
6759 tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6760
6761 if( SCIPisHugeValue(scip, -tmpval) )
6762 break;
6763
6764 minact += tmpval;
6765
6766 tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6767
6769 break;
6770
6771 maxact += tmpval;
6772 }
6773 }
6774 }
6775 }
6776 if( v == consdata->nvars && !SCIPisHugeValue(scip, -minact) && !SCIPisHugeValue(scip, maxact) )
6777 {
6779 char name[SCIP_MAXSTRLEN];
6780 SCIP_Real newlhs;
6781 SCIP_Real newrhs;
6782
6783 assert(maxact > minact);
6785
6786 newlhs = lhs - maxact;
6787 newrhs = rhs - minact;
6788 assert(newlhs < newrhs);
6789
6790 /* create, add, and release new artificial constraint */
6791 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons2_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6792 ++conshdlrdata->naddconss;
6793
6794 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6795
6799
6802
6803 ++(*naddconss);
6804 }
6805 }
6806
6807 TERMINATE:
6810
6811 return SCIP_OKAY;
6812}
6813
6814/** tightens bounds of a single variable due to activity bounds */
6815static
6817 SCIP* scip, /**< SCIP data structure */
6818 SCIP_CONS* cons, /**< linear constraint */
6819 int pos, /**< position of the variable in the vars array */
6820 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6821 int* nchgbds, /**< pointer to count the total number of tightened bounds */
6822 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
6823 )
6824{
6825 SCIP_CONSDATA* consdata;
6826 SCIP_VAR* var;
6827 SCIP_Real val;
6828 SCIP_Real lb;
6829 SCIP_Real ub;
6830 SCIP_Real minresactivity;
6831 SCIP_Real maxresactivity;
6832 SCIP_Real lhs;
6833 SCIP_Real rhs;
6834 SCIP_Bool infeasible;
6835 SCIP_Bool tightened;
6836 SCIP_Bool minisrelax;
6837 SCIP_Bool maxisrelax;
6838 SCIP_Bool isminsettoinfinity;
6839 SCIP_Bool ismaxsettoinfinity;
6840
6841 assert(scip != NULL);
6842 assert(cons != NULL);
6843 assert(cutoff != NULL);
6844 assert(nchgbds != NULL);
6845
6846 /* we cannot tighten variables' bounds, if the constraint may be not complete */
6847 if( SCIPconsIsModifiable(cons) )
6848 return SCIP_OKAY;
6849
6850 consdata = SCIPconsGetData(cons);
6851 assert(consdata != NULL);
6852 assert(0 <= pos && pos < consdata->nvars);
6853
6854 *cutoff = FALSE;
6855
6856 var = consdata->vars[pos];
6857
6858 /* we cannot tighten bounds of multi-aggregated variables */
6860 return SCIP_OKAY;
6861
6862 val = consdata->vals[pos];
6863 lhs = consdata->lhs;
6864 rhs = consdata->rhs;
6867 assert(var != NULL);
6868 assert(!SCIPisZero(scip, val));
6869 assert(!SCIPisInfinity(scip, lhs));
6870 assert(!SCIPisInfinity(scip, -rhs));
6871
6872 lb = SCIPvarGetLbLocal(var);
6873 ub = SCIPvarGetUbLocal(var);
6874 assert(SCIPisLE(scip, lb, ub));
6875
6876 if( val > 0.0 )
6877 {
6878 /* check, if we can tighten the variable's bounds */
6880 {
6881 SCIP_Real newub;
6882
6883 newub = (rhs - minresactivity)/val;
6884
6885 if( !SCIPisInfinity(scip, newub) &&
6886 ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6887 {
6888 SCIP_Bool activityunreliable;
6889 activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6890
6891 /* check minresactivities for reliability */
6892 if( activityunreliable )
6893 {
6895 newub = (rhs - minresactivity)/val;
6898 && (!force || !SCIPisLT(scip, newub, ub)));
6899 }
6900
6901 if( !activityunreliable )
6902 {
6903 /* tighten upper bound */
6904 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
6905 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6907 &infeasible, &tightened) );
6908 if( infeasible )
6909 {
6910 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6912
6913 /* analyze conflict */
6915
6916 *cutoff = TRUE;
6917 return SCIP_OKAY;
6918 }
6919 if( tightened )
6920 {
6921 ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6923 (*nchgbds)++;
6924
6925 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6926 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6927 }
6928 }
6929 }
6930 }
6931
6932 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
6933 {
6934 SCIP_Real newlb;
6935
6936 newlb = (lhs - maxresactivity)/val;
6937 if( !SCIPisInfinity(scip, -newlb) &&
6938 ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6939 {
6940 /* check maxresactivities for reliability */
6941 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6942 {
6944 newlb = (lhs - maxresactivity)/val;
6945
6948 && (!force || !SCIPisGT(scip, newlb, lb))) )
6949 return SCIP_OKAY;
6950 }
6951
6952 /* tighten lower bound */
6953 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6954 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6956 &infeasible, &tightened) );
6957 if( infeasible )
6958 {
6959 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6961
6962 /* analyze conflict */
6964
6965 *cutoff = TRUE;
6966 return SCIP_OKAY;
6967 }
6968 if( tightened )
6969 {
6970 lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6972 (*nchgbds)++;
6973 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6974 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6975 }
6976 }
6977 }
6978 }
6979 else
6980 {
6981 /* check, if we can tighten the variable's bounds */
6983 {
6984 SCIP_Real newlb;
6985
6986 newlb = (rhs - minresactivity)/val;
6987 if( !SCIPisInfinity(scip, -newlb) &&
6988 ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6989 {
6990 SCIP_Bool activityunreliable;
6991 activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6992 /* check minresactivities for reliability */
6993 if( activityunreliable )
6994 {
6996 newlb = (rhs - minresactivity)/val;
6997
6999 || (!SCIPisLbBetter(scip, newlb, lb, ub) && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
7000 && (!force || !SCIPisGT(scip, newlb, lb)));
7001 }
7002
7003 if( !activityunreliable )
7004 {
7005 /* tighten lower bound */
7006 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
7007 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
7009 &infeasible, &tightened) );
7010 if( infeasible )
7011 {
7012 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
7014
7015 /* analyze conflict */
7017
7018 *cutoff = TRUE;
7019 return SCIP_OKAY;
7020 }
7021 if( tightened )
7022 {
7023 lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
7025 (*nchgbds)++;
7026 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
7027 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
7028 }
7029 }
7030 }
7031 }
7032
7033 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
7034 {
7035 SCIP_Real newub;
7036
7037 newub = (lhs - maxresactivity)/val;
7038 if( !SCIPisInfinity(scip, newub) &&
7039 ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
7040 {
7041 /* check maxresactivities for reliability */
7042 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
7043 {
7045 newub = (lhs - maxresactivity)/val;
7046
7049 && (!force || !SCIPisLT(scip, newub, ub))) )
7050 return SCIP_OKAY;
7051 }
7052
7053 /* tighten upper bound */
7054 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g], newub=%.15g\n",
7055 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
7057 &infeasible, &tightened) );
7058 if( infeasible )
7059 {
7060 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
7062
7063 /* analyze conflict */
7065
7066 *cutoff = TRUE;
7067 return SCIP_OKAY;
7068 }
7069 if( tightened )
7070 {
7071 ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
7073 (*nchgbds)++;
7074 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
7075 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
7076 }
7077 }
7078 }
7079 }
7080
7081 return SCIP_OKAY;
7082}
7083
7084#define MAXTIGHTENROUNDS 10
7085
7086/** tightens bounds of variables in constraint due to activity bounds */
7087static
7089 SCIP* scip, /**< SCIP data structure */
7090 SCIP_CONS* cons, /**< linear constraint */
7091 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7092 SCIP_Bool sortvars, /**< should variables be used in sorted order? */
7093 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7094 int* nchgbds /**< pointer to count the total number of tightened bounds */
7095 )
7096{
7097 SCIP_CONSDATA* consdata;
7098 unsigned int tightenmode;
7099 int nvars;
7100 int nrounds;
7101 int lastchange;
7102 int oldnchgbds;
7103#ifndef SCIP_DEBUG
7104 int oldnchgbdstotal;
7105#endif
7106 int v;
7107 SCIP_Bool force;
7108 SCIP_Bool easycase;
7109
7110 assert(scip != NULL);
7111 assert(cons != NULL);
7112 assert(nchgbds != NULL);
7113 assert(cutoff != NULL);
7114
7115 *cutoff = FALSE;
7116
7117 /* we cannot tighten variables' bounds, if the constraint may be not complete */
7118 if( SCIPconsIsModifiable(cons) )
7119 return SCIP_OKAY;
7120
7121 /* if a constraint was created after presolve, then it may hold fixed variables
7122 * if there are even multi-aggregated variables, then we cannot do bound tightening on these
7123 * thus, ensure here again that variable fixings have been applied
7124 */
7125 SCIP_CALL( applyFixings(scip, cons, cutoff) );
7126 if( *cutoff )
7127 return SCIP_OKAY;
7128
7129 /* check if constraint has any chances of tightening bounds */
7130 if( !canTightenBounds(cons) )
7131 return SCIP_OKAY;
7132
7133 consdata = SCIPconsGetData(cons);
7134 assert(consdata != NULL);
7135
7136 nvars = consdata->nvars;
7137 force = (nvars == 1) && !SCIPconsIsModifiable(cons);
7138
7139 /* we are at the root node or during presolving */
7140 if( SCIPgetDepth(scip) < 1 )
7141 tightenmode = 2;
7142 else
7143 tightenmode = 1;
7144
7145 /* stop if we already tightened the constraint and the tightening is not forced */
7146 if( !force && (consdata->boundstightened >= tightenmode) ) /*lint !e574*/
7147 return SCIP_OKAY;
7148
7149 /* ensure that the variables are properly sorted */
7150 if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7151 {
7152 SCIP_CALL( consdataSort(scip, consdata) );
7153 assert(consdata->coefsorted);
7154 }
7155
7156 /* update maximal activity delta if necessary */
7157 if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
7159
7160 assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
7161 assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
7162 checkMaxActivityDelta(scip, consdata);
7163
7164 /* this may happen if all variables are fixed */
7165 if( SCIPisFeasZero(scip, consdata->maxactdelta) )
7166 return SCIP_OKAY;
7167
7168 if( !SCIPisInfinity(scip, consdata->maxactdelta) )
7169 {
7170 SCIP_Real slack;
7171 SCIP_Real surplus;
7172 SCIP_Real minactivity;
7173 SCIP_Real maxactivity;
7174 SCIP_Bool minisrelax;
7175 SCIP_Bool maxisrelax;
7176 SCIP_Bool isminsettoinfinity;
7177 SCIP_Bool ismaxsettoinfinity;
7178
7179 /* use maximal activity delta to skip propagation (cannot deduce anything) */
7180 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minisrelax, &maxisrelax,
7182 assert(!SCIPisInfinity(scip, minactivity));
7183 assert(!SCIPisInfinity(scip, -maxactivity));
7184
7185 slack = (SCIPisInfinity(scip, consdata->rhs) || isminsettoinfinity) ? SCIPinfinity(scip) : (consdata->rhs - minactivity);
7186 surplus = (SCIPisInfinity(scip, -consdata->lhs) || ismaxsettoinfinity) ? SCIPinfinity(scip) : (maxactivity - consdata->lhs);
7187
7188 /* check if the constraint will propagate */
7189 if( SCIPisLE(scip, consdata->maxactdelta, MIN(slack, surplus)) )
7190 return SCIP_OKAY;
7191 }
7192
7193 /* check if we can use fast implementation for easy and numerically well behaved cases */
7194 easycase = SCIPisLT(scip, consdata->maxactdelta, maxeasyactivitydelta);
7195
7196 /* as long as the bounds might be tightened again, try to tighten them; abort after a maximal number of rounds */
7197 lastchange = -1;
7198 oldnchgbds = 0;
7199
7200#ifndef SCIP_DEBUG
7201 oldnchgbdstotal = *nchgbds;
7202#endif
7203
7204 for( nrounds = 0; (force || consdata->boundstightened < tightenmode) && nrounds < MAXTIGHTENROUNDS; ++nrounds ) /*lint !e574*/
7205 {
7206 /* ensure that the variables are properly sorted
7207 *
7208 * note: it might happen that integer variables become binary during bound tightening at the root node
7209 */
7210 if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7211 {
7212 SCIP_CALL( consdataSort(scip, consdata) );
7213 assert(consdata->coefsorted);
7214 }
7215
7216 /* mark the constraint to have the variables' bounds tightened */
7217 consdata->boundstightened = (unsigned int)tightenmode;
7218
7219 /* try to tighten the bounds of each variable in the constraint. During solving process, the binary variable
7220 * sorting enables skipping variables
7221 */
7222 v = 0;
7223 while( v < nvars && v != lastchange && !(*cutoff) )
7224 {
7225 oldnchgbds = *nchgbds;
7226
7227 if( easycase )
7228 {
7229 SCIP_CALL( tightenVarBoundsEasy(scip, cons, v, cutoff, nchgbds, force) );
7230 }
7231 else
7232 {
7233 SCIP_CALL( tightenVarBounds(scip, cons, v, cutoff, nchgbds, force) );
7234 }
7235
7236 /* if there was no progress, skip the rest of the binary variables */
7237 if( *nchgbds > oldnchgbds )
7238 {
7239 lastchange = v;
7240 ++v;
7241 }
7242 else if( consdata->coefsorted && v < consdata->nbinvars - 1
7243 && !SCIPisFeasEQ(scip, SCIPvarGetUbLocal(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v])) )
7244 v = consdata->nbinvars;
7245 else
7246 ++v;
7247 }
7248
7249#ifndef SCIP_DEBUG
7250 SCIPdebugMessage("linear constraint <%s> found %d bound changes in round %d\n", SCIPconsGetName(cons),
7251 *nchgbds - oldnchgbdstotal, nrounds);
7253#endif
7254 }
7255
7256#ifndef NDEBUG
7257 if( force && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
7258 assert(*cutoff || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->vars[0]), SCIPvarGetUbLocal(consdata->vars[0])));
7259#endif
7260
7261 return SCIP_OKAY;
7262}
7263
7264/** checks linear constraint for feasibility of given solution or current solution */
7265static
7267 SCIP* scip, /**< SCIP data structure */
7268 SCIP_CONS* cons, /**< linear constraint */
7269 SCIP_SOL* sol, /**< solution to be checked, or NULL for current solution */
7270 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
7271 SCIP_Bool checkrelmaxabs, /**< Should the violation for a constraint with side 0.0 be checked relative
7272 * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
7273 SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
7274 )
7275{
7276 SCIP_CONSDATA* consdata;
7277 SCIP_Real activity;
7278 SCIP_Real absviol;
7279 SCIP_Real relviol;
7280 SCIP_Real lhsviol;
7281 SCIP_Real rhsviol;
7282
7283 assert(scip != NULL);
7284 assert(cons != NULL);
7285 assert(violated != NULL);
7286
7287 SCIPdebugMsg(scip, "checking linear constraint <%s>\n", SCIPconsGetName(cons));
7289
7290 consdata = SCIPconsGetData(cons);
7291 assert(consdata != NULL);
7292
7293 *violated = FALSE;
7294
7295 if( consdata->row != NULL )
7296 {
7297 if( !checklprows && SCIProwIsInLP(consdata->row) )
7298 return SCIP_OKAY;
7299 else if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
7300 activity = consdataComputePseudoActivity(scip, consdata);
7301 else
7302 activity = SCIPgetRowSolActivity(scip, consdata->row, sol);
7303 }
7304 else
7305 activity = consdataGetActivity(scip, consdata, sol);
7306
7307 SCIPdebugMsg(scip, " consdata activity=%.15g (lhs=%.15g, rhs=%.15g, row=%p, checklprows=%u, rowinlp=%u, sol=%p, hascurrentnodelp=%u)\n",
7308 activity, consdata->lhs, consdata->rhs, (void*)consdata->row, checklprows,
7309 consdata->row == NULL ? 0 : SCIProwIsInLP(consdata->row), (void*)sol,
7310 consdata->row == NULL ? FALSE : SCIPhasCurrentNodeLP(scip));
7311
7312 /* calculate absolute and relative bound violations */
7313 lhsviol = consdata->lhs - activity;
7314 rhsviol = activity - consdata->rhs;
7315
7316 absviol = 0.0;
7317 relviol = 0.0;
7318 if( (lhsviol > 0) && (lhsviol > rhsviol) )
7319 {
7320 absviol = lhsviol;
7321 relviol = SCIPrelDiff(consdata->lhs, activity);
7322 }
7323 else if( rhsviol > 0 )
7324 {
7325 absviol = rhsviol;
7326 relviol = SCIPrelDiff(activity, consdata->rhs);
7327 }
7328
7329 /* the activity of pseudo solutions may be invalid if it comprises positive and negative infinity contributions; we
7330 * return infeasible for safety
7331 */
7332 if( activity == SCIP_INVALID ) /*lint !e777*/
7333 {
7334 assert(sol == NULL);
7335 *violated = TRUE;
7336
7337 /* set violation of invalid pseudo solutions */
7340
7341 /* reset constraint age since we are in enforcement */
7343 }
7344 /* check with relative tolerances (the default) */
7345 else if( !consdata->checkabsolute && (SCIPisFeasLT(scip, activity, consdata->lhs) || SCIPisFeasGT(scip, activity, consdata->rhs)) )
7346 {
7347 /* the "normal" check: one of the two sides is violated */
7348 if( !checkrelmaxabs )
7349 {
7350 *violated = TRUE;
7351
7352 /* only reset constraint age if we are in enforcement */
7353 if( sol == NULL )
7354 {
7356 }
7357 }
7358 /* the (much) more complicated check: we try to disregard random noise and violations of a 0.0 side which are
7359 * small compared to the absolute values occurring in the activity
7360 */
7361 else
7362 {
7363 SCIP_Real maxabs;
7364 SCIP_Real coef;
7365 SCIP_Real absval;
7366 SCIP_Real solval;
7367 int v;
7368
7369 maxabs = 1.0;
7370
7371 /* compute maximum absolute value */
7372 for( v = 0; v < consdata->nvars; ++v )
7373 {
7374 if( consdata->vals != NULL )
7375 {
7376 coef = consdata->vals[v];
7377 }
7378 else
7379 coef = 1.0;
7380
7381 solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
7382 absval = REALABS( coef * solval );
7383 maxabs = MAX( maxabs, absval );
7384 }
7385
7386 /* regard left hand side, first */
7387 if( SCIPisFeasLT(scip, activity, consdata->lhs) )
7388 {
7389 /* check whether violation is random noise */
7390 if( (consdata->lhs - activity) <= (1e-15 * maxabs) )
7391 {
7392 SCIPdebugMsg(scip, " lhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7393 consdata->lhs - activity, maxabs);
7395
7396 /* only increase constraint age if we are in enforcement */
7397 if( sol == NULL )
7398 {
7399 SCIP_CALL( SCIPincConsAge(scip, cons) );
7400 }
7401 }
7402 /* lhs is violated and lhs is 0.0: use relative tolerance w.r.t. largest absolute value */
7403 else if( SCIPisZero(scip, consdata->lhs) )
7404 {
7405 if( (consdata->lhs - activity) <= (SCIPfeastol(scip) * maxabs) )
7406 {
7407 SCIPdebugMsg(scip, " lhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7408 consdata->lhs - activity, maxabs);
7410
7411 /* only increase constraint age if we are in enforcement */
7412 if( sol == NULL )
7413 {
7414 SCIP_CALL( SCIPincConsAge(scip, cons) );
7415 }
7416 }
7417 else
7418 {
7419 *violated = TRUE;
7420
7421 /* only reset constraint age if we are in enforcement */
7422 if( sol == NULL )
7423 {
7425 }
7426 }
7427 }
7428 else
7429 {
7430 *violated = TRUE;
7431
7432 /* only reset constraint age if we are in enforcement */
7433 if( sol == NULL )
7434 {
7436 }
7437 }
7438 }
7439
7440 /* now regard right hand side */
7441 if( SCIPisFeasGT(scip, activity, consdata->rhs) )
7442 {
7443 /* check whether violation is random noise */
7444 if( (activity - consdata->rhs) <= (1e-15 * maxabs) )
7445 {
7446 SCIPdebugMsg(scip, " rhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7447 activity - consdata->rhs, maxabs);
7449
7450 /* only increase constraint age if we are in enforcement */
7451 if( sol == NULL )
7452 {
7453 SCIP_CALL( SCIPincConsAge(scip, cons) );
7454 }
7455 }
7456 /* rhs is violated and rhs is 0.0, use relative tolerance w.r.t. largest absolute value */
7457 else if( SCIPisZero(scip, consdata->rhs) )
7458 {
7459 if( (activity - consdata->rhs) <= (SCIPfeastol(scip) * maxabs) )
7460 {
7461 SCIPdebugMsg(scip, " rhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7462 activity - consdata->rhs, maxabs);
7464
7465 /* only increase constraint age if we are in enforcement */
7466 if( sol == NULL )
7467 {
7468 SCIP_CALL( SCIPincConsAge(scip, cons) );
7469 }
7470 }
7471 else
7472 {
7473 *violated = TRUE;
7474
7475 /* only reset constraint age if we are in enforcement */
7476 if( sol == NULL )
7477 {
7479 }
7480 }
7481 }
7482 else
7483 {
7484 *violated = TRUE;
7485
7486 /* only reset constraint age if we are in enforcement */
7487 if( sol == NULL )
7488 {
7490 }
7491 }
7492 }
7493 }
7494 }
7495 /* check with absolute tolerances */
7496 else if( consdata->checkabsolute &&
7497 ((!SCIPisInfinity(scip, -consdata->lhs) && SCIPisGT(scip, consdata->lhs-activity, SCIPfeastol(scip))) ||
7498 (!SCIPisInfinity(scip, consdata->rhs) && SCIPisGT(scip, activity-consdata->rhs, SCIPfeastol(scip)))) )
7499 {
7500 *violated = TRUE;
7501
7502 /* only reset constraint age if we are in enforcement */
7503 if( sol == NULL )
7504 {
7506 }
7507 }
7508 else
7509 {
7510 /* only increase constraint age if we are in enforcement */
7511 if( sol == NULL )
7512 {
7513 SCIP_CALL( SCIPincConsAge(scip, cons) );
7514 }
7515 }
7516
7517 /* update absolute and relative violation of the solution */
7518 if( sol != NULL )
7520
7521 return SCIP_OKAY;
7522}
7523
7524/** creates an LP row in a linear constraint data */
7525static
7527 SCIP* scip, /**< SCIP data structure */
7528 SCIP_CONS* cons /**< linear constraint */
7529 )
7530{
7531 SCIP_CONSDATA* consdata;
7532
7533 assert(scip != NULL);
7534 assert(cons != NULL);
7535
7536 consdata = SCIPconsGetData(cons);
7537 assert(consdata != NULL);
7538 assert(consdata->row == NULL);
7539
7540 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
7542
7543 SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) );
7544
7545 return SCIP_OKAY;
7546}
7547
7548/** adds linear constraint as cut to the LP */
7549static
7551 SCIP* scip, /**< SCIP data structure */
7552 SCIP_CONS* cons, /**< linear constraint */
7553 SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7554 )
7555{
7556 SCIP_CONSDATA* consdata;
7557
7558 assert(scip != NULL);
7559 assert(cons != NULL);
7560
7561 consdata = SCIPconsGetData(cons);
7562 assert(consdata != NULL);
7563
7564 if( consdata->row == NULL )
7565 {
7566 if( !SCIPconsIsModifiable(cons) )
7567 {
7568 /* 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
7569 * removing this here will make test cons/linear/fixedvar.c fail (as of 2018-12-03)
7570 */
7571 SCIP_CALL( applyFixings(scip, cons, cutoff) );
7572 if( *cutoff )
7573 return SCIP_OKAY;
7574 }
7575
7576 /* convert consdata object into LP row */
7577 SCIP_CALL( createRow(scip, cons) );
7578 }
7579 assert(consdata->row != NULL);
7580
7581 if( consdata->nvars == 0 )
7582 {
7583 SCIPdebugMsg(scip, "Empty linear constraint enters LP: <%s>\n", SCIPconsGetName(cons));
7584 }
7585
7586 /* insert LP row as cut */
7587 if( !SCIProwIsInLP(consdata->row) )
7588 {
7589 SCIPdebugMsg(scip, "adding relaxation of linear constraint <%s>: ", SCIPconsGetName(cons));
7590 SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL)) );
7591 /* if presolving is turned off, the row might be trivial */
7592 if ( ! SCIPisInfinity(scip, -consdata->lhs) || ! SCIPisInfinity(scip, consdata->rhs) )
7593 {
7594 SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, cutoff) );
7595 }
7596#ifndef NDEBUG
7597 else
7598 {
7599 int pr;
7600 int cr;
7601 SCIP_CALL( SCIPgetIntParam(scip, "presolving/maxrounds", &pr) );
7602 SCIP_CALL( SCIPgetIntParam(scip, "constraints/linear/maxprerounds", &cr) );
7603 assert( pr == 0 || cr == 0 );
7604 }
7605#endif
7606 }
7607
7608 return SCIP_OKAY;
7609}
7610
7611/** adds linear constraint as row to the NLP, if not added yet */
7612static
7614 SCIP* scip, /**< SCIP data structure */
7615 SCIP_CONS* cons /**< linear constraint */
7616 )
7617{
7618 SCIP_CONSDATA* consdata;
7619
7621
7622 /* skip deactivated, redundant, or local linear constraints (the NLP does not allow for local rows at the moment) */
7623 if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsLocal(cons) )
7624 return SCIP_OKAY;
7625
7626 consdata = SCIPconsGetData(cons);
7627 assert(consdata != NULL);
7628
7629 if( consdata->nlrow == NULL )
7630 {
7631 assert(consdata->lhs <= consdata->rhs);
7632
7633 SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons),
7634 0.0, consdata->nvars, consdata->vars, consdata->vals, NULL, consdata->lhs, consdata->rhs, SCIP_EXPRCURV_LINEAR) );
7635
7636 assert(consdata->nlrow != NULL);
7637 }
7638
7639 if( !SCIPnlrowIsInNLP(consdata->nlrow) )
7640 {
7641 SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow) );
7642 }
7643
7644 return SCIP_OKAY;
7645}
7646
7647/** separates linear constraint: adds linear constraint as cut, if violated by given solution */
7648static
7650 SCIP* scip, /**< SCIP data structure */
7651 SCIP_CONS* cons, /**< linear constraint */
7652 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
7653 SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
7654 SCIP_Bool separatecards, /**< should knapsack cardinality cuts be generated? */
7655 SCIP_Bool separateall, /**< should all constraints be subject to cardinality cut generation instead of only
7656 * the ones with non-zero dual value? */
7657 int* ncuts, /**< pointer to add up the number of found cuts */
7658 SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7659 )
7660{
7661 SCIP_CONSDATA* consdata;
7662 SCIP_Bool violated;
7663 int oldncuts;
7664
7665 assert(scip != NULL);
7666 assert(conshdlrdata != NULL);
7667 assert(cons != NULL);
7668 assert(cutoff != NULL);
7669
7670 consdata = SCIPconsGetData(cons);
7671 assert(ncuts != NULL);
7672 assert(consdata != NULL);
7673
7674 oldncuts = *ncuts;
7675 *cutoff = FALSE;
7676
7677 SCIP_CALL( checkCons(scip, cons, sol, (sol != NULL), conshdlrdata->checkrelmaxabs, &violated) );
7678
7679 if( violated )
7680 {
7681 /* insert LP row as cut */
7683 (*ncuts)++;
7684 }
7685 else if( !SCIPconsIsModifiable(cons) && separatecards )
7686 {
7687 /* relax linear constraint into knapsack constraint and separate lifted cardinality cuts */
7688 if( !separateall && sol == NULL )
7689 {
7690 /* we only want to call the knapsack cardinality cut separator for rows that have a non-zero dual solution */
7691 if( consdata->row != NULL && SCIProwIsInLP(consdata->row) )
7692 {
7693 SCIP_Real dualsol;
7694
7695 dualsol = SCIProwGetDualsol(consdata->row);
7696 if( SCIPisFeasNegative(scip, dualsol) )
7697 {
7698 if( !SCIPisInfinity(scip, consdata->rhs) )
7699 {
7700 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7701 consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7702 }
7703 }
7704 else if( SCIPisFeasPositive(scip, dualsol) )
7705 {
7706 if( !SCIPisInfinity(scip, -consdata->lhs) )
7707 {
7708 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7709 consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7710 }
7711 }
7712 }
7713 }
7714 else
7715 {
7716 if( !SCIPisInfinity(scip, consdata->rhs) )
7717 {
7718 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7719 consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7720 }
7721 if( !SCIPisInfinity(scip, -consdata->lhs) )
7722 {
7723 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7724 consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7725 }
7726 }
7727 }
7728
7729 if( *ncuts > oldncuts )
7730 {
7732 }
7733
7734 return SCIP_OKAY;
7735}
7736
7737/** propagation method for linear constraints */
7738static
7740 SCIP* scip, /**< SCIP data structure */
7741 SCIP_CONS* cons, /**< linear constraint */
7742 SCIP_Bool tightenbounds, /**< should the variable's bounds be tightened? */
7743 SCIP_Bool rangedrowpropagation,/**< should ranged row propagation be performed? */
7744 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7745 SCIP_Bool sortvars, /**< should variable sorting for faster propagation be used? */
7746 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7747 int* nchgbds /**< pointer to count the total number of tightened bounds */
7748 )
7749{
7750 SCIP_CONSDATA* consdata;
7751 SCIP_Real minactivity;
7752 SCIP_Real maxactivity;
7753 SCIP_Bool minactisrelax;
7754 SCIP_Bool maxactisrelax;
7755 SCIP_Bool isminsettoinfinity;
7756 SCIP_Bool ismaxsettoinfinity;
7757
7758 assert(scip != NULL);
7759 assert(cons != NULL);
7760 assert(cutoff != NULL);
7761 assert(nchgbds != NULL);
7762
7763 /*SCIPdebugMsg(scip, "propagating linear constraint <%s>\n", SCIPconsGetName(cons));*/
7764
7765 consdata = SCIPconsGetData(cons);
7766 assert(consdata != NULL);
7767
7768 if( consdata->eventdata == NULL )
7769 {
7770 SCIP_CONSHDLR* conshdlr;
7771 SCIP_CONSHDLRDATA* conshdlrdata;
7772
7773 conshdlr = SCIPconsGetHdlr(cons);
7774 assert(conshdlr != NULL);
7775
7776 conshdlrdata = SCIPconshdlrGetData(conshdlr);
7777 assert(conshdlrdata != NULL);
7778
7779 /* catch bound change events of variables */
7780 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
7781 assert(consdata->eventdata != NULL);
7782 }
7783
7784 *cutoff = FALSE;
7785
7786 /* we can only infer activity bounds of the linear constraint, if it is not modifiable */
7787 if( !SCIPconsIsModifiable(cons) )
7788 {
7789 /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
7791 {
7792 SCIP_CALL( SCIPincConsAge(scip, cons) );
7793 }
7794
7795 /* tighten the variable's bounds */
7796 if( tightenbounds )
7797 {
7798 int oldnchgbds;
7799
7800 oldnchgbds = *nchgbds;
7801
7802 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
7803
7804 if( *nchgbds > oldnchgbds )
7805 {
7807 }
7808 }
7809
7810 /* propagate ranged rows */
7811 if( rangedrowpropagation && tightenbounds && !(*cutoff) )
7812 {
7813 int nfixedvars;
7814 int naddconss;
7815 SCIPdebug( int oldnchgbds = *nchgbds; )
7816
7817 nfixedvars = 0;
7818 naddconss = 0;
7819
7820 SCIP_CALL( rangedRowPropagation(scip, cons, cutoff, &nfixedvars, nchgbds, &naddconss) );
7821
7822 if( *cutoff )
7823 {
7824 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible\n", SCIPconsGetName(cons));
7825 }
7826 else
7827 {
7828 SCIPdebug( SCIPdebugMsg(scip, "linear constraint <%s> found %d bound changes and %d fixings\n", SCIPconsGetName(cons), *nchgbds - oldnchgbds, nfixedvars); )
7829 }
7830
7831 if( nfixedvars > 0 )
7832 *nchgbds += 2*nfixedvars;
7833 } /*lint !e438*/
7834
7835 /* check constraint for infeasibility and redundancy */
7836 if( !(*cutoff) )
7837 {
7838 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
7840
7841 if( SCIPisFeasGT(scip, minactivity, consdata->rhs) )
7842 {
7843 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (rhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7844 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7845
7846 /* analyze conflict */
7848
7850 *cutoff = TRUE;
7851 }
7852 else if( SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
7853 {
7854 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (lhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7855 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7856
7857 /* analyze conflict */
7859
7861 *cutoff = TRUE;
7862 }
7863 else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
7864 {
7865 SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7866 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7867
7868 /* remove the constraint locally unless it has become empty, in which case it is removed globally */
7869 if( consdata->nvars > 0 )
7871 else
7872 SCIP_CALL( SCIPdelCons(scip, cons) );
7873 }
7874 }
7875 }
7876
7877 return SCIP_OKAY;
7878}
7879
7880
7881/*
7882 * Presolving methods
7883 */
7884
7885/** converts all variables with fixed domain into FIXED variables */
7886static
7888 SCIP* scip, /**< SCIP data structure */
7889 SCIP_CONS* cons, /**< linear constraint */
7890 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
7891 int* nfixedvars /**< pointer to count the total number of fixed variables */
7892 )
7893{
7894 SCIP_CONSDATA* consdata;
7895 SCIP_VAR* var;
7896 SCIP_VARSTATUS varstatus;
7897 SCIP_Real lb;
7898 SCIP_Real ub;
7899 SCIP_Bool fixed;
7900 SCIP_Bool infeasible;
7901 int v;
7902
7903 assert(scip != NULL);
7904 assert(cons != NULL);
7905 assert(cutoff != NULL);
7906 assert(nfixedvars != NULL);
7907
7908 consdata = SCIPconsGetData(cons);
7909 assert(consdata != NULL);
7910
7911 for( v = 0; v < consdata->nvars; ++v )
7912 {
7913 assert(consdata->vars != NULL);
7914 var = consdata->vars[v];
7915 varstatus = SCIPvarGetStatus(var);
7916
7917 if( varstatus != SCIP_VARSTATUS_FIXED )
7918 {
7919 lb = SCIPvarGetLbGlobal(var);
7920 ub = SCIPvarGetUbGlobal(var);
7921 if( SCIPisEQ(scip, lb, ub) )
7922 {
7923 SCIP_Real fixval;
7924
7926 SCIPdebugMsg(scip, "converting variable <%s> with fixed bounds [%.15g,%.15g] into fixed variable fixed at %.15g\n",
7927 SCIPvarGetName(var), lb, ub, fixval);
7928 SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
7929 if( infeasible )
7930 {
7931 SCIPdebugMsg(scip, " -> infeasible fixing\n");
7932 *cutoff = TRUE;
7933 return SCIP_OKAY;
7934 }
7935 if( fixed )
7936 (*nfixedvars)++;
7937 }
7938 }
7939 }
7940
7941 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
7942
7943 if( infeasible )
7944 {
7945 SCIPdebugMsg(scip, " -> infeasible fixing\n");
7946 *cutoff = TRUE;
7947 return SCIP_OKAY;
7948 }
7949
7950 assert(consdata->removedfixings);
7951
7952 return SCIP_OKAY;
7953}
7954
7955#define MAX_CLIQUE_NONZEROS_PER_CONS 1000000
7956
7957/** extracts cliques of the constraint and adds them to SCIP
7958 *
7959 * The following clique extraction mechanism are implemeneted
7960 *
7961 * 1. collect binary variables and sort them in non increasing order, then
7962 *
7963 * a) if the constraint has a finite right hand side and the negative infinity counters for the minactivity are zero
7964 * then add the variables as a clique for which all successive pairs of coefficients fullfill the following
7965 * condition
7966 *
7967 * minactivity + vals[i] + vals[i+1] > rhs
7968 *
7969 * and also add the binary to binary implication also for non-successive variables for which the same argument
7970 * holds
7971 *
7972 * minactivity + vals[i] + vals[j] > rhs
7973 *
7974 * 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
7975 * binary to binary implications x1 = 1 => x4 = 0 and x2 = 1 => x4 = 0
7976 *
7977 * b) if the constraint has a finite left hand side and the positive infinity counters for the maxactivity are zero
7978 * then add the variables as a clique for which all successive pairs of coefficients fullfill the follwoing
7979 * condition
7980 *
7981 * maxactivity + vals[i] + vals[i-1] < lhs
7982 *
7983 * and also add the binary to binary implication also for non-successive variables for which the same argument
7984 * holds
7985 *
7986 * maxactivity + vals[i] + vals[j] < lhs
7987 *
7988 * e.g. you could multiply the above example by -1
7989 *
7990 * c) the constraint has a finite right hand side and a finite minactivity then add the variables as a negated
7991 * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7992 * condition
7993 *
7994 * minactivity - vals[i] - vals[i-1] > rhs
7995 *
7996 * and also add the binary to binary implication also for non-successive variables for which the
7997 * same argument holds
7998 *
7999 * minactivity - vals[i] - vals[j] > rhs
8000 *
8001 * e.g. -4 x1 -3 x2 - 2 x3 + 2 x4 <= -4 would lead to the (negated) clique (~x1, ~x2) and the binary to binary
8002 * implication x1 = 0 => x3 = 1
8003 *
8004 * d) the constraint has a finite left hand side and a finite maxactivity then add the variables as a negated
8005 * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
8006 * condition
8007 *
8008 * maxactivity - vals[i] - vals[i+1] < lhs
8009 *
8010 * and also add the binary to binary implication also for non-successive variables for which the same argument
8011 * holds
8012 *
8013 * maxactivity - vals[i] - vals[j] < lhs
8014 *
8015 * e.g. you could multiply the above example by -1
8016 *
8017 * 2. if the linear constraint represents a set-packing or set-partitioning constraint, the whole constraint is added
8018 * as clique, (this part is done at the end of the method)
8019 *
8020 */
8021static
8023 SCIP* scip, /**< SCIP data structure */
8024 SCIP_CONS* cons, /**< linear constraint */
8025 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
8026 SCIP_Bool sortvars, /**< should variables be used in sorted order? */
8027 int* nfixedvars, /**< pointer to count number of fixed variables */
8028 int* nchgbds, /**< pointer to count the total number of tightened bounds */
8029 SCIP_Bool* cutoff /**< pointer to store TRUE, if a cutoff was found */
8030 )
8031{
8032 SCIP_VAR** vars;
8033 SCIP_Real* vals;
8034 SCIP_CONSDATA* consdata;
8035 SCIP_Bool lhsclique;
8036 SCIP_Bool rhsclique;
8037 SCIP_Bool finitelhs;
8038 SCIP_Bool finiterhs;
8039 SCIP_Bool finiteminact;
8040 SCIP_Bool finitemaxact;
8041 SCIP_Bool finitenegminact;
8042 SCIP_Bool finitenegmaxact;
8043 SCIP_Bool finiteposminact;
8044 SCIP_Bool finiteposmaxact;
8045 SCIP_Bool infeasible;
8046 SCIP_Bool stopped;
8048 int v;
8049 int i;
8050 int nposcoefs;
8051 int nnegcoefs;
8052 int nvars;
8053
8054 assert(scip != NULL);
8055 assert(cons != NULL);
8056 assert(nfixedvars != NULL);
8057 assert(nchgbds != NULL);
8058 assert(cutoff != NULL);
8059 assert(!SCIPconsIsDeleted(cons));
8060
8061 consdata = SCIPconsGetData(cons);
8062 assert(consdata != NULL);
8063
8064 if( consdata->nvars < 2 )
8065 return SCIP_OKAY;
8066
8067 /* add implications if posibble
8068 *
8069 * for now we only add binary to non-binary implications, and this is only done for the binary variable with the
8070 * maximal absolute contribution and also only if this variable would force all other variables to their bound
8071 * corresponding to the global minimal activity of the constraint
8072 */
8073 if( !consdata->implsadded )
8074 {
8075 /* sort variables by variable type */
8076 SCIP_CALL( consdataSort(scip, consdata) );
8077
8078 /* @todo we might extract implications/cliques if SCIPvarIsBinary() variables exist and we have integer variables
8079 * up front, might change sorting correspondingly
8080 */
8081 /* fast abort if no binaries exist */
8082 if( !SCIPvarIsBinary(consdata->vars[0]) )
8083 {
8084#ifndef NDEBUG
8085 for( i = 1; i < consdata->nvars; i++ )
8086 assert(!SCIPvarIsBinary(consdata->vars[i]));
8087#endif
8088 return SCIP_OKAY;
8089 }
8090 nvars = consdata->nvars;
8091 vars = consdata->vars;
8092 vals = consdata->vals;
8093
8094 /* recompute activities if needed */
8095 if( !consdata->validactivities )
8096 consdataCalcActivities(scip, consdata);
8097 assert(consdata->validactivities);
8098
8099 finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8100 finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8101 finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8102 finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8103 finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8104 finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8107
8109 {
8110 SCIP_Real maxabscontrib = -1.0;
8111 SCIP_Bool posval = FALSE;
8112 SCIP_Bool allbinary = TRUE;
8113 int oldnchgbds = *nchgbds;
8114 int nbdchgs = 0;
8115 int nimpls = 0;
8116 int position = -1;
8117
8118 /* we need a valid minimal/maximal activity to add cliques */
8119 if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8120 {
8122 assert(consdata->validglbminact);
8123 }
8124
8125 if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8126 {
8128 assert(consdata->validglbmaxact);
8129 }
8130 assert(consdata->validglbminact || consdata->validglbmaxact);
8131
8132 /* @todo extend this to local/constraint probing */
8133
8134 /* determine maximal contribution to the activity */
8135 for( v = nvars - 1; v >= 0; --v )
8136 {
8137 if( SCIPvarIsBinary(vars[v]) )
8138 {
8139 if( vals[v] > 0 )
8140 {
8141 SCIP_Real value = vals[v] * SCIPvarGetUbGlobal(vars[v]);
8142
8143 if( value > maxabscontrib )
8144 {
8145 maxabscontrib = value;
8146 position = v;
8147 posval = TRUE;
8148 }
8149 }
8150 else
8151 {
8152 SCIP_Real value = vals[v] * SCIPvarGetLbGlobal(vars[v]);
8153
8154 value = REALABS(value);
8155
8156 if( value > maxabscontrib )
8157 {
8158 maxabscontrib = value;
8159 position = v;
8160 posval = FALSE;
8161 }
8162 }
8163 }
8164 else
8165 allbinary = FALSE;
8166 }
8167 assert(0 <= position && position < nvars);
8168
8169 if( !SCIPisEQ(scip, maxabscontrib, 1.0) && !allbinary )
8170 {
8171 /* if the right hand side and the minimal activity are finite and changing the variable with the biggest
8172 * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8173 * implications
8174 */
8175 if( finiterhs && finiteminact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbminactivity), consdata->rhs - maxabscontrib) )
8176 {
8177 for( v = nvars - 1; v >= 0; --v )
8178 {
8179 /* binary to binary implications will be collected when extrating cliques */
8180 if( !SCIPvarIsBinary(vars[v]) )
8181 {
8182 if( v != position )
8183 {
8184 if( vals[v] > 0 )
8185 {
8186 /* add implications */
8187 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8188 ++nimpls;
8189 *nchgbds += nbdchgs;
8190 }
8191 else
8192 {
8193 /* add implications */
8194 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8195 ++nimpls;
8196 *nchgbds += nbdchgs;
8197 }
8198
8199 if( infeasible )
8200 {
8201 *cutoff = TRUE;
8202 break;
8203 }
8204 }
8205 }
8206 /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8207 else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8208 break;
8209 }
8210 }
8211
8212 /* if the left hand side and the maximal activity are finite and changing the variable with the biggest
8213 * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8214 * implications
8215 */
8216 if( finitelhs && finitemaxact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbmaxactivity), consdata->lhs - maxabscontrib) )
8217 {
8218 for( v = nvars - 1; v >= 0; --v )
8219 {
8220 /* binary to binary implications will be collected when extrating cliques */
8221 if( !SCIPvarIsBinary(vars[v]) )
8222 {
8223 if( v != position )
8224 {
8225 if( vals[v] > 0 )
8226 {
8227 /* add implications */
8228 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8229 ++nimpls;
8230 *nchgbds += nbdchgs;
8231 }
8232 else
8233 {
8234 /* add implications */
8235 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8236 ++nimpls;
8237 *nchgbds += nbdchgs;
8238 }
8239
8240 if( infeasible )
8241 {
8242 *cutoff = TRUE;
8243 break;
8244 }
8245 }
8246 }
8247 /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8248 else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8249 break;
8250 }
8251 }
8252
8253 /* did we find some implications */
8254 if( nimpls > 0 )
8255 {
8256 SCIPdebugMsg(scip, "extracted %d implications from constraint %s which led to %d bound changes, %scutoff detetcted\n", nimpls, SCIPconsGetName(cons), *nchgbds - oldnchgbds, *cutoff ? "" : "no ");
8257
8258 if( *cutoff )
8259 return SCIP_OKAY;
8260
8261 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8262 if( *nchgbds - oldnchgbds > 0 )
8263 {
8264 /* check for fixed variables */
8265 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8266 if( *cutoff )
8267 return SCIP_OKAY;
8268
8269 /* tighten variable's bounds */
8270 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8271 if( *cutoff )
8272 return SCIP_OKAY;
8273
8274 /* check for fixed variables */
8275 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8276 if( *cutoff )
8277 return SCIP_OKAY;
8278 }
8279 }
8280 }
8281 }
8282
8283 consdata->implsadded = TRUE;
8284 }
8285
8286 /* check if we already added the cliques of this constraint */
8287 if( consdata->cliquesadded )
8288 return SCIP_OKAY;
8289
8290 consdata->cliquesadded = TRUE;
8292 stopped = FALSE;
8293
8294 /* sort variables by variable type */
8295 SCIP_CALL( consdataSort(scip, consdata) );
8296
8297 nvars = consdata->nvars;
8298 vars = consdata->vars;
8299 vals = consdata->vals;
8300
8301 /**@todo extract more cliques, implications and variable bounds from linear constraints */
8302
8303 /* recompute activities if needed */
8304 if( !consdata->validactivities )
8305 consdataCalcActivities(scip, consdata);
8306 assert(consdata->validactivities);
8307
8308 finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8309 finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8310 finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8311 finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8312 finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8313 finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8316
8317 /* 1. we wheck whether some variables do not fit together into this constraint and add the corresponding clique
8318 * information
8319 */
8321 {
8322 SCIP_VAR** binvars;
8323 SCIP_Real* binvarvals;
8324 int nposbinvars = 0;
8325 int nnegbinvars = 0;
8326 int allonebinary = 0;
8327
8330
8331 /* collect binary variables */
8332 for( i = 0; i < nvars; ++i )
8333 {
8334 if( SCIPvarIsBinary(vars[i]) )
8335 {
8336 assert(!SCIPisZero(scip, vals[i]));
8337
8338 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8339 ++allonebinary;
8340
8341 binvars[nposbinvars + nnegbinvars] = vars[i];
8343
8344 if( SCIPisPositive(scip, vals[i]) )
8345 ++nposbinvars;
8346 else
8347 ++nnegbinvars;
8348
8350 }
8351 /* stop searching for binary variables, because the constraint data is sorted */
8353 break;
8354 }
8356
8357 /* setppc constraints will be handled later; we need at least two binary variables with same sign to extract
8358 * cliques
8359 */
8360 if( allonebinary < nvars && (nposbinvars >= 2 || nnegbinvars >= 2) )
8361 {
8362 SCIP_Real threshold;
8363 int oldnchgbds = *nchgbds;
8364 int nbdchgs;
8365 int jstart;
8366 int j;
8367
8368 /* we need a valid minimal/maximal activity to add cliques */
8369 if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8370 {
8372 assert(consdata->validglbminact);
8373 }
8374
8375 if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8376 {
8378 assert(consdata->validglbmaxact);
8379 }
8380 assert(consdata->validglbminact || consdata->validglbmaxact);
8381
8382 /* sort coefficients non-increasing to be faster in the clique search */
8384
8385 /* case a) */
8386 if( finiterhs && finitenegminact && nposbinvars >= 2 )
8387 {
8388 /* compute value that needs to be exceeded */
8389 threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
8390
8391 j = 1;
8392#ifdef SCIP_DISABLED_CODE /* assertion should only hold when constraints were fully propagated and boundstightened */
8393 /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8395#endif
8396 /* check if at least two variables are in a clique */
8398 {
8399 ++j;
8400 /* check for extending the clique */
8401 while( j < nposbinvars )
8402 {
8404 break;
8405 ++j;
8406 }
8407 assert(j >= 2);
8408
8409 /* add clique with at least two variables */
8410 SCIP_CALL( SCIPaddClique(scip, binvars, NULL, j, FALSE, &infeasible, &nbdchgs) );
8411
8412 if( infeasible )
8413 *cutoff = TRUE;
8414
8415 *nchgbds += nbdchgs;
8416
8419 stopped = TRUE;
8420
8421 /* exchange the last variable in the clique if possible and add all new ones */
8422 if( !stopped && !(*cutoff) && j < nposbinvars )
8423 {
8424 SCIP_VAR** clqvars;
8425 int lastfit = j - 2;
8426 assert(lastfit >= 0);
8427
8428 /* copy all 'main'-clique variables */
8430
8431 /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8432 while( lastfit >= 0 && j < nposbinvars )
8433 {
8434 /* check if two variables are in a clique */
8436 {
8437 clqvars[lastfit + 1] = binvars[j];
8438
8439 /* add clique with at least two variables */
8440 SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8441
8442 if( infeasible )
8443 {
8444 *cutoff = TRUE;
8445 break;
8446 }
8447
8448 *nchgbds += nbdchgs;
8449
8452 {
8453 stopped = TRUE;
8454 break;
8455 }
8456
8457 ++j;
8458 }
8459 else
8460 --lastfit;
8461 }
8462
8464 }
8465 }
8466 }
8467
8468 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8469 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8470 {
8471 /* check for fixed variables */
8472 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8473
8474 if( !*cutoff )
8475 {
8476 /* tighten variable's bounds */
8477 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8478
8479 if( !*cutoff )
8480 {
8481 /* check for fixed variables */
8482 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8483
8484 if( !*cutoff )
8485 {
8486 /* sort variables by variable type */
8487 SCIP_CALL( consdataSort(scip, consdata) );
8488
8489 /* recompute activities if needed */
8490 if( !consdata->validactivities )
8491 consdataCalcActivities(scip, consdata);
8492 assert(consdata->validactivities);
8493
8494 nvars = consdata->nvars;
8495 vars = consdata->vars;
8496 vals = consdata->vals;
8497 nposbinvars = 0;
8498 nnegbinvars = 0;
8499 allonebinary = 0;
8500
8501 /* update binary variables */
8502 for( i = 0; i < nvars; ++i )
8503 {
8504 if( SCIPvarIsBinary(vars[i]) )
8505 {
8506 assert(!SCIPisZero(scip, vals[i]));
8507
8508 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8509 ++allonebinary;
8510
8511 binvars[nposbinvars + nnegbinvars] = vars[i];
8513
8514 if( SCIPisPositive(scip, vals[i]) )
8515 ++nposbinvars;
8516 else
8517 ++nnegbinvars;
8518
8520 }
8521 /* stop searching for binary variables, because the constraint data is sorted */
8523 break;
8524 }
8526 }
8527 }
8528 }
8529
8530 oldnchgbds = *nchgbds;
8531 }
8532
8533 /* case b) */
8534 if( !stopped && !(*cutoff) && finitelhs && finiteposmaxact && nnegbinvars >= 2 )
8535 {
8536 /* compute value that needs to be deceeded */
8537 threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
8538
8539 i = nposbinvars + nnegbinvars - 1;
8540 j = i - 1;
8541#if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8542 /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8544#endif
8545 /* check if two variables are in a clique */
8547 {
8548 --j;
8549 /* check for extending the clique */
8550 while( j >= nposbinvars )
8551 {
8553 break;
8554 --j;
8555 }
8556 jstart = j;
8557
8558 assert(i - j >= 2);
8559 /* add clique with at least two variables */
8560 SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), NULL, i - j, FALSE, &infeasible, &nbdchgs) );
8561
8562 if( infeasible )
8563 *cutoff = TRUE;
8564
8565 *nchgbds += nbdchgs;
8566
8567 cliquenonzerosadded += (i - j);
8569 stopped = TRUE;
8570
8571 /* exchange the last variable in the clique if possible and add all new ones */
8572 if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8573 {
8574 SCIP_VAR** clqvars;
8575 int lastfit = jstart + 1;
8576 assert(lastfit < i);
8577
8578 /* copy all 'main'-clique variables */
8580 ++lastfit;
8581
8582 /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8584 {
8585 /* check if two variables are in a clique */
8587 {
8588 assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8589 clqvars[lastfit - jstart - 2] = binvars[j];
8590
8591 assert(i - lastfit + 2 >= 2);
8592 /* add clique with at least two variables */
8593 SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), NULL, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8594
8595 if( infeasible )
8596 {
8597 *cutoff = TRUE;
8598 break;
8599 }
8600
8601 *nchgbds += nbdchgs;
8602
8603 cliquenonzerosadded += (i - lastfit + 2);
8605 {
8606 stopped = TRUE;
8607 break;
8608 }
8609
8610 --j;
8611 }
8612 else
8613 ++lastfit;
8614 }
8615
8617 }
8618 }
8619 }
8620
8621 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8622 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8623 {
8624 /* check for fixed variables */
8625 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8626
8627 if( !*cutoff )
8628 {
8629 /* tighten variable's bounds */
8630 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8631
8632 if( !*cutoff )
8633 {
8634 /* check for fixed variables */
8635 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8636
8637 if( !*cutoff )
8638 {
8639 /* sort variables by variable type */
8640 SCIP_CALL( consdataSort(scip, consdata) );
8641
8642 /* recompute activities if needed */
8643 if( !consdata->validactivities )
8644 consdataCalcActivities(scip, consdata);
8645 assert(consdata->validactivities);
8646
8647 nvars = consdata->nvars;
8648 vars = consdata->vars;
8649 vals = consdata->vals;
8650 nposbinvars = 0;
8651 nnegbinvars = 0;
8652 allonebinary = 0;
8653
8654 /* update binary variables */
8655 for( i = 0; i < nvars; ++i )
8656 {
8657 if( SCIPvarIsBinary(vars[i]) )
8658 {
8659 assert(!SCIPisZero(scip, vals[i]));
8660
8661 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8662 ++allonebinary;
8663
8664 binvars[nposbinvars + nnegbinvars] = vars[i];
8666
8667 if( SCIPisPositive(scip, vals[i]) )
8668 ++nposbinvars;
8669 else
8670 ++nnegbinvars;
8671
8673 }
8674 /* stop searching for binary variables, because the constraint data is sorted */
8676 break;
8677 }
8679 }
8680 }
8681 }
8682
8683 oldnchgbds = *nchgbds;
8684 }
8685
8686 /* case c) */
8687 if( !(*cutoff) && finiterhs && finiteminact && nnegbinvars >= 2 )
8688 {
8689 SCIP_Bool* values;
8690
8691 /* initialize clique values array for adding a negated clique */
8694
8695 /* compute value that needs to be exceeded */
8696 threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
8697
8698 i = nposbinvars + nnegbinvars - 1;
8699 j = i - 1;
8700
8701#if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8702 /* check if the variable should not have already been fixed to one */
8704#endif
8705
8707 {
8708 --j;
8709 /* check for extending the clique */
8710 while( j >= nposbinvars )
8711 {
8713 break;
8714 --j;
8715 }
8716 jstart = j;
8717
8718 assert(i - j >= 2);
8719 /* add negated clique with at least two variables */
8720 SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), values, i - j, FALSE, &infeasible, &nbdchgs) );
8721
8722 if( infeasible )
8723 *cutoff = TRUE;
8724
8725 *nchgbds += nbdchgs;
8726
8727 cliquenonzerosadded += (i - j);
8729 stopped = TRUE;
8730
8731 /* exchange the last variable in the clique if possible and add all new ones */
8732 if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8733 {
8734 SCIP_VAR** clqvars;
8735 int lastfit = j + 1;
8736 assert(lastfit < i);
8737
8738 /* copy all 'main'-clique variables */
8740 ++lastfit;
8741
8742 /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8744 {
8745 /* check if two variables are in a negated clique */
8747 {
8748 assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8749 clqvars[lastfit - jstart - 2] = binvars[j];
8750
8751 assert(i - lastfit + 2 >= 2);
8752 /* add clique with at least two variables */
8753 SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), values, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8754
8755 if( infeasible )
8756 {
8757 *cutoff = TRUE;
8758 break;
8759 }
8760
8761 *nchgbds += nbdchgs;
8762
8763 cliquenonzerosadded += (i - lastfit + 2);
8765 {
8766 stopped = TRUE;
8767 break;
8768 }
8769
8770 --j;
8771 }
8772 else
8773 ++lastfit;
8774 }
8775
8777 }
8778 }
8779
8780 SCIPfreeBufferArray(scip, &values);
8781 }
8782
8783 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8784 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8785 {
8786 /* check for fixed variables */
8787 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8788
8789 if( !*cutoff )
8790 {
8791 /* tighten variable's bounds */
8792 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8793
8794 if( !*cutoff )
8795 {
8796 /* check for fixed variables */
8797 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8798
8799 if( !*cutoff )
8800 {
8801 /* sort variables by variable type */
8802 SCIP_CALL( consdataSort(scip, consdata) );
8803
8804 /* recompute activities if needed */
8805 if( !consdata->validactivities )
8806 consdataCalcActivities(scip, consdata);
8807 assert(consdata->validactivities);
8808
8809 nvars = consdata->nvars;
8810 vars = consdata->vars;
8811 vals = consdata->vals;
8812 nposbinvars = 0;
8813 nnegbinvars = 0;
8814 allonebinary = 0;
8815
8816 /* update binary variables */
8817 for( i = 0; i < nvars; ++i )
8818 {
8819 if( SCIPvarIsBinary(vars[i]) )
8820 {
8821 assert(!SCIPisZero(scip, vals[i]));
8822
8823 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8824 ++allonebinary;
8825
8826 binvars[nposbinvars + nnegbinvars] = vars[i];
8828
8829 if( SCIPisPositive(scip, vals[i]) )
8830 ++nposbinvars;
8831 else
8832 ++nnegbinvars;
8833
8835 }
8836 /* stop searching for binary variables, because the constraint data is sorted */
8838 break;
8839 }
8841 }
8842 }
8843 }
8844 }
8845
8846 /* case d) */
8847 if( !stopped && !(*cutoff) && finitelhs && finitemaxact && nposbinvars >= 2 )
8848 {
8849 SCIP_Bool* values;
8850
8851 /* initialize clique values array for adding a negated clique */
8854
8855 /* compute value that needs to be exceeded */
8856 threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
8857
8858 j = 1;
8859
8860#if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8861 /* check if the variable should not have already been fixed to one */
8863#endif
8864
8866 {
8867 ++j;
8868 /* check for extending the clique */
8869 while( j < nposbinvars )
8870 {
8872 break;
8873 ++j;
8874 }
8875 assert(j >= 2);
8876
8877 /* add negated clique with at least two variables */
8878 SCIP_CALL( SCIPaddClique(scip, binvars, values, j, FALSE, &infeasible, &nbdchgs) );
8879
8880 if( infeasible )
8881 *cutoff = TRUE;
8882
8883 *nchgbds += nbdchgs;
8884
8887 stopped = TRUE;
8888
8889 /* exchange the last variable in the clique if possible and add all new ones */
8890 if( !stopped && !(*cutoff) && j < nposbinvars )
8891 {
8892 SCIP_VAR** clqvars;
8893 int lastfit = j - 2;
8894 assert(lastfit >= 0);
8895
8896 /* copy all 'main'-clique variables */
8898
8899 /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8900 while( lastfit >= 0 && j < nposbinvars )
8901 {
8902 /* check if two variables are in a negated clique */
8904 {
8905 clqvars[lastfit + 1] = binvars[j];
8906
8907 /* add clique with at least two variables */
8908 SCIP_CALL( SCIPaddClique(scip, clqvars, values, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8909
8910 if( infeasible )
8911 {
8912 *cutoff = TRUE;
8913 break;
8914 }
8915
8916 *nchgbds += nbdchgs;
8917
8920 break;
8921
8922 ++j;
8923 }
8924 else
8925 --lastfit;
8926 }
8927
8929 }
8930 }
8931
8932 SCIPfreeBufferArray(scip, &values);
8933 }
8934 }
8935
8937 SCIPfreeBufferArray(scip, &binvars);
8938
8939 if( *cutoff )
8940 return SCIP_OKAY;
8941 }
8942
8943 /* 2. we only check if the constraint is a set packing / partitioning constraint */
8944
8945 /* check if all variables are binary, if the coefficients are +1 or -1, and if the right hand side is equal
8946 * to 1 - number of negative coefficients, or if the left hand side is equal to number of positive coefficients - 1
8947 */
8948 nposcoefs = 0;
8949 nnegcoefs = 0;
8950 for( i = 0; i < nvars; ++i )
8951 {
8952 if( !SCIPvarIsBinary(vars[i]) )
8953 return SCIP_OKAY;
8954 else if( SCIPisEQ(scip, vals[i], +1.0) )
8955 nposcoefs++;
8956 else if( SCIPisEQ(scip, vals[i], -1.0) )
8957 nnegcoefs++;
8958 else
8959 return SCIP_OKAY;
8960 }
8961
8962 lhsclique = SCIPisEQ(scip, consdata->lhs, (SCIP_Real)nposcoefs - 1.0);
8963 rhsclique = SCIPisEQ(scip, consdata->rhs, 1.0 - (SCIP_Real)nnegcoefs);
8964
8965 if( lhsclique || rhsclique )
8966 {
8967 SCIP_Bool* values;
8968 int nbdchgs;
8969
8970 SCIPdebugMsg(scip, "linear constraint <%s>: adding clique with %d vars (%d pos, %d neg)\n",
8973
8974 for( i = 0; i < nvars; ++i )
8975 values[i] = (rhsclique == (vals[i] > 0.0));
8976
8977 SCIP_CALL( SCIPaddClique(scip, vars, values, nvars, SCIPisEQ(scip, consdata->lhs, consdata->rhs), &infeasible, &nbdchgs) );
8978
8979 if( infeasible )
8980 *cutoff = TRUE;
8981
8982 *nchgbds += nbdchgs;
8983 SCIPfreeBufferArray(scip, &values);
8984 }
8985
8986 return SCIP_OKAY;
8987}
8988
8989/** tightens left and right hand side of constraint due to integrality */
8990static
8992 SCIP* scip, /**< SCIP data structure */
8993 SCIP_CONS* cons, /**< linear constraint */
8994 int* nchgsides, /**< pointer to count number of side changes */
8995 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
8996 )
8997{
8998 SCIP_CONSDATA* consdata;
8999 SCIP_Real newlhs;
9000 SCIP_Real newrhs;
9001 SCIP_Bool chglhs;
9002 SCIP_Bool chgrhs;
9003 SCIP_Bool integral;
9004 int i;
9005
9006 assert(scip != NULL);
9007 assert(cons != NULL);
9008 assert(nchgsides != NULL);
9009 assert(infeasible != NULL);
9010
9011 consdata = SCIPconsGetData(cons);
9012 assert(consdata != NULL);
9013
9014 *infeasible = FALSE;
9015
9016 chglhs = FALSE;
9017 chgrhs = FALSE;
9020
9021 if( !SCIPisIntegral(scip, consdata->lhs) || !SCIPisIntegral(scip, consdata->rhs) )
9022 {
9023 integral = TRUE;
9024 for( i = 0; i < consdata->nvars && integral; ++i )
9025 {
9026 integral = SCIPisIntegral(scip, consdata->vals[i])
9027 && (SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS);
9028 }
9029 if( integral )
9030 {
9031 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisIntegral(scip, consdata->lhs) )
9032 {
9033 newlhs = SCIPfeasCeil(scip, consdata->lhs);
9034 chglhs = TRUE;
9035 }
9036 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisIntegral(scip, consdata->rhs) )
9037 {
9038 newrhs = SCIPfeasFloor(scip, consdata->rhs);
9039 chgrhs = TRUE;
9040 }
9041
9042 /* check whether rounding would lead to an unsatisfiable constraint */
9043 if( SCIPisGT(scip, newlhs, newrhs) )
9044 {
9045 SCIPdebugMsg(scip, "rounding sides=[%.15g,%.15g] of linear constraint <%s> with integral coefficients and variables only "
9046 "is infeasible\n", consdata->lhs, consdata->rhs, SCIPconsGetName(cons));
9047
9048 *infeasible = TRUE;
9049 return SCIP_OKAY;
9050 }
9051
9052 SCIPdebugMsg(scip, "linear constraint <%s>: make sides integral: sides=[%.15g,%.15g]\n",
9053 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
9054
9055 if( chglhs )
9056 {
9058
9059 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9060 if( !consdata->upgraded )
9061 (*nchgsides)++;
9062 }
9063 if( chgrhs )
9064 {
9066
9067 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9068 if( !consdata->upgraded )
9069 (*nchgsides)++;
9070 }
9071 SCIPdebugMsg(scip, "linear constraint <%s>: new integral sides: sides=[%.15g,%.15g]\n",
9072 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
9073 }
9074 }
9075
9076 return SCIP_OKAY;
9077}
9078
9079/** tightens coefficients of binary, integer, and implicit integer variables due to activity bounds in presolving:
9080 * given an inequality lhs <= a*x + ai*xi <= rhs, with a non-continuous variable li <= xi <= ui
9081 * let minact := min{a*x + ai*xi}, maxact := max{a*x + ai*xi}
9082 * (i) ai >= 0:
9083 * if minact + ai >= lhs and maxact - ai <= rhs: (**)
9084 * - a deviation from the lower/upper bound of xi would make the left/right hand side redundant
9085 * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
9086 * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
9087 * - change coefficients:
9088 * ai' := max(lhs - minact, maxact - rhs)
9089 * lhs' := lhs - (ai - ai')*li
9090 * rhs' := rhs - (ai - ai')*ui
9091 * (ii) ai < 0:
9092 * if minact - ai >= lhs and maxact + ai <= rhs: (***)
9093 * - a deviation from the upper/lower bound of xi would make the left/right hand side redundant
9094 * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
9095 * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
9096 * - change coefficients:
9097 * ai' := min(rhs - maxact, minact - lhs)
9098 * lhs' := lhs - (ai - ai')*ui
9099 * rhs' := rhs - (ai - ai')*li
9100 *
9101 * We further try to remove redundant variable from the constraint;
9102 * Variables which fulfill conditions (**) or (***) are called surely non-redundant variables.
9103 * A deviation of only one from their bound makes the lhs/rhs feasible (i.e., redundant), even if all other
9104 * variables are set to their "worst" bound. If all variables which are not surely non-redundant cannot make
9105 * the lhs/rhs redundant, even if they are set to their "best" bound, they can be removed from the constraint.
9106 * E.g., for binary variables and an inequality x_1 +x_2 +10y_1 +10y_2 >= 5, setting either of the y_i to one
9107 * suffices to fulfill the inequality, whereas the x_i do not contribute to feasibility and can be removed.
9108 *
9109 * @todo use also some tightening procedures for (knapsack) constraints with non-integer coefficients, see
9110 * cons_knapsack.c the following methods detectRedundantVars() and tightenWeights()
9111 */
9112static
9114 SCIP* scip, /**< SCIP data structure */
9115 SCIP_CONS* cons, /**< linear constraint */
9116 int* nchgcoefs, /**< pointer to count total number of changed coefficients */
9117 int* nchgsides /**< pointer to count number of side changes */
9118 )
9119{
9120 SCIP_CONSDATA* consdata;
9121 SCIP_VAR* var;
9122 SCIP_Real minactivity; /* minimal value w.r.t. the variable's local bounds for the constraint's
9123 * activity, ignoring the coefficients contributing with infinite value */
9124 SCIP_Real maxactivity; /* maximal value w.r.t. the variable's local bounds for the constraint's
9125 * activity, ignoring the coefficients contributing with infinite value */
9126 SCIP_Bool minactisrelax; /* do huge finite values contribute to the minactivity? */
9127 SCIP_Bool maxactisrelax; /* do huge finite values contribute to the maxactivity? */
9128 SCIP_Bool isminsettoinfinity;
9129 SCIP_Bool ismaxsettoinfinity;
9130 SCIP_Real minleftactivity; /* minimal activity without surely non-redundant variables. */
9131 SCIP_Real maxleftactivity; /* maximal activity without surely non-redundant variables. */
9132 SCIP_Real aggrlhs; /* lhs without minimal activity of surely non-redundant variables. */
9133 SCIP_Real aggrrhs; /* rhs without maximal activity of surely non-redundant variables. */
9134 SCIP_Real lval; /* candidate for new value arising from considering the left hand side */
9135 SCIP_Real rval; /* candidate for new value arising from considering the left hand side */
9136 SCIP_Real val;
9137 SCIP_Real newval;
9138 SCIP_Real newlhs;
9139 SCIP_Real newrhs;
9140 SCIP_Real lb;
9141 SCIP_Real ub;
9142 int i;
9143
9144 assert(scip != NULL);
9145 assert(cons != NULL);
9146 assert(nchgcoefs != NULL);
9147 assert(nchgsides != NULL);
9148
9149 consdata = SCIPconsGetData(cons);
9150 assert(consdata != NULL);
9151
9152 /* @todo Is this still needed with automatic recomputation of activities? */
9153 /* if the maximal coefficient is too large, recompute the activities */
9154 if( (consdata->validmaxabsval && consdata->maxabsval > MAXVALRECOMP)
9155 || (consdata->validminabsval && consdata->minabsval < MINVALRECOMP) )
9156 {
9159 }
9160
9161 /* get the minimal and maximal activity of the constraint */
9162 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9164
9165 minleftactivity = 0.0;
9166 maxleftactivity = 0.0;
9167
9168 /* try to tighten each coefficient */
9169 i = 0;
9170 while( i < consdata->nvars )
9171 {
9172 var = consdata->vars[i];
9173
9174 /* get coefficient and variable's bounds */
9175 lb = SCIPvarGetLbLocal(var);
9176 ub = SCIPvarGetUbLocal(var);
9177 val = consdata->vals[i];
9178 assert(!SCIPisZero(scip, val));
9179
9180 /* check sign of coefficient */
9181 if( val >= 0.0 )
9182 {
9183 /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9185 SCIPisGE(scip, minactivity + val, consdata->lhs) && SCIPisLE(scip, maxactivity - val, consdata->rhs) )
9186 {
9187 /* change coefficients:
9188 * ai' := max(lhs - minact, maxact - rhs)
9189 * lhs' := lhs - (ai - ai')*li
9190 * rhs' := rhs - (ai - ai')*ui
9191 */
9192
9193 lval = consdata->lhs - minactivity;
9194 rval = maxactivity - consdata->rhs;
9195
9196 /* Try to avoid cancellation, if there are only two variables */
9197 if( consdata->nvars == 2 )
9198 {
9199 SCIP_Real otherval;
9200 otherval = consdata->vals[1-i];
9201
9202 if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9203 {
9204 lval = consdata->lhs - val*lb;
9205 lval -= otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9206 }
9207
9208 if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9209 {
9210 rval = val*ub - consdata->rhs;
9211 rval += otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9212 }
9213 }
9214
9215 newval = MAX(lval, rval);
9216 assert(SCIPisSumRelLE(scip, newval, val));
9217
9218 /* Try to avoid cancellation in computation of lhs/rhs */
9219 newlhs = consdata->lhs - val * lb;
9220 newlhs += newval * lb;
9221 newrhs = consdata->rhs - val * ub;
9222 newrhs += newval * ub;
9223
9224 if( !SCIPisSumRelEQ(scip, newval, val) )
9225 {
9226 SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9227 SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
9228 minactivity, maxactivity, consdata->lhs, consdata->rhs);
9229
9230 /* update the coefficient and the activity bounds */
9231 if( SCIPisZero(scip, newval) )
9232 {
9233 SCIP_CALL( delCoefPos(scip, cons, i) );
9234 i--;
9235 }
9236 else
9237 {
9238 SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9239 }
9240 (*nchgcoefs)++;
9241
9242 /* get the new minimal and maximal activity of the constraint */
9243 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9245
9246 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9247 {
9248 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9249
9250 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9251 (*nchgsides)++;
9252 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9253 }
9254
9255 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9256 {
9257 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9258
9259 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9260 (*nchgsides)++;
9261 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9262 }
9263 }
9264 }
9265 else
9266 {
9268 {
9269 assert(!SCIPisInfinity(scip, val));
9270 assert(!SCIPisInfinity(scip, lb));
9271 if( SCIPisInfinity(scip, -lb) )
9273 else
9274 minleftactivity += val * lb;
9275 }
9276
9278 {
9279 assert(!SCIPisInfinity(scip, val));
9280 assert(!SCIPisInfinity(scip, -ub));
9281 if( SCIPisInfinity(scip,ub) )
9283 else
9284 maxleftactivity += val * ub;
9285 }
9286 }
9287 }
9288 else
9289 {
9290 /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9292 SCIPisGE(scip, minactivity - val, consdata->lhs) && SCIPisLE(scip, maxactivity + val, consdata->rhs) )
9293 {
9294 /* change coefficients:
9295 * ai' := min(rhs - maxact, minact - lhs)
9296 * lhs' := lhs - (ai - ai')*ui
9297 * rhs' := rhs - (ai - ai')*li
9298 */
9299
9300 lval = minactivity - consdata->lhs;
9301 rval = consdata->rhs - maxactivity;
9302
9303 /* Try to avoid cancellation, if there are only two variables */
9304 if( consdata->nvars == 2 )
9305 {
9306 SCIP_Real otherval;
9307 otherval = consdata->vals[1-i];
9308
9309 if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9310 {
9311 lval = val*ub - consdata->lhs;
9312 lval += otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9313 }
9314
9315 if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9316 {
9317 rval = consdata->rhs - val*lb;
9318 rval -= otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9319 }
9320 }
9321
9322 newval = MIN(lval, rval);
9323 assert(SCIPisSumRelGE(scip, newval, val));
9324
9325 /* Try to avoid cancellation in computation of lhs/rhs */
9326 newlhs = consdata->lhs - val * ub;
9327 newlhs += newval * ub;
9328 newrhs = consdata->rhs - val * lb;
9329 newrhs += newval * lb;
9330
9331 if( !SCIPisSumRelEQ(scip, newval, val) )
9332 {
9333 SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9334 SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
9335 minactivity, maxactivity, consdata->lhs, consdata->rhs);
9336
9337 /* update the coefficient and the activity bounds */
9338 if( SCIPisZero(scip, newval) )
9339 {
9340 SCIP_CALL( delCoefPos(scip, cons, i) );
9341 i--;
9342 }
9343 else
9344 {
9345 SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9346 }
9347 (*nchgcoefs)++;
9348
9349 /* get the new minimal and maximal activity of the constraint */
9350 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9352
9353 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9354 {
9355 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9356
9357 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9358 (*nchgsides)++;
9359 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9360 }
9361
9362 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9363 {
9364 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9365
9366 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9367 (*nchgsides)++;
9368 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9369 }
9370 }
9371 }
9372 else
9373 {
9375 {
9376 assert(!SCIPisInfinity(scip, -val));
9377 assert(!SCIPisInfinity(scip, -ub));
9378 if( SCIPisInfinity(scip, ub) )
9380 else
9381 minleftactivity += val * ub;
9382 }
9383
9385 {
9386 assert(!SCIPisInfinity(scip, -val));
9387 assert(!SCIPisInfinity(scip, lb));
9388 if( SCIPisInfinity(scip, -lb) )
9390 else
9391 maxleftactivity += val * lb;
9392 }
9393 }
9394 }
9395 ++i;
9396 }
9397
9398 SCIPdebugMsg(scip, "minleftactivity = %.15g, rhs = %.15g\n",
9399 minleftactivity, consdata->rhs);
9400 SCIPdebugMsg(scip, "maxleftactivity = %.15g, lhs = %.15g\n",
9401 maxleftactivity, consdata->lhs);
9402
9403 /* minleft == \infty ==> minactivity == \infty */
9406
9407 /* if the lhs is finite, we will check in the following whether the not non-redundant variables can make lhs feasible;
9408 * this is not valid, if the minactivity is -\infty (aggrlhs would be minus infinity in the following computation)
9409 * or if huge values contributed to the minactivity, because the minactivity is then just a relaxation
9410 * (<= the exact minactivity), and we might falsely claim variables to be redundant in the following
9411 */
9412 assert(!SCIPisInfinity(scip, minactivity));
9413 if( !SCIPisInfinity(scip, -consdata->lhs) && (SCIPisInfinity(scip, -minactivity) || minactisrelax) )
9414 return SCIP_OKAY;
9415
9416 /* if the rhs is finite, we will check in the following whether the not non-redundant variables can make rhs feasible;
9417 * this is not valid, if the maxactivity is \infty (aggrrhs would be infinity in the following computation)
9418 * or if huge values contributed to the maxactivity, because the maxactivity is then just a relaxation
9419 * (>= the exact maxactivity), and we might falsely claim variables to be redundant in the following
9420 */
9421 assert(!SCIPisInfinity(scip, -maxactivity));
9422 if( !SCIPisInfinity(scip, consdata->rhs) && (SCIPisInfinity(scip, maxactivity) || maxactisrelax) )
9423 return SCIP_OKAY;
9424
9425 /* correct lhs and rhs by min/max activity of surely non-redundant variables
9426 * surely non-redundant variables are all those where a deviation from the bound makes the lhs/rhs redundant
9427 */
9428 aggrlhs = consdata->lhs - minactivity + minleftactivity;
9429 aggrrhs = consdata->rhs - maxactivity + maxleftactivity;
9430
9431 /* check if the constraint contains variables which are redundant. The reasoning is the following:
9432 * Each non-redundant variable can make the lhs/rhs feasible with a deviation of only one in the bound.
9433 * If _all_ variables which are not non-redundant together cannot make lhs/rhs feasible,
9434 * they can be removed from the constraint.
9435 * aggrrhs may contain some near-infinity value, but only if rhs is infinity.
9436 */
9437 if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasLT(scip, maxleftactivity, aggrlhs))
9438 && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasGT(scip, minleftactivity, aggrrhs)) )
9439 {
9440 SCIP_Real minleftactivitypart;
9441 SCIP_Real maxleftactivitypart;
9442
9443 assert(!SCIPisInfinity(scip, -consdata->lhs) || !SCIPisInfinity(scip, consdata->rhs));
9444
9445 /* try to remove redundant variables from constraint */
9446 i = 0;
9447 while( i < consdata->nvars )
9448 {
9449 var = consdata->vars[i];
9450 minleftactivitypart = 0.0;
9451 maxleftactivitypart = 0.0;
9452 lb = SCIPvarGetLbLocal(var);
9453 ub = SCIPvarGetUbLocal(var);
9454
9455 /* get coefficient and variable's bounds */
9456 val = consdata->vals[i];
9457 assert(!SCIPisZero(scip, val));
9458
9459 /* check sign of coefficient */
9460 if( val >= 0.0 )
9461 {
9462 /* negation of condition above in case of positive val */
9464 SCIPisLT(scip, minactivity + val, consdata->lhs) || SCIPisGT(scip, maxactivity - val, consdata->rhs) )
9465 {
9466 SCIPdebugMsg(scip, "minactivity = %g\tval = %g\tlhs = %g\n", minactivity, val, consdata->lhs);
9467 SCIPdebugMsg(scip, "maxactivity = %g\tval = %g\trhs = %g\n", maxactivity, val, consdata->rhs);
9468 SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
9469 SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
9470
9471 minleftactivitypart = val * lb;
9472 maxleftactivitypart = val * ub;
9473
9474 SCIP_CALL( delCoefPos(scip, cons, i) );
9475 i--;
9476
9477 /* get the new minimal and maximal activity of the constraint */
9478 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9480
9481 /* we return above if the condition does not hold and deleting a variable cannot increase the number of
9482 * huge contributions
9483 */
9484 assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs));
9485 assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs));
9486 }
9487 }
9488 else
9489 {
9490 /* negation of condition above in case of negative val */
9492 SCIPisLT(scip, minactivity - val, consdata->lhs) || SCIPisGT(scip, maxactivity + val, consdata->rhs) )
9493 {
9494 SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
9495 SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
9496
9497 minleftactivitypart = val * ub;
9498 maxleftactivitypart = val * lb;
9499
9500 SCIP_CALL( delCoefPos(scip, cons, i) );
9501 i--;
9502
9503 /* get the new minimal and maximal activity of the constraint */
9504 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9506
9507 /* we return above if the condition does not hold and deleting a variable cannot increase the number of
9508 * huge contributions
9509 */
9510 assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs));
9511 assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs));
9512 }
9513 }
9514
9515 /* the following update step is needed in every iteration cause otherwise it is possible that the surely none-
9516 * redundant variables could get deleted,
9517 * e.g. y_1 + 16y_2 >= 25, y1 with bounds [9,12], y2 with bounds [0,2], minactivity would be 9, it follows that
9518 * y_2 is surely not redundant and y_1 is redundant so we would first delete y1 and without updating the sides
9519 * we would also delete y2 and as a result we would have gotten infeasibility */
9520 /* adjust lhs and right hand side */
9521 newlhs = consdata->lhs - minleftactivitypart;
9522 newrhs = consdata->rhs - maxleftactivitypart;
9523
9524 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisFeasEQ(scip, newlhs, consdata->lhs) )
9525 {
9526 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9527 SCIP_CALL( chgLhs(scip, cons, newlhs) );
9528 ++(*nchgsides);
9529 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9530 }
9531 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisFeasEQ(scip, newrhs, consdata->rhs) )
9532 {
9533 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9534 SCIP_CALL( chgRhs(scip, cons, newrhs) );
9535 ++(*nchgsides);
9536 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9537 }
9538 ++i;
9539 }
9540 }
9541
9542 return SCIP_OKAY;
9543}
9544
9545/** processes equality with only one variable by fixing the variable and deleting the constraint */
9546static
9548 SCIP* scip, /**< SCIP data structure */
9549 SCIP_CONS* cons, /**< linear constraint */
9550 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9551 int* nfixedvars, /**< pointer to count number of fixed variables */
9552 int* ndelconss /**< pointer to count number of deleted constraints */
9553 )
9554{
9555 SCIP_CONSDATA* consdata;
9556 SCIP_VAR* var;
9557 SCIP_Real val;
9558 SCIP_Real fixval;
9559 SCIP_Bool infeasible;
9560 SCIP_Bool fixed;
9561
9562 assert(scip != NULL);
9563 assert(cons != NULL);
9564 assert(cutoff != NULL);
9565 assert(nfixedvars != NULL);
9566 assert(ndelconss != NULL);
9567
9568 consdata = SCIPconsGetData(cons);
9569 assert(consdata != NULL);
9570 assert(consdata->nvars == 1);
9571 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9572
9573 /* calculate the value to fix the variable to */
9574 var = consdata->vars[0];
9575 val = consdata->vals[0];
9576 assert(!SCIPisZero(scip, val));
9577 fixval = SCIPselectSimpleValue(consdata->lhs/val - 0.9 * SCIPepsilon(scip),
9578 consdata->rhs/val + 0.9 * SCIPepsilon(scip), MAXDNOM);
9579 SCIPdebugMsg(scip, "linear equality <%s>: fix <%s> == %.15g\n",
9581
9582 /* fix variable */
9583 SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
9584 if( infeasible )
9585 {
9586 SCIPdebugMsg(scip, " -> infeasible fixing\n");
9587 *cutoff = TRUE;
9588 return SCIP_OKAY;
9589 }
9590 if( fixed )
9591 (*nfixedvars)++;
9592
9593 /* disable constraint */
9594 SCIP_CALL( SCIPdelCons(scip, cons) );
9595 if( !consdata->upgraded )
9596 (*ndelconss)++;
9597
9598 return SCIP_OKAY;
9599}
9600
9601/** processes equality with exactly two variables by aggregating one of the variables and deleting the constraint */
9602static
9604 SCIP* scip, /**< SCIP data structure */
9605 SCIP_CONS* cons, /**< linear constraint */
9606 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9607 int* naggrvars, /**< pointer to count number of aggregated variables */
9608 int* ndelconss /**< pointer to count number of deleted constraints */
9609 )
9610{
9611 SCIP_CONSDATA* consdata;
9612 SCIP_Bool infeasible;
9613 SCIP_Bool redundant;
9614 SCIP_Bool aggregated;
9615
9616 assert(scip != NULL);
9617 assert(cons != NULL);
9618 assert(cutoff != NULL);
9619 assert(naggrvars != NULL);
9620 assert(ndelconss != NULL);
9621
9622 consdata = SCIPconsGetData(cons);
9623 assert(consdata != NULL);
9624 assert(consdata->nvars == 2);
9625 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9626
9627 SCIPdebugMsg(scip, "linear constraint <%s>: aggregate %.15g<%s> + %.15g<%s> == %.15g\n",
9628 SCIPconsGetName(cons), consdata->vals[0], SCIPvarGetName(consdata->vars[0]),
9629 consdata->vals[1], SCIPvarGetName(consdata->vars[1]), consdata->rhs);
9630
9631 /* aggregate the equality */
9632 SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], consdata->vals[0], consdata->vals[1],
9633 consdata->rhs, &infeasible, &redundant, &aggregated) );
9634
9635 /* check for infeasibility of aggregation */
9636 if( infeasible )
9637 {
9638 SCIPdebugMsg(scip, " -> infeasible aggregation\n");
9639 *cutoff = TRUE;
9640 return SCIP_OKAY;
9641 }
9642
9643 /* count the aggregation */
9644 if( aggregated )
9645 (*naggrvars)++;
9646
9647 /* delete the constraint, if it is redundant */
9648 if( redundant )
9649 {
9650 SCIP_CALL( SCIPdelCons(scip, cons) );
9651
9652 if( !consdata->upgraded )
9653 (*ndelconss)++;
9654 }
9655
9656 return SCIP_OKAY;
9657}
9658
9659/** calculates the new lhs and rhs of the constraint after the given variable is aggregated out */
9660static
9662 SCIP* scip, /**< SCIP data structure */
9663 SCIP_CONSDATA* consdata, /**< linear constraint data */
9664 SCIP_VAR* slackvar, /**< variable to be aggregated out */
9665 SCIP_Real slackcoef, /**< coefficient of variable in constraint */
9666 SCIP_Real* newlhs, /**< pointer to store new lhs of constraint */
9667 SCIP_Real* newrhs /**< pointer to store new rhs of constraint */
9668 )
9669{
9670 SCIP_Real slackvarlb;
9671 SCIP_Real slackvarub;
9672
9673 assert(scip != NULL);
9674 assert(consdata != NULL);
9675 assert(newlhs != NULL);
9676 assert(newrhs != NULL);
9677 assert(!SCIPisInfinity(scip, -consdata->lhs));
9678 assert(!SCIPisInfinity(scip, consdata->rhs));
9679
9680 slackvarlb = SCIPvarGetLbGlobal(slackvar);
9681 slackvarub = SCIPvarGetUbGlobal(slackvar);
9682 if( slackcoef > 0.0 )
9683 {
9686 else
9687 *newrhs = consdata->rhs - slackcoef * slackvarlb;
9690 else
9691 *newlhs = consdata->lhs - slackcoef * slackvarub;
9692 }
9693 else
9694 {
9697 else
9698 *newlhs = consdata->rhs - slackcoef * slackvarlb;
9701 else
9702 *newrhs = consdata->lhs - slackcoef * slackvarub;
9703 }
9705}
9706
9707/** processes equality with more than two variables by multi-aggregating one of the variables and converting the equality
9708 * into an inequality; if multi-aggregation is not possible, tries to identify one continuous or integer variable that
9709 * is implicitly integral by this constraint
9710 *
9711 * @todo Check whether a more clever way of avoiding aggregation of variables containing implicitly integer variables
9712 * can help.
9713 */
9714static
9716 SCIP* scip, /**< SCIP data structure */
9717 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
9718 SCIP_CONS* cons, /**< linear constraint */
9719 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9720 int* naggrvars, /**< pointer to count number of aggregated variables */
9721 int* ndelconss /**< pointer to count number of deleted constraints */
9722 )
9723{
9724 SCIP_CONSDATA* consdata;
9725 SCIP_VAR** vars;
9726 SCIP_Real* vals;
9729 SCIP_Real lhs;
9730 SCIP_Real rhs;
9731 SCIP_Real bestslackdomrng;
9732 SCIP_Real minabsval;
9733 SCIP_Real maxabsval;
9734 SCIP_Bool bestremovescons;
9735 SCIP_Bool coefszeroone;
9736 SCIP_Bool coefsintegral;
9737 SCIP_Bool varsintegral;
9738 SCIP_Bool infeasible;
9739 SCIP_Bool samevar;
9740 int supinf; /* counter for infinite contributions to the supremum of a possible
9741 * multi-aggregation
9742 */
9743 int infinf; /* counter for infinite contributions to the infimum of a possible
9744 * multi-aggregation
9745 */
9746 int maxnlocksstay;
9747 int maxnlocksremove;
9748 int bestslackpos;
9749 int bestnlocks;
9750 int ncontvars;
9751 int contvarpos;
9752 int nintvars;
9753 int nimplvars;
9754 int intvarpos;
9755 int v;
9756
9757 assert(scip != NULL);
9758 assert(cons != NULL);
9759 assert(cutoff != NULL);
9760 assert(naggrvars != NULL);
9761
9762 consdata = SCIPconsGetData(cons);
9763 assert(consdata != NULL);
9764 assert(consdata->nvars > 2);
9765 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9766
9767 SCIPdebugMsg(scip, "linear constraint <%s>: try to multi-aggregate equality\n", SCIPconsGetName(cons));
9768
9769 /* We do not want to increase the total number of non-zeros due to the multi-aggregation.
9770 * Therefore, we have to restrict the number of locks of a variable that is aggregated out.
9771 * maxnlocksstay: maximal sum of lock numbers if the constraint does not become redundant after the aggregation
9772 * maxnlocksremove: maximal sum of lock numbers if the constraint can be deleted after the aggregation
9773 */
9774 lhs = consdata->lhs;
9775 rhs = consdata->rhs;
9776 maxnlocksstay = 0;
9777 if( consdata->nvars == 3 )
9778 {
9779 /* If the constraint becomes redundant, 3 non-zeros are removed, and we get 1 additional non-zero for each
9780 * constraint the variable appears in. Thus, the variable must appear in at most 3 other constraints.
9781 */
9782 maxnlocksremove = 3;
9783 }
9784 else if( consdata->nvars == 4 )
9785 {
9786 /* If the constraint becomes redundant, 4 non-zeros are removed, and we get 2 additional non-zeros for each
9787 * constraint the variable appears in. Thus, the variable must appear in at most 2 other constraints.
9788 */
9789 maxnlocksremove = 2;
9790 }
9791 else
9792 {
9793 /* If the constraint is redundant but has more than 4 variables, we can only accept one other constraint. */
9794 maxnlocksremove = 1;
9795 }
9796
9797 /* the locks on this constraint can be ignored */
9798 if( SCIPconsIsChecked(cons) )
9799 {
9800 if( !SCIPisInfinity(scip, -lhs) )
9801 {
9802 maxnlocksstay++;
9804 }
9805 if( !SCIPisInfinity(scip, rhs) )
9806 {
9807 maxnlocksstay++;
9809 }
9810 }
9811
9812 /* look for a slack variable s to convert a*x + s == b into lhs <= a*x <= rhs */
9813 vars = consdata->vars;
9814 vals = consdata->vals;
9815 bestslackpos = -1;
9819 bestslackdomrng = 0.0;
9823 ncontvars = 0;
9824 contvarpos = -1;
9825 nintvars = 0;
9826 nimplvars = 0;
9827 intvarpos = -1;
9828 minabsval = SCIPinfinity(scip);
9829 maxabsval = -1.0;
9830 for( v = 0; v < consdata->nvars; ++v )
9831 {
9832 SCIP_VAR* var;
9833 SCIP_Real val;
9834 SCIP_Real absval;
9835 SCIP_Real varlb;
9836 SCIP_Real varub;
9837 SCIP_Bool iscont;
9838 int nlocks;
9839
9840 assert(vars != NULL);
9841 assert(vals != NULL);
9842
9843 var = vars[v];
9844 assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= 1); /* because variable is locked in this equality */
9848
9849 val = vals[v];
9850 absval = REALABS(val);
9852
9853 /* calculate minimal and maximal absolute value */
9854 if( absval < minabsval )
9855 minabsval = absval;
9856 if( absval > maxabsval )
9857 maxabsval = absval;
9858
9859 /* do not try to multi aggregate, when numerical bad */
9860 if( maxabsval / minabsval > conshdlrdata->maxmultaggrquot )
9861 return SCIP_OKAY;
9862
9868
9869 /* update candidates for continuous -> implint and integer -> implint conversion */
9871 {
9872 ncontvars++;
9873 contvarpos = v;
9874 }
9875 else if( slacktype == SCIP_VARTYPE_IMPLINT )
9876 {
9877 ++nimplvars;
9878 }
9879 else if( slacktype == SCIP_VARTYPE_INTEGER )
9880 {
9881 nintvars++;
9882 intvarpos = v;
9883 }
9884
9885 /* check, if variable is already fixed or aggregated */
9886 if( !SCIPvarIsActive(var) )
9887 continue;
9888
9889 /* check, if variable is used in too many other constraints, even if this constraint could be deleted */
9891
9892 if( nlocks > maxnlocksremove )
9893 continue;
9894
9895 /* check, if variable can be used as a slack variable */
9896 if( (iscont || (coefsintegral && varsintegral && SCIPisEQ(scip, absval, 1.0))) &&
9898 {
9899 SCIP_Bool better;
9900 SCIP_Bool equal;
9901 SCIP_Real slackdomrng;
9902
9905 /* we do not want to perform multi-aggregation due to numerics, if the bounds are huge */
9907 return SCIP_OKAY;
9908 else
9909 {
9912 }
9913 equal = FALSE;
9914 better = (slacktype > bestslacktype) || (bestslackpos == -1);
9915 if( !better && slacktype == bestslacktype )
9916 {
9917 better = (nlocks < bestnlocks);
9918 if( nlocks == bestnlocks && !bestremovescons )
9919 {
9922 }
9923 }
9924
9925 if( better || equal )
9926 {
9927 SCIP_Real minresactivity;
9928 SCIP_Real maxresactivity;
9929 SCIP_Real newlhs;
9930 SCIP_Real newrhs;
9931 SCIP_Bool removescons;
9932 SCIP_Bool minisrelax;
9933 SCIP_Bool maxisrelax;
9934 SCIP_Bool isminsettoinfinity;
9935 SCIP_Bool ismaxsettoinfinity;
9936
9937 /* check if the constraint becomes redundant after multi-aggregation */
9940
9941 /* do not perform the multi-aggregation due to numerics, if we have huge contributions in the residual
9942 * activity
9943 */
9944 if( minisrelax || maxisrelax )
9945 continue;
9946
9947 getNewSidesAfterAggregation(scip, consdata, var, val, &newlhs, &newrhs);
9949
9950 /* check resactivities for reliability */
9951 if( removescons )
9952 {
9953 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
9955
9956 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity)
9959
9961 }
9962
9963 /* if parameter multaggrremove is set to TRUE, only aggregate when this removes constraint */
9964 if( conshdlrdata->multaggrremove && !removescons )
9965 continue;
9966
9967 /* prefer variables that make the constraints redundant */
9969 continue;
9970
9971 /* if the constraint does not become redundant, only accept the variable if it does not appear in
9972 * other constraints
9973 */
9974 if( !removescons && nlocks > maxnlocksstay )
9975 continue;
9976
9978 if( better )
9979 {
9980 bestslackpos = v;
9982 bestnlocks = nlocks;
9985 }
9986 }
9987 }
9988 }
9989
9990 /* if all coefficients and variables are integral, the right hand side must also be integral */
9991 if( coefsintegral && varsintegral && !SCIPisFeasIntegral(scip, consdata->rhs) )
9992 {
9993 SCIPdebugMsg(scip, "linear equality <%s> is integer infeasible\n", SCIPconsGetName(cons));
9995 *cutoff = TRUE;
9996 return SCIP_OKAY;
9997 }
9998
9999 supinf = 0;
10000 infinf = 0;
10001 samevar = FALSE;
10002
10003 /* check whether the the infimum and the supremum of the multi-aggregation can be get infinite */
10004 for( v = 0; v < consdata->nvars; ++v )
10005 {
10006 if( v != bestslackpos )
10007 {
10008 if( SCIPisPositive(scip, consdata->vals[v]) )
10009 {
10010 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
10011 {
10012 ++supinf;
10013 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
10014 {
10015 ++infinf;
10016 samevar = TRUE;
10017 }
10018 }
10019 else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
10020 ++infinf;
10021 }
10022 else if( SCIPisNegative(scip, consdata->vals[v]) )
10023 {
10024 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
10025 {
10026 ++supinf;
10027 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
10028 {
10029 ++infinf;
10030 samevar = TRUE;
10031 }
10032 }
10033 else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
10034 ++infinf;
10035 }
10036 }
10037 }
10038 assert(!samevar || (supinf > 0 && infinf > 0));
10039
10040 /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
10041 * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
10042 if( (samevar && (supinf > 1 || infinf > 1)) || (!samevar && supinf > 0 && infinf > 0) )
10043 {
10044 SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
10045 return SCIP_OKAY;
10046 }
10047
10048 /* if the slack variable is of integer type, and the constraint itself may take fractional values,
10049 * we cannot aggregate the variable, because the integrality condition would get lost
10050 * Similarly, if there are implicitly integral variables we cannot aggregate, since we might
10051 * loose the integrality condition for this variable.
10052 */
10053 if( bestslackpos >= 0
10055 || (coefsintegral && varsintegral && nimplvars == 0)) )
10056 {
10057 SCIP_VAR* slackvar;
10058 SCIP_Real* scalars;
10059 SCIP_Real slackcoef;
10060 SCIP_Real aggrconst;
10061 SCIP_Real newlhs;
10062 SCIP_Real newrhs;
10063 SCIP_Bool aggregated;
10064
10065 /* we found a slack variable that only occurs in at most one other constraint:
10066 * a_1*x_1 + ... + a_k*x_k + a'*s == rhs -> s == rhs - a_1/a'*x_1 - ... - a_k/a'*x_k
10067 */
10069
10070 /* do not multi aggregate binary variables */
10072 return SCIP_OKAY;
10073
10074 /* convert equality into inequality by deleting the slack variable:
10075 * x + a*s == b, l <= s <= u -> b - a*u <= x <= b - a*l
10076 */
10077 slackvar = vars[bestslackpos];
10078 slackcoef = vals[bestslackpos];
10080 aggrconst = consdata->rhs/slackcoef;
10081
10082 getNewSidesAfterAggregation(scip, consdata, slackvar, slackcoef, &newlhs, &newrhs);
10084 SCIP_CALL( chgLhs(scip, cons, newlhs) );
10085 SCIP_CALL( chgRhs(scip, cons, newrhs) );
10087
10088 /* allocate temporary memory */
10089 SCIP_CALL( SCIPallocBufferArray(scip, &scalars, consdata->nvars) );
10090
10091 /* set up the multi-aggregation */
10092 SCIPdebugMsg(scip, "linear constraint <%s>: multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(slackvar));
10093 for( v = 0; v < consdata->nvars; ++v )
10094 {
10095 scalars[v] = -consdata->vals[v]/slackcoef;
10096 SCIPdebugMsgPrint(scip, " %+.15g<%s>", scalars[v], SCIPvarGetName(vars[v]));
10097 }
10098 SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g], nlocks=%d, maxnlocks=%d, removescons=%u\n",
10099 aggrconst, SCIPvarGetName(slackvar), SCIPvarGetLbGlobal(slackvar), SCIPvarGetUbGlobal(slackvar),
10101
10102 /* perform the multi-aggregation */
10103 SCIP_CALL( SCIPmultiaggregateVar(scip, slackvar, consdata->nvars, vars, scalars, aggrconst,
10104 &infeasible, &aggregated) );
10106
10107 /* free temporary memory */
10109
10110 /* check for infeasible aggregation */
10111 if( infeasible )
10112 {
10113 SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
10114 *cutoff = TRUE;
10115 return SCIP_OKAY;
10116 }
10117
10118 (*naggrvars)++;
10119
10120 /* delete the constraint if it became redundant */
10121 if( bestremovescons )
10122 {
10123 SCIPdebugMsg(scip, "linear constraint <%s>: redundant after multi-aggregation\n", SCIPconsGetName(cons));
10124 SCIP_CALL( SCIPdelCons(scip, cons) );
10125
10126 if( !consdata->upgraded )
10127 (*ndelconss)++;
10128 }
10129 }
10130 else if( ncontvars == 1 )
10131 {
10132 SCIP_VAR* var;
10133
10135 var = vars[contvarpos];
10137
10138 if( coefsintegral && SCIPisFeasIntegral(scip, consdata->rhs) )
10139 {
10140 /* upgrade continuous variable to an implicit one, if the absolute value of the coefficient is one */
10141 if( SCIPisEQ(scip, REALABS(vals[contvarpos]), 1.0) )
10142 {
10143 /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
10144 SCIPdebugMsg(scip, "linear constraint <%s>: converting continuous variable <%s> to implicit integer variable\n",
10147 if( infeasible )
10148 {
10149 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10150 *cutoff = TRUE;
10151
10152 return SCIP_OKAY;
10153 }
10154 }
10155 /* aggregate continuous variable to an implicit one, if the absolute value of the coefficient is unequal to one */
10156 /* @todo check if the aggregation coefficient should be in some range(, which is not too big) */
10157 else if( !SCIPdoNotAggr(scip) )
10158 {
10160 SCIP_Real absval;
10162 SCIP_Bool redundant;
10163 SCIP_Bool aggregated;
10164
10165 absval = REALABS(vals[contvarpos]);
10166
10168
10169 /* create new implicit variable for aggregation */
10172
10173 /* add new variable to problem */
10175
10176#ifdef WITH_DEBUG_SOLUTION
10178 {
10179 SCIP_Real varval;
10182 }
10183#endif
10184
10185 /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
10186 SCIPdebugMsg(scip, "linear constraint <%s>: aggregating continuous variable <%s> to newly created implicit integer variable <%s>, aggregation factor = %g\n",
10188
10189 /* aggregate continuous and implicit variable */
10190 SCIP_CALL( SCIPaggregateVars(scip, var, newvar, absval, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
10191
10192 if( infeasible )
10193 {
10194 SCIPdebugMsg(scip, "infeasible aggregation of variable <%s> to implicit variable <%s>, domain is empty\n",
10196 *cutoff = TRUE;
10197
10198 /* release implicit variable */
10200
10201 return SCIP_OKAY;
10202 }
10203
10204 /* release implicit variable */
10206
10207 if( aggregated )
10208 (*naggrvars)++;
10209 else
10210 return SCIP_OKAY;
10211 }
10212
10213 /* we do not have any event on vartype changes, so we need to manually force this constraint to be presolved
10214 * again
10215 */
10216 consdata->boundstightened = 0;
10217 consdata->rangedrowpropagated = 0;
10218 consdata->presolved = FALSE;
10219 }
10220 }
10221 else if( ncontvars == 0 && nimplvars == 0 && nintvars == 1 && !coefszeroone )
10222 {
10223 SCIP_VAR* var;
10224
10225 /* this seems to help for rococo instances, but does not for rout (where all coefficients are +/- 1.0)
10226 * -> we don't convert integers into implints if the row is a 0/1-row
10227 */
10230 var = vars[intvarpos];
10232
10233 if( coefsintegral
10234 && SCIPisEQ(scip, REALABS(vals[intvarpos]), 1.0)
10235 && SCIPisFeasIntegral(scip, consdata->rhs) )
10236 {
10237 /* convert the integer variable with coefficient 1.0 into an implicit integer variable */
10238 SCIPdebugMsg(scip, "linear constraint <%s>: converting integer variable <%s> to implicit integer variable\n",
10241 if( infeasible )
10242 {
10243 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10244 *cutoff = TRUE;
10245
10246 return SCIP_OKAY;
10247 }
10248 }
10249 }
10250
10251 return SCIP_OKAY;
10252}
10253
10254/** checks if the given variables and their coefficient are equal (w.r.t. scaling factor) to the objective function */
10255static
10257 SCIP* scip, /**< SCIP data structure */
10258 SCIP_CONSDATA* consdata, /**< linear constraint data */
10259 SCIP_Real* scale, /**< pointer to store the scaling factor between the constraint and the
10260 * objective function */
10261 SCIP_Real* offset /**< pointer to store the offset of the objective function resulting by
10262 * this constraint */
10263 )
10264{
10265 SCIP_VAR** vars;
10266 SCIP_VAR* var;
10267 SCIP_Real objval;
10268 SCIP_Bool negated;
10269 int nvars;
10270 int v;
10271
10272 vars = consdata->vars;
10273 nvars = consdata->nvars;
10274
10275 assert(vars != NULL);
10276
10277 for( v = 0; v < nvars; ++v )
10278 {
10279 negated = FALSE;
10280 var = vars[v];
10281 assert(var != NULL);
10282
10283 if( SCIPvarIsNegated(var) )
10284 {
10285 negated = TRUE;
10287 assert(var != NULL);
10288 }
10289
10291
10292 /* if a variable has a zero objective coefficient the linear constraint is not a subset of the objective
10293 * function
10294 */
10295 if( SCIPisZero(scip, objval) )
10296 return FALSE;
10297 else
10298 {
10299 SCIP_Real val;
10300
10301 val = consdata->vals[v];
10302
10303 if( negated )
10304 {
10305 if( v == 0 )
10306 {
10307 /* the first variable defines the scale */
10308 (*scale) = val / -objval;
10309
10310 (*offset) += val;
10311 }
10312 else if( SCIPisEQ(scip, -objval * (*scale), val) )
10313 (*offset) += val;
10314 else
10315 return FALSE;
10316 }
10317 else if( v == 0 )
10318 {
10319 /* the first variable defines the scale */
10320 (*scale) = val / objval;
10321 }
10322 else if( !SCIPisEQ(scip, objval * (*scale), val) )
10323 return FALSE;
10324 }
10325 }
10326
10327 return TRUE;
10328}
10329
10330/** check if the linear equality constraint is equal to a subset of the objective function; if so we can remove the
10331 * objective coefficients and add an objective offset
10332 */
10333static
10335 SCIP* scip, /**< SCIP data structure */
10336 SCIP_CONS* cons, /**< linear equation constraint */
10337 SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10338 )
10339{
10340 SCIP_CONSDATA* consdata;
10341 SCIP_Real offset;
10342 SCIP_Real scale;
10343 SCIP_Bool applicable;
10344 int nobjvars;
10345 int nvars;
10346 int v;
10347
10348 assert(scip != NULL);
10349 assert(cons != NULL);
10350 assert(conshdlrdata != NULL);
10351
10352 consdata = SCIPconsGetData(cons);
10353 assert(consdata != NULL);
10354 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
10355
10356 nvars = consdata->nvars;
10357 nobjvars = SCIPgetNObjVars(scip);
10358
10359 /* check if the linear equality constraints does not have more variables than the objective function */
10360 if( nvars > nobjvars || nvars == 0 )
10361 return SCIP_OKAY;
10362
10363 /* check for allowance of algorithm */
10364 if( (nvars < nobjvars && !conshdlrdata->detectpartialobjective) ||
10365 (nvars == nobjvars && (!conshdlrdata->detectcutoffbound || !conshdlrdata->detectlowerbound)) )
10366 return SCIP_OKAY;
10367
10368 offset = consdata->rhs;
10369 scale = 1.0;
10370
10371 /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10372 applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10373
10374 if( applicable )
10375 {
10376 SCIP_VAR** vars;
10377
10378 vars = consdata->vars;
10379 assert(vars != NULL);
10380
10381 offset /= scale;
10382
10383 SCIPdebugMsg(scip, "linear equality constraint <%s> == %g (offset %g) is a subset of the objective function\n",
10384 SCIPconsGetName(cons), consdata->rhs, offset);
10385
10386 /* make equality a model constraint to ensure optimality in this direction */
10389
10390 /* set all objective coefficient to zero */
10391 for( v = 0; v < nvars; ++v )
10392 {
10393 SCIP_CALL( SCIPchgVarObj(scip, vars[v], 0.0) );
10394 }
10395
10396 /* add an objective offset */
10398 }
10399
10400 return SCIP_OKAY;
10401}
10402
10403/** updates the cutoff if the given primal bound (which is implied by the given constraint) is better */
10404static
10406 SCIP* scip, /**< SCIP data structure */
10407 SCIP_CONS* cons, /**< constraint */
10408 SCIP_Real primalbound /**< feasible primal bound */
10409 )
10410{
10411 SCIP_Real cutoffbound;
10412
10413 /* increase the cutoff bound value by an epsilon to ensue that solution with the value of the cutoff bound are still
10414 * accepted
10415 */
10416 cutoffbound = primalbound + SCIPcutoffbounddelta(scip);
10417
10418 if( cutoffbound < SCIPgetCutoffbound(scip) )
10419 {
10420 SCIPdebugMsg(scip, "update cutoff bound <%g>\n", cutoffbound);
10421
10422 SCIP_CALL( SCIPupdateCutoffbound(scip, cutoffbound) );
10423 }
10424 else
10425 {
10426 SCIP_CONSDATA* consdata;
10427
10428 consdata = SCIPconsGetData(cons);
10429 assert(consdata != NULL);
10430
10431 /* we cannot disable the enforcement and propagation on ranged rows, because the cutoffbound could only have
10432 * resulted from one side
10433 */
10434 if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
10435 {
10436 /* in case the cutoff bound is worse then the currently known one, we additionally avoid enforcement and
10437 * propagation
10438 */
10441 }
10442 }
10443
10444 return SCIP_OKAY;
10445}
10446
10447/** check if the linear constraint is parallel to objective function; if so update the cutoff bound and avoid that the
10448 * constraint enters the LP by setting the initial and separated flag to FALSE
10449 */
10450static
10452 SCIP* scip, /**< SCIP data structure */
10453 SCIP_CONS* cons, /**< linear constraint */
10454 SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10455 )
10456{
10457 SCIP_CONSDATA* consdata;
10458 SCIP_Real offset;
10459 SCIP_Real scale;
10460 SCIP_Bool applicable;
10461 int nobjvars;
10462 int nvars;
10463
10464 assert(scip != NULL);
10465 assert(cons != NULL);
10466 assert(conshdlrdata != NULL);
10467
10468 consdata = SCIPconsGetData(cons);
10469 assert(consdata != NULL);
10470
10471 /* ignore equalities since these are covered by the method checkPartialObjective() */
10472 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10473 return SCIP_OKAY;
10474
10475 nvars = consdata->nvars;
10476 nobjvars = SCIPgetNObjVars(scip);
10477
10478 /* check if the linear inequality constraints has the same number of variables as the objective function and if the
10479 * initial and/or separated flag is set to FALSE
10480 */
10481 if( nvars != nobjvars || (!SCIPconsIsInitial(cons) && !SCIPconsIsSeparated(cons)) )
10482 return SCIP_OKAY;
10483
10484 offset = 0.0;
10485 scale = 1.0;
10486
10487 /* There are no variables in the objective function and in the constraint. Thus, the constraint is redundant or proves
10488 * infeasibility. Since we have a pure feasibility problem, we do not want to set a cutoff or lower bound.
10489 */
10490 if( nobjvars == 0 )
10491 return SCIP_OKAY;
10492
10493 /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10494 applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10495
10496 if( applicable )
10497 {
10498 SCIP_Bool rhsfinite = !SCIPisInfinity(scip, consdata->rhs);
10499 SCIP_Bool lhsfinite = !SCIPisInfinity(scip, -consdata->lhs);
10500
10501 assert(scale != 0.0);
10502
10503 if( scale > 0.0 )
10504 {
10505 if( conshdlrdata->detectcutoffbound && rhsfinite )
10506 {
10507 SCIP_Real primalbound;
10508
10509 primalbound = (consdata->rhs - offset) / scale;
10510
10511 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10513
10515 }
10516
10517 if( conshdlrdata->detectlowerbound && lhsfinite )
10518 {
10519 SCIP_Real lowerbound;
10520
10521 lowerbound = (consdata->lhs - offset) / scale;
10522
10523 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10524 SCIPconsGetName(cons), lowerbound);
10525
10527 }
10528
10529 if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !lhsfinite)) ||
10530 (conshdlrdata->detectlowerbound && !rhsfinite) )
10531 {
10532 /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10535 }
10536 }
10537 else
10538 {
10539 if( conshdlrdata->detectlowerbound && rhsfinite )
10540 {
10541 SCIP_Real lowerbound;
10542
10543 lowerbound = (consdata->rhs - offset) / scale;
10544
10545 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10546 SCIPconsGetName(cons), lowerbound);
10547
10549 }
10550
10551 if( conshdlrdata->detectcutoffbound && lhsfinite )
10552 {
10553 SCIP_Real primalbound;
10554
10555 primalbound = (consdata->lhs - offset) / scale;
10556
10557 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10559
10561 }
10562
10563 if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !rhsfinite)) ||
10564 (conshdlrdata->detectlowerbound && !lhsfinite) )
10565 {
10566 /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10569 }
10570 }
10571 }
10572
10573 return SCIP_OKAY;
10574}
10575
10576/** converts special equalities */
10577static
10579 SCIP* scip, /**< SCIP data structure */
10580 SCIP_CONS* cons, /**< linear constraint */
10581 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10582 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10583 int* nfixedvars, /**< pointer to count number of fixed variables */
10584 int* naggrvars, /**< pointer to count number of aggregated variables */
10585 int* ndelconss /**< pointer to count number of deleted constraints */
10586 )
10587{
10588 SCIP_CONSDATA* consdata;
10589
10590 assert(scip != NULL);
10591 assert(cons != NULL);
10592 assert(conshdlrdata != NULL);
10593 assert(cutoff != NULL);
10594 assert(nfixedvars != NULL);
10595 assert(naggrvars != NULL);
10596 assert(ndelconss != NULL);
10597
10598 consdata = SCIPconsGetData(cons);
10599 assert(consdata != NULL);
10600 assert(consdata->removedfixings);
10601
10602 /* do nothing on inequalities */
10603 if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10604 return SCIP_OKAY;
10605
10606 /* depending on the number of variables, call a special conversion method */
10607 if( consdata->nvars == 1 )
10608 {
10609 /* fix variable */
10610 SCIP_CALL( convertUnaryEquality(scip, cons, cutoff, nfixedvars, ndelconss) );
10611 }
10612 else if( consdata->nvars == 2 )
10613 {
10614 /* aggregate one of the variables */
10615 SCIP_CALL( convertBinaryEquality(scip, cons, cutoff, naggrvars, ndelconss) );
10616 }
10617 else
10618 {
10619 /* check if the equality is part of the objective function */
10620 SCIP_CALL( checkPartialObjective(scip, cons, conshdlrdata) );
10621
10622 /* try to multi-aggregate one of the variables */
10623 SCIP_CALL( convertLongEquality(scip, conshdlrdata, cons, cutoff, naggrvars, ndelconss) );
10624 }
10625
10626 return SCIP_OKAY;
10627}
10628
10629/** returns whether the linear sum of all variables/coefficients except the given one divided by the given value is always
10630 * integral
10631 */
10632static
10634 SCIP* scip, /**< SCIP data structure */
10635 SCIP_CONSDATA* consdata, /**< linear constraint */
10636 int pos, /**< position of variable to be left out */
10637 SCIP_Real val /**< value to divide the coefficients by */
10638 )
10639{
10640 int v;
10641
10642 assert(scip != NULL);
10643 assert(consdata != NULL);
10644 assert(0 <= pos && pos < consdata->nvars);
10645
10646 for( v = 0; v < consdata->nvars; ++v )
10647 {
10648 if( v != pos && (!SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v]/val)) )
10649 return FALSE;
10650 }
10651
10652 return TRUE;
10653}
10654
10655/** 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$,
10656 * 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$
10657 */
10658static
10660 SCIP* scip, /**< SCIP data structure */
10661 SCIP_Real side, /**< lhs or rhs */
10662 SCIP_Real val, /**< coefficient */
10663 SCIP_Real minresactivity, /**< minimal residual activity */
10664 SCIP_Real maxresactivity, /**< maximal residual activity */
10665 SCIP_Real* minval, /**< pointer to store calculated minval */
10666 SCIP_Real* maxval /**< pointer to store calculated maxval */
10667 )
10668{
10669 assert(scip != NULL);
10670 assert(minval != NULL);
10671 assert(maxval != NULL);
10672
10673 if( val > 0.0 )
10674 {
10676 *minval = -maxresactivity;
10677 else
10678 *minval = (side - maxresactivity)/val;
10679
10681 *maxval = -minresactivity;
10682 else
10683 *maxval = (side - minresactivity)/val;
10684 }
10685 else
10686 {
10688 *minval = minresactivity;
10689 else
10690 *minval = (side - minresactivity)/val;
10691
10693 *maxval = maxresactivity;
10694 else
10695 *maxval = (side - maxresactivity)/val;
10696 }
10697}
10698
10699
10700/** applies dual presolving for variables that are locked only once in a direction, and this locking is due to a
10701 * linear inequality
10702 */
10703static
10705 SCIP* scip, /**< SCIP data structure */
10706 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10707 SCIP_CONS* cons, /**< linear constraint */
10708 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10709 int* nfixedvars, /**< pointer to count number of fixed variables */
10710 int* naggrvars, /**< pointer to count number of aggregated variables */
10711 int* ndelconss /**< pointer to count number of deleted constraints */
10712 )
10713{
10714 SCIP_CONSDATA* consdata;
10715 SCIP_Bool lhsexists;
10716 SCIP_Bool rhsexists;
10717 SCIP_Bool bestisint;
10718 SCIP_Bool bestislhs;
10719 SCIP_Real minabsval;
10720 SCIP_Real maxabsval;
10721 int bestpos;
10722 int i;
10723 int maxotherlocks;
10724
10725 assert(scip != NULL);
10726 assert(cons != NULL);
10727 assert(cutoff != NULL);
10728 assert(nfixedvars != NULL);
10729 assert(naggrvars != NULL);
10730 assert(ndelconss != NULL);
10731
10732 /* only process checked constraints (for which the locks are increased);
10733 * otherwise we would have to check for variables with nlocks == 0, and these are already processed by the
10734 * dualfix presolver
10735 */
10736 if( !SCIPconsIsChecked(cons) )
10737 return SCIP_OKAY;
10738
10739 consdata = SCIPconsGetData(cons);
10740 assert(consdata != NULL);
10741
10742 lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
10743 rhsexists = !SCIPisInfinity(scip, consdata->rhs);
10744
10745 /* search for a single-locked variable which can be multi-aggregated; if a valid continuous variable was found, we
10746 * can use it safely for aggregation and break the search loop
10747 */
10748 bestpos = -1;
10749 bestisint = TRUE;
10750 bestislhs = FALSE;
10751
10752 /* We only want to multi-aggregate variables, if they appear in maximal one additional constraint,
10753 * everything else would produce fill-in. Exceptions:
10754 * - If there are only two variables in the constraint from which the multi-aggregation arises, no fill-in will be
10755 * produced.
10756 * - If there are three variables in the constraint, multi-aggregation in three additional constraints will remove
10757 * six nonzeros (three from the constraint and the three entries of the multi-aggregated variable) and add
10758 * six nonzeros (two variables per substitution).
10759 * - If there at most four variables in the constraint, multi-aggregation in two additional constraints will remove
10760 * six nonzeros (four from the constraint and the two entries of the multi-aggregated variable) and add
10761 * six nonzeros (three variables per substitution). God exists!
10762 */
10763 if( consdata->nvars <= 2 )
10765 else if( consdata->nvars == 3 )
10766 maxotherlocks = 3;
10767 else if( consdata->nvars == 4 )
10768 maxotherlocks = 2;
10769 else
10770 maxotherlocks = 1;
10771
10772 /* if this constraint has both sides, it also provides a lock for the other side and thus we can allow one more lock */
10774 maxotherlocks++;
10775
10776 minabsval = SCIPinfinity(scip);
10777 maxabsval = -1.0;
10778 for( i = 0; i < consdata->nvars && bestisint; ++i )
10779 {
10780 SCIP_VAR* var;
10781 SCIP_Bool isint;
10782 SCIP_Real val;
10783 SCIP_Real absval;
10784 SCIP_Real obj;
10785 SCIP_Real lb;
10786 SCIP_Real ub;
10787 SCIP_Bool agglhs;
10788 SCIP_Bool aggrhs;
10789
10790 val = consdata->vals[i];
10791 absval = REALABS(val);
10792
10793 /* calculate minimal and maximal absolute value */
10794 if( absval < minabsval )
10795 minabsval = absval;
10796 if( absval > maxabsval )
10797 maxabsval = absval;
10798
10799 /* do not try to multi aggregate, when numerical bad */
10800 if( maxabsval / minabsval > conshdlrdata->maxdualmultaggrquot )
10801 return SCIP_OKAY;
10802
10803 var = consdata->vars[i];
10805
10806 /* if we already found a candidate, skip integers */
10807 if( bestpos >= 0 && isint )
10808 continue;
10809
10810 /* better do not multi-aggregate binary variables, since most plugins rely on their binary variables to be either
10811 * active, fixed, or single-aggregated with another binary variable
10812 */
10813 if( SCIPvarIsBinary(var) && consdata->nvars > 2 )
10814 continue;
10815
10817 continue;
10818
10819 val = consdata->vals[i];
10821 lb = SCIPvarGetLbGlobal(var);
10822 ub = SCIPvarGetUbGlobal(var);
10823
10824 /* lhs <= a_0 * x_0 + a_1 * x_1 + ... + a_{n-1} * x_{n-1} <= rhs
10825 *
10826 * a_i >= 0, c_i >= 0, lhs exists, nlocksdown(x_i) == 1:
10827 * - constraint is the only one that forbids fixing the variable to its lower bound
10828 * - 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
10829 *
10830 * a_i <= 0, c_i <= 0, lhs exists, nlocksup(x_i) == 1:
10831 * - constraint is the only one that forbids fixing the variable to its upper bound
10832 * - 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
10833 *
10834 * a_i >= 0, c_i <= 0, rhs exists, nlocksup(x_i) == 1:
10835 * - constraint is the only one that forbids fixing the variable to its upper bound
10836 * - 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
10837 *
10838 * a_i <= 0, c_i >= 0, rhs exists, nlocksdown(x_i) == 1:
10839 * - constraint is the only one that forbids fixing the variable to its lower bound
10840 * - 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
10841 *
10842 * but: all this is only applicable, if the aggregated value is inside x_i's bounds for all possible values
10843 * of all x_j
10844 * furthermore: we only want to apply this, if no fill-in will be produced
10845 */
10856 if( agglhs || aggrhs )
10857 {
10858 SCIP_Real minresactivity;
10859 SCIP_Real maxresactivity;
10860 SCIP_Real minval;
10861 SCIP_Real maxval;
10862 SCIP_Bool minisrelax;
10863 SCIP_Bool maxisrelax;
10864 SCIP_Bool isminsettoinfinity;
10865 SCIP_Bool ismaxsettoinfinity;
10866
10867 /* calculate bounds for \sum_{j \neq i} a_j * x_j */
10871
10872 /* We called consdataGetActivityResiduals() saying that we do not need a good relaxation,
10873 * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
10874 * This is needed, because we do not want to rely on relaxed finite resactivities.
10875 */
10877
10878 if( agglhs )
10879 {
10880 /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10881 calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10882
10883 assert(SCIPisLE(scip, minval, maxval));
10884 if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10885 (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10886 {
10887 SCIP_Real oldmaxresactivity;
10888 SCIP_Real oldminresactivity;
10889 SCIP_Bool recalculated;
10890
10894
10895 /* check minresactivity for reliability */
10896 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10897 {
10900 isminsettoinfinity = TRUE; /* here it means only that it was even calculated */
10901 }
10902
10903 /* check maxresactivity for reliability */
10904 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10905 {
10908 ismaxsettoinfinity = TRUE; /* here it means only that it was even calculated */
10909 }
10910
10911 /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10912 if( recalculated )
10913 {
10915
10916 /* check again if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10917 calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10918
10919 assert(SCIPisLE(scip, minval, maxval));
10920 }
10921
10922 if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10923 {
10924 /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10925 * in the multi-aggregation
10926 */
10927 if( !isint || (SCIPisIntegral(scip, consdata->lhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10928 {
10929 bestpos = i;
10930 bestisint = isint;
10931 bestislhs = TRUE;
10932 continue; /* no need to also look at the right hand side */
10933 }
10934 }
10935 }
10936 }
10937
10938 if( aggrhs )
10939 {
10940 /* check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10941 calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10942
10943 assert(SCIPisLE(scip,minval,maxval));
10944 if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10945 (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10946 {
10947 SCIP_Real oldmaxresactivity;
10948 SCIP_Real oldminresactivity;
10949 SCIP_Bool recalculated;
10950
10954
10955 /* check minresactivity for reliability */
10956 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10957 {
10960 }
10961
10962 /* check maxresactivity for reliability */
10963 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10964 {
10967 }
10968
10969 /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10970 if( recalculated )
10971 {
10972 /* check again if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10973 calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10974 assert(SCIPisLE(scip,minval,maxval));
10975 }
10976
10977 if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10978 {
10979 /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10980 * in the multi-aggregation
10981 */
10982 if( !isint || (SCIPisIntegral(scip, consdata->rhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10983 {
10984 bestpos = i;
10985 bestisint = isint;
10986 bestislhs = FALSE;
10987 }
10988 }
10989 }
10990 }
10991 }
10992 }
10993
10994 if( bestpos >= 0 )
10995 {
10997 SCIP_Real* aggrcoefs;
10998 SCIP_Real aggrconst;
11000 SCIP_Real bestval;
11001 SCIP_Real epsilon;
11002 int naggrs;
11003 int j;
11004 SCIP_Bool infeasible;
11005 SCIP_Bool aggregated;
11006 SCIP_Bool samevar;
11007 int supinf; /* counter for infinite contributions to the supremum of a possible
11008 * multi-aggregation
11009 */
11010 int infinf; /* counter for infinite contributions to the infimum of a possible
11011 * multi-aggregation
11012 */
11013
11016
11017 bestvar = consdata->vars[bestpos];
11018 bestval = consdata->vals[bestpos];
11019 assert(bestisint ==
11021
11022 /* allocate temporary memory */
11023 SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars-1) );
11024 SCIP_CALL( SCIPallocBufferArray(scip, &aggrcoefs, consdata->nvars-1) );
11025
11026 /* set up the multi-aggregation */
11028 SCIPdebugMsg(scip, "linear constraint <%s> (dual): multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(bestvar));
11029 naggrs = 0;
11030 supinf = 0;
11031 infinf = 0;
11032 samevar = FALSE;
11033 epsilon = SCIPepsilon(scip);
11034
11035 for( j = 0; j < consdata->nvars; ++j )
11036 {
11037 if( j != bestpos )
11038 {
11039 SCIP_Real absaggrcoef;
11040
11041 aggrvars[naggrs] = consdata->vars[j];
11042 aggrcoefs[naggrs] = -consdata->vals[j]/consdata->vals[bestpos];
11044
11046
11047 /* do not try to multi aggregate, when numerical bad */
11048 if( absaggrcoef < epsilon )
11049 {
11050 SCIPdebugMsg(scip, "do not perform multi-aggregation: too large aggregation coefficients\n");
11051
11052 /* free temporary memory */
11055
11056 return SCIP_OKAY;
11057 }
11058
11059 if( bestisint )
11060 {
11061 /* coefficient must be integral: round it to exact integral value */
11064 }
11065
11067 {
11068 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
11069 {
11070 ++supinf;
11071 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
11072 {
11073 ++infinf;
11074 samevar = TRUE;
11075 }
11076 }
11077 else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
11078 ++infinf;
11079 }
11080 else if( SCIPisNegative(scip, aggrcoefs[naggrs]) )
11081 {
11082 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
11083 {
11084 ++supinf;
11085 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
11086 {
11087 ++infinf;
11088 samevar = TRUE;
11089 }
11090 }
11091 else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
11092 ++infinf;
11093 }
11094
11095 naggrs++;
11096 }
11097 }
11098 assert(!samevar || (supinf > 0 && infinf > 0));
11099
11100 aggrconst = (bestislhs ? consdata->lhs/bestval : consdata->rhs/bestval);
11101 SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g]\n", aggrconst, SCIPvarGetName(bestvar),
11103 assert(naggrs == consdata->nvars-1);
11104
11105 /* right hand side must be integral: round it to exact integral value */
11106 if( bestisint )
11107 {
11110 }
11111
11112 aggregated = FALSE;
11113 infeasible = FALSE;
11114
11115 /* perform the multi-aggregation */
11116 if( (samevar && supinf == 1 && infinf == 1) || (!samevar && (supinf == 0 || infinf == 0)) )
11117 {
11118 /* @todo if multi-aggregate makes them numerical trouble, avoid them if the coefficients differ to much, see
11119 * also convertLongEquality() early termination due to coefficients
11120 */
11122
11123 /* if the multi-aggregate bestvar is integer, we need to convert implicit integers to integers because
11124 * the implicitness might rely on the constraint and the integrality of bestvar
11125 */
11126 if( !infeasible && aggregated && SCIPvarGetType(bestvar) == SCIP_VARTYPE_INTEGER )
11127 {
11128 SCIP_Bool infeasiblevartypechg;
11129
11130 for( j = 0; j < naggrs; ++j)
11131 {
11132 /* If the multi-aggregation was not infeasible, then setting implicit integers to integers should not
11133 * lead to infeasibility
11134 */
11136 {
11139 }
11140 }
11141 }
11142 }
11143 else
11144 {
11145 /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
11146 * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
11147 SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
11148 }
11149 /* free temporary memory */
11152
11153 /* check for infeasible aggregation */
11154 if( infeasible )
11155 {
11156 SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
11157 *cutoff = TRUE;
11158 return SCIP_OKAY;
11159 }
11160
11161 /* delete the constraint, if the aggregation was successful */
11162 if( aggregated )
11163 {
11164 SCIP_CALL( SCIPdelCons(scip, cons) );
11165
11166 if( !consdata->upgraded )
11167 (*ndelconss)++;
11168 (*naggrvars)++;
11169 }
11170 else
11171 {
11172 SCIPdebugMsg(scip, "aggregation non successful!\n");
11173 }
11174 }
11175
11176 return SCIP_OKAY;
11177}
11178
11179#define BINWEIGHT 1
11180#define INTWEIGHT 4
11181#define CONTWEIGHT 8
11182
11183/** gets weight for variable in a "weighted number of variables" sum */
11184static
11186 SCIP_VAR* var /**< variable to get weight for */
11187 )
11188{
11189 switch( SCIPvarGetType(var) )
11190 {
11192 return BINWEIGHT;
11195 return INTWEIGHT;
11197 return CONTWEIGHT;
11198 default:
11199 SCIPerrorMessage("invalid variable type\n");
11200 SCIPABORT();
11201 return 0; /*lint !e527*/
11202 }
11203}
11204
11205/** tries to aggregate variables in equations a^Tx = lhs
11206 * in case there are at most two binary variables with an odd coefficient and all other
11207 * variables are not continuous and have an even coefficient then:
11208 * - exactly one odd binary variables
11209 * this binary variables y can be fixed to 0 if the lhs is even and to 1 if the lhs is odd
11210 * - lhs is odd -> y = 1
11211 * - lhs is even -> y = 0
11212 * - exactly two odd binary variables
11213 * aggregate the two binary variables with odd coefficient
11214 * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11215 * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11216 */
11217static
11219 SCIP* scip, /**< SCIP data structure */
11220 SCIP_CONS* cons, /**< linear constraint */
11221 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
11222 int* nfixedvars, /**< pointer to count number of fixed variables */
11223 int* naggrvars /**< pointer to count number of aggregated variables */
11224 )
11225{ /*lint --e{715}*/
11226 SCIP_CONSDATA* consdata;
11227 SCIP_Bool success;
11228
11229 assert( scip != NULL );
11230 assert( cons != NULL );
11231
11232 consdata = SCIPconsGetData(cons);
11233 assert( consdata != NULL );
11234
11235 /* check if the linear constraint is an equation with integral right hand side */
11236 if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) || !SCIPisIntegral(scip, consdata->lhs) )
11237 return SCIP_OKAY;
11238
11239 /* try to fix and aggregated variables until nothing is possible anymore */
11240 do
11241 {
11242 int v;
11243 int nvars;
11244 SCIP_VAR** vars;
11245 SCIP_Real* vals;
11246 SCIP_Real lhs;
11247 SCIP_Bool lhsodd;
11248
11249 SCIP_Bool infeasible;
11250 SCIP_Bool fixed;
11251 SCIP_Bool aggregated;
11252 SCIP_Bool redundant;
11253
11254 SCIP_VAR* var1;
11255 SCIP_VAR* var2;
11256 int noddvars;
11257
11258 success = FALSE;
11259
11260 lhs = consdata->lhs;
11261 vars = consdata->vars;
11262 vals = consdata->vals;
11263 nvars = consdata->nvars;
11264
11265 assert( !SCIPisInfinity(scip, ABS(lhs)) );
11266
11267 var1 = NULL;
11268 var2 = NULL;
11269 noddvars = 0;
11270
11271 /* search for binary variables with an odd coefficient */
11272 for( v = 0; v < nvars && noddvars < 3; ++v )
11273 {
11274 SCIP_Longint val;
11275
11276 /* all coefficients and variables have to be integral */
11278 return SCIP_OKAY;
11279
11280 val = (SCIP_Longint)SCIPfeasFloor(scip, vals[v]);
11281 if( val % 2 != 0 )
11282 {
11283 /* the odd values have to belong to binary variables */
11284 if( !SCIPvarIsBinary(vars[v]) )
11285 return SCIP_OKAY;
11286
11287 if( noddvars == 0 )
11288 var1 = vars[v];
11289 else
11290 var2 = vars[v];
11291
11292 noddvars++;
11293 }
11294 }
11295
11296 /* check lhs is odd or even */
11297 lhsodd = (((SCIP_Longint)SCIPfeasFloor(scip, lhs)) % 2 != 0);
11298
11299 if( noddvars == 1 )
11300 {
11301 assert( var1 != NULL );
11302
11303 SCIPdebugMsg(scip, "linear constraint <%s>: try fixing variable <%s> to <%g>\n",
11304 SCIPconsGetName(cons), SCIPvarGetName(var1), lhsodd ? 1.0 : 0.0);
11305
11306 SCIP_CALL( SCIPfixVar(scip, var1, lhsodd? 1.0 : 0.0, &infeasible, &fixed) );
11307
11308 /* check for infeasibility of fixing */
11309 if( infeasible )
11310 {
11311 SCIPdebugMsg(scip, " -> infeasible fixing\n");
11312 *cutoff = TRUE;
11313 return SCIP_OKAY;
11314 }
11315
11316 if( fixed )
11317 {
11318 SCIPdebugMsg(scip, " -> feasible fixing\n");
11319 (*nfixedvars)++;
11320 success = TRUE;
11321 }
11322 }
11323 else if( noddvars == 2 )
11324 {
11325 assert( var1 != NULL );
11326 assert( var2 != NULL );
11327
11328 /* aggregate the two variables with odd coefficient
11329 * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11330 * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11331 */
11332 SCIPdebugMsg(scip, "linear constraint <%s>: try aggregation of variables <%s> and <%s>\n",
11334
11335 SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, lhsodd ? 1.0 : -1.0,
11336 lhsodd ? 1.0 : 0.0, &infeasible, &redundant, &aggregated) );
11337
11338 /* check for infeasibility of aggregation */
11339 if( infeasible )
11340 {
11341 SCIPdebugMsg(scip, " -> infeasible aggregation\n");
11342 *cutoff = TRUE;
11343 return SCIP_OKAY;
11344 }
11345
11346 /* count the aggregation */
11347 if( aggregated )
11348 {
11349 SCIPdebugMsg(scip, " -> feasible aggregation\n");
11350 (*naggrvars)++;
11351 success = TRUE;
11352 }
11353 }
11354
11355 if( success )
11356 {
11357 /* apply fixings and aggregation to successfully rerun this presolving step */
11358 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
11359
11360 if( infeasible )
11361 {
11362 SCIPdebugMsg(scip, " -> infeasible fixing\n");
11363 *cutoff = TRUE;
11364 return SCIP_OKAY;
11365 }
11366
11367 /* normalize constraint */
11368 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
11369
11370 if( infeasible )
11371 {
11372 SCIPdebugMsg(scip, " -> infeasible normalization\n");
11373 *cutoff = TRUE;
11374 return SCIP_OKAY;
11375 }
11376 }
11377 }
11378 while( success );
11379
11380 return SCIP_OKAY;
11381}
11382
11383
11384
11385/** sorting method for constraint data, compares two variables on given indices, continuous variables will be sorted to
11386 * the end and for all other variables the sortation will be in non-increasing order of their absolute value of the
11387 * coefficients
11388 */
11389static
11391{ /*lint --e{715}*/
11392 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
11395 SCIP_Real value;
11396
11397 assert(consdata != NULL);
11400
11401 vartype1 = SCIPvarGetType(consdata->vars[ind1]);
11402 vartype2 = SCIPvarGetType(consdata->vars[ind2]);
11403
11405 {
11406 /* continuous varibles will be sorted to the back */
11407 if( vartype2 != vartype1 )
11408 return +1;
11409 /* both variables are continuous */
11410 else
11411 return 0;
11412 }
11413 /* continuous variables will be sorted to the back */
11414 else if( vartype2 == SCIP_VARTYPE_CONTINUOUS )
11415 return -1;
11416
11417 value = REALABS(consdata->vals[ind2]) - REALABS(consdata->vals[ind1]);
11418
11419 /* for all non-continuous variables, the variables are sorted after decreasing absolute coefficients */
11420 return (value > 0 ? +1 : (value < 0 ? -1 : 0));
11421}
11422
11423/** tries to simplify coefficients in ranged row of the form lhs <= a^Tx <= rhs
11424 *
11425 * 1. lhs <= a^Tx <= rhs, x binary, lhs > 0, forall a_i >= lhs, a_i <= rhs, and forall pairs a_i + a_j > rhs,
11426 * then we can change this constraint to 1^Tx = 1
11427 */
11428static
11430 SCIP* scip, /**< SCIP data structure */
11431 SCIP_CONS* cons, /**< linear constraint */
11432 int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11433 int* nchgsides /**< pointer to store the amount of changed sides */
11434 )
11435{
11436 SCIP_CONSDATA* consdata;
11437 SCIP_VAR** vars;
11438 SCIP_Real* vals;
11439 SCIP_Real minval;
11440 SCIP_Real secondminval;
11441 SCIP_Real maxval;
11442 SCIP_Real lhs;
11443 SCIP_Real rhs;
11444 int nvars;
11445 int v;
11446
11447 /* we must not change a modifiable constraint in any way */
11448 if( SCIPconsIsModifiable(cons) )
11449 return SCIP_OKAY;
11450
11451 if( SCIPconsIsDeleted(cons) )
11452 return SCIP_OKAY;
11453
11454 consdata = SCIPconsGetData(cons);
11455 assert(consdata != NULL);
11456
11457 nvars = consdata->nvars;
11458
11459 /* do not check empty or bound-constraints */
11460 if( nvars < 2 )
11461 return SCIP_OKAY;
11462
11463 lhs = consdata->lhs;
11464 rhs = consdata->rhs;
11465 assert(!SCIPisInfinity(scip, -lhs));
11466 assert(!SCIPisInfinity(scip, rhs));
11467 assert(!SCIPisNegative(scip, rhs));
11468
11469 /* sides must be positive and different to detect set partition */
11470 if( !SCIPisPositive(scip, lhs) || !SCIPisLT(scip, lhs, rhs) )
11471 return SCIP_OKAY;
11472
11473 vals = consdata->vals;
11474 vars = consdata->vars;
11475 assert(vars != NULL);
11476 assert(vals != NULL);
11477
11478 minval = SCIP_INVALID;
11480 maxval = -SCIP_INVALID;
11481
11482 for( v = nvars - 1; v >= 0; --v )
11483 {
11484 if( SCIPvarIsBinary(vars[v]) )
11485 {
11486 if( minval > vals[v] || minval == SCIP_INVALID ) /*lint !e777*/
11487 {
11488 secondminval = minval;
11489 minval = vals[v];
11490 }
11491 else if( secondminval > vals[v] || secondminval == SCIP_INVALID ) /*lint !e777*/
11492 secondminval = vals[v];
11493
11494 if( maxval < vals[v] || maxval == -SCIP_INVALID ) /*lint !e777*/
11495 maxval = vals[v];
11496 }
11497 else
11498 break;
11499 }
11500
11501 /* check if all variables are binary, we can choose one, and need to choose at most one */
11502 if( v == -1 && SCIPisGE(scip, minval, lhs) && SCIPisLE(scip, maxval, rhs)
11503 && SCIPisGT(scip, minval + secondminval, rhs) )
11504 {
11505 /* change all coefficients to 1.0 */
11506 for( v = nvars - 1; v >= 0; --v )
11507 {
11508 SCIP_CALL( chgCoefPos(scip, cons, v, 1.0) );
11509 }
11510 (*nchgcoefs) += nvars;
11511
11512 /* replace old right and left hand side with 1.0 */
11513 SCIP_CALL( chgRhs(scip, cons, 1.0) );
11514 SCIP_CALL( chgLhs(scip, cons, 1.0) );
11515 (*nchgsides) += 2;
11516 }
11517
11518 return SCIP_OKAY;
11519}
11520
11521/** tries to simplify coefficients and delete variables in constraints of the form lhs <= a^Tx <= rhs
11522 *
11523 * for both-sided constraints only @see rangedRowSimplify() will be called
11524 *
11525 * for one-sided constraints there are several different coefficient reduction steps which will be applied
11526 *
11527 * 1. We try to determine parts of the constraint which will not change anything on (in-)feasibility of the constraint
11528 *
11529 * e.g. 5x1 + 5x2 + 3z1 <= 8 => 3z1 is redundant if all x are binary and -2 < 3z1 <= 3
11530 *
11531 * 2. We try to remove redundant fractional parts in a constraint
11532 *
11533 * e.g. 5.2x1 + 5.1x2 + 3x3 <= 8.3 => will be changed to 5x1 + 5x2 + 3x3 <= 8 if all x are binary
11534 *
11535 * 3. We are using the greatest common divisor for further reductions
11536 *
11537 * e.g. 10x1 + 5y2 + 5x3 + 3x4 <= 15 => will be changed to 2x1 + y2 + x3 + x4 <= 3 if all xi are binary and y2 is
11538 * integral
11539 */
11540static
11542 SCIP* scip, /**< SCIP data structure */
11543 SCIP_CONS* cons, /**< linear constraint */
11544 int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11545 int* nchgsides, /**< pointer to store the amount of changed sides */
11546 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
11547 )
11548{
11549 SCIP_CONSDATA* consdata;
11550 SCIP_VAR** vars;
11551 SCIP_Real* vals;
11552 int* perm;
11553 SCIP_Real minactsub;
11554 SCIP_Real maxactsub;
11555 SCIP_Real siderest;
11556 SCIP_Real feastol;
11557 SCIP_Real newcoef;
11558 SCIP_Real absval;
11559 SCIP_Real minact;
11560 SCIP_Real maxact;
11561 SCIP_Real side;
11562 SCIP_Real lhs;
11563 SCIP_Real rhs;
11564 SCIP_Real lb;
11565 SCIP_Real ub;
11566 SCIP_Longint restcoef;
11567 SCIP_Longint oldgcd;
11568 SCIP_Longint rest;
11569 SCIP_Longint gcd;
11570 SCIP_Bool isminsettoinfinity;
11571 SCIP_Bool ismaxsettoinfinity;
11572 SCIP_Bool isminrelax;
11573 SCIP_Bool ismaxrelax;
11574 SCIP_Bool allcoefintegral;
11575 SCIP_Bool onlybin;
11576 SCIP_Bool hasrhs;
11577 SCIP_Bool haslhs;
11578 int oldnchgcoefs;
11579 int oldnchgsides;
11580 int foundbin;
11581 int candpos;
11582 int candpos2;
11583 int offsetv;
11584 int nvars;
11585 int v;
11586 int w;
11587
11588 assert(scip != NULL);
11589 assert(cons != NULL);
11590 assert(nchgcoefs != NULL);
11591 assert(nchgsides != NULL);
11592
11593 *infeasible = FALSE;
11594
11595 /* we must not change a modifiable constraint in any way */
11596 if( SCIPconsIsModifiable(cons) )
11597 return SCIP_OKAY;
11598
11599 if( SCIPconsIsDeleted(cons) )
11600 return SCIP_OKAY;
11601
11602 consdata = SCIPconsGetData(cons);
11603 assert(consdata != NULL);
11604
11605 nvars = consdata->nvars;
11606
11607 /* do not check empty or bound-constraints */
11608 if( nvars <= 2 )
11609 return SCIP_OKAY;
11610
11611 /* update maximal activity delta if necessary */
11612 if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
11614
11615 assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
11616 assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
11617 checkMaxActivityDelta(scip, consdata);
11618
11619 /* @todo the following might be too hard, check which steps can be applied and what code must be corrected
11620 * accordingly
11621 */
11622 /* can only work with valid non-infinity activities per variable */
11623 if( SCIPisInfinity(scip, consdata->maxactdelta) )
11624 return SCIP_OKAY;
11625
11626 /* @todo: change the following: due to vartype changes, the status of the normalization can be wrong, need an event
11627 * but the eventsystem seems to be full
11628 */
11629 consdata->normalized = FALSE;
11630
11631 /* normalize constraint */
11632 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11633 assert(nvars == consdata->nvars);
11634
11635 if( *infeasible )
11636 return SCIP_OKAY;
11637
11638 if( !consdata->normalized )
11639 return SCIP_OKAY;
11640
11641 lhs = consdata->lhs;
11642 rhs = consdata->rhs;
11643 assert(!SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs));
11644 assert(!SCIPisNegative(scip, rhs));
11645
11646 if( !SCIPisInfinity(scip, -lhs) )
11647 haslhs = TRUE;
11648 else
11649 haslhs = FALSE;
11650
11651 if( !SCIPisInfinity(scip, rhs) )
11652 hasrhs = TRUE;
11653 else
11654 hasrhs = FALSE;
11655
11656 SCIPdebug( oldnchgcoefs = *nchgcoefs; )
11657 SCIPdebug( oldnchgsides = *nchgsides; )
11658
11659 /* @todo extend both-sided simplification */
11660 if( haslhs && hasrhs )
11661 {
11662 SCIP_CALL( rangedRowSimplify(scip, cons, nchgcoefs, nchgsides ) );
11663
11664 return SCIP_OKAY;
11665 }
11666 assert(haslhs != hasrhs);
11667
11668 /* if we have a normalized inequality (not ranged) the one side should be positive, @see normalizeCons() */
11669 assert(!hasrhs || !SCIPisNegative(scip, rhs));
11670 assert(!haslhs || !SCIPisNegative(scip, lhs));
11671
11672 /* get temporary memory to store the sorted permutation */
11674
11675 /* call sorting method, order continuous variables to the end and all other variables after non-increasing absolute
11676 * value of their coefficients
11677 */
11678 SCIPsort(perm, consdataCompSim, (void*)consdata, nvars);
11679
11680 /* perform sorting after permutation array */
11681 permSortConsdata(consdata, perm, nvars);
11682 consdata->indexsorted = FALSE;
11683 consdata->coefsorted = FALSE;
11684
11685 vars = consdata->vars;
11686 vals = consdata->vals;
11687 assert(vars != NULL);
11688 assert(vals != NULL);
11689 assert(consdata->validmaxabsval ? (SCIPisFeasEQ(scip, consdata->maxabsval, REALABS(vals[0])) || SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS) : TRUE);
11690
11691 /* free temporary memory */
11692 SCIPfreeBufferArray(scip, &perm);
11693
11694 /* only check constraints with at least two non continuous variables */
11696 return SCIP_OKAY;
11697
11698 /* do not process constraints when all coefficients are 1.0 */
11699 if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) && ((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs))) )
11700 return SCIP_OKAY;
11701
11702 feastol = SCIPfeastol(scip);
11703
11704 SCIPdebugMsg(scip, "starting simplification of coefficients\n");
11706
11707 /* get global activities */
11710
11711 /* cannot work with infinite activities */
11713 return SCIP_OKAY;
11714
11717 assert(maxact > minact);
11720
11721 v = 0;
11722 offsetv = -1;
11723 side = haslhs ? lhs : rhs;
11724 minactsub = minact;
11725 maxactsub = maxact;
11726
11727 /* we now determine coefficients as large as the side of the constraint to retrieve a better reduction where we
11728 * do not need to look at the large coefficients
11729 *
11730 * e.g. all x are binary, z are positive integer
11731 * c1: +5x1 + 5x2 + 3x3 + 3x4 + x5 >= 5 (x5 is redundant and does not change (in-)feasibility of this constraint)
11732 * c2: +4x1 + 4x2 + 3x3 + 3x4 + x5 >= 4 (gcd (without the coefficient of x5) after the large coefficients is 3
11733 * c3: +30x1 + 29x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 30 (gcd (without the coefficient of x2) after the large coefficients is 7
11734 *
11735 * can be changed to
11736 *
11737 * c1: +6x1 + 6x2 + 3x3 + 3x4 >= 6 (will be changed to c1: +2x1 + 2x2 + x3 + x4 >= 2)
11738 * c2: +6x1 + 6x2 + 3x3 + 3x4 + 3x5 >= 6 (will be changed to c2: +2x1 + 2x2 + x3 + x4 + x5 >= 2)
11739 * c3: +28x1 + 28x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 28 (will be changed to c3: +4x1 + 4x2 + 2x3 + 2z1 + x5 + x6 <= 4)
11740 */
11741
11742 /* if the minimal activity is negative and we found more than one variable with a coefficient bigger than the left
11743 * hand side, we cannot apply the extra reduction step and need to reset v
11744 *
11745 * 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
11746 * coefficients due to the gcd on the "small" coefficients we would get 8x1 + 8x2 - 4x3 - 4x4 >= 8 were xi = 1
11747 * for all i is a solution
11748 *
11749 * also redundancy of variables would not be correctly determined in such a case
11750 */
11751 if( nvars > 2 && SCIPisEQ(scip, vals[0], side) && !SCIPisNegative(scip, minactsub) )
11752 {
11753 v = 1;
11754
11755 while( v < nvars && SCIPisEQ(scip, side, vals[v]) )
11756 {
11757 /* if we have integer variable with "side"-coefficients but also with a lower bound greater than 0 we stop this
11758 * extra step, which might have worked
11759 */
11760 if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
11761 {
11762 v = 0;
11763 break;
11764 }
11765
11766 ++v;
11767 }
11768
11769 /* easy and quick fix: if all coefficients were equal to the side, we cannot apply further simplifications */
11770 /* todo find numerically stable normalization conditions to scale this cons to have coefficients almost equal to 1 */
11771 if( v == nvars )
11772 return SCIP_OKAY;
11773
11774 /* cannot work with continuous variables which have a big coefficient */
11775 if( v > 0 && SCIPvarGetType(vars[v - 1]) == SCIP_VARTYPE_CONTINUOUS )
11776 return SCIP_OKAY;
11777
11778 /* big negative coefficient, do not try to use the extra coefficient reduction step */
11779 if( SCIPisEQ(scip, side, -vals[v]) )
11780 v = 0;
11781
11782 /* all but one variable are processed or the next variable is continuous we cannot perform the extra coefficient
11783 * reduction
11784 */
11785 if( v == nvars - 1 || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11786 v = 0;
11787
11788 if( v > 0 )
11789 {
11790 assert(v < nvars);
11791
11792 offsetv = v - 1;
11793
11794 for( w = 0; w < v; ++w )
11795 {
11796 lb = SCIPvarGetLbGlobal(vars[w]);
11797 ub = SCIPvarGetUbGlobal(vars[w]);
11798
11799 assert(vals[w] > 0);
11800
11801 /* update residual activities */
11802 maxactsub -= ub * vals[w];
11803 minactsub -= lb * vals[w];
11805 }
11806 }
11807 }
11808
11809 /* find and remove redundant variables which do not interact with the (in-)feasibility of this constraint
11810 *
11811 * e.g. let all x are binary and y1 is continuous with bounds [-3,1] then we can reduce
11812 *
11813 * 15x1 + 15x2 + 7x3 + 3x4 + y1 <= 26
11814 * to
11815 * 15x1 + 15x2 <= 26 <=> x1 + x2 <= 1
11816 */
11817 if( nvars > 2 && SCIPisIntegral(scip, vals[v]) )
11818 {
11819 SCIP_Bool redundant = FALSE;
11820 SCIP_Bool numericsok;
11821 SCIP_Bool rredundant;
11822 SCIP_Bool lredundant;
11823
11824 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11825 assert(gcd >= 1);
11826
11827 if( v == 0 )
11828 {
11829 lb = SCIPvarGetLbGlobal(vars[0]);
11830 ub = SCIPvarGetUbGlobal(vars[0]);
11831
11832 /* update residual activities */
11833 if( vals[0] > 0 )
11834 {
11835 maxactsub -= ub * vals[0];
11836 minactsub -= lb * vals[0];
11837 }
11838 else
11839 {
11840 maxactsub -= lb * vals[0];
11841 minactsub -= ub * vals[0];
11842 }
11844 ++v;
11845 }
11846
11849
11850 /* check if some variables always fit into the given constraint */
11851 for( ; v < nvars - 1; ++v )
11852 {
11854 break;
11855
11856 if( !SCIPisIntegral(scip, vals[v]) )
11857 {
11859 break;
11860 }
11861
11862 /* calculate greatest common divisor for all general and binary variables */
11863 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11864
11865 if( gcd == 1 )
11866 break;
11867
11868 lb = SCIPvarGetLbGlobal(vars[v]);
11869 ub = SCIPvarGetUbGlobal(vars[v]);
11870
11871 assert(!SCIPisInfinity(scip, -lb));
11872 assert(!SCIPisInfinity(scip, ub));
11873
11874 /* update residual activities */
11875 if( vals[v] > 0 )
11876 {
11877 maxactsub -= ub * vals[v];
11878 minactsub -= lb * vals[v];
11879 }
11880 else
11881 {
11882 maxactsub -= lb * vals[v];
11883 minactsub -= ub * vals[v];
11884 }
11886
11887 if( hasrhs )
11888 {
11889 /* determine the remainder of the right hand side and the gcd */
11890 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11891 }
11892 else
11893 {
11894 /* determine the remainder of the left hand side and the gcd */
11895 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11896 if( SCIPisZero(scip, siderest) )
11897 siderest = gcd;
11898 }
11899
11902
11903 /* early termination if the activities deceed the gcd */
11904 if( offsetv == -1 && (rredundant || lredundant) )
11905 {
11906 redundant = TRUE;
11907 break;
11908 }
11909 }
11910 assert(v < nvars || (offsetv >= 0 && gcd > 1));
11911
11912 if( !redundant )
11913 {
11914 if( hasrhs )
11915 {
11916 /* determine the remainder of the right hand side and the gcd */
11917 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11918 }
11919 else
11920 {
11921 /* determine the remainder of the left hand side and the gcd */
11922 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11923 if( SCIPisZero(scip, siderest) )
11924 siderest = gcd;
11925 }
11926 }
11927 else
11928 ++v;
11929
11930 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",
11931 v, nvars, minactsub, maxactsub, redundant, hasrhs, siderest, gcd, offsetv);
11932
11933 /* to avoid inconsistencies due to numerics, check that the full and partial activities have
11934 * reasonable absolute values */
11937
11940
11941 /* check if we can remove redundant variables */
11942 if( v < nvars && numericsok && (redundant || (offsetv == -1 && (rredundant || lredundant))) )
11943 {
11944 SCIP_Real oldcoef;
11945
11946 /* double check the redundancy */
11947#ifndef NDEBUG
11948 SCIP_Real tmpminactsub = 0.0;
11949 SCIP_Real tmpmaxactsub = 0.0;
11950
11951 /* recompute residual activities */
11952 for( w = v; w < nvars; ++w )
11953 {
11954 lb = SCIPvarGetLbGlobal(vars[w]);
11955 ub = SCIPvarGetUbGlobal(vars[w]);
11956
11957 assert(!SCIPisInfinity(scip, -lb));
11958 assert(!SCIPisInfinity(scip, ub));
11959
11960 /* update residual activities */
11961 if( vals[w] > 0 )
11962 {
11963 tmpmaxactsub += ub * vals[w];
11964 tmpminactsub += lb * vals[w];
11965 }
11966 else
11967 {
11968 tmpmaxactsub += lb * vals[w];
11969 tmpminactsub += ub * vals[w];
11970 }
11972 }
11973
11974 if( hasrhs )
11975 {
11976 assert(offsetv == -1);
11977
11978 /* determine the remainder of the right hand side and the gcd */
11979 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11980 }
11981 else
11982 {
11983 /* determine the remainder of the left hand side and the gcd */
11984 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11985 if( SCIPisZero(scip, siderest) )
11986 siderest = gcd;
11987 }
11988
11989 /* is the redundancy really fulfilled */
11992#endif
11993
11994 SCIPdebugMsg(scip, "removing %d last variables from constraint <%s>, because they never change anything on the feasibility of this constraint\n",
11995 nvars - v, SCIPconsGetName(cons));
11996
11997 /* remove redundant variables */
11998 for( w = nvars - 1; w >= v; --w )
11999 {
12000 SCIP_CALL( delCoefPos(scip, cons, w) );
12001 }
12002 (*nchgcoefs) += (nvars - v);
12003
12004 assert(w >= 0);
12005
12006 oldcoef = vals[w];
12007
12008 /* normalize constraint */
12009 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12010 assert(vars == consdata->vars);
12011 assert(vals == consdata->vals);
12013
12014 if( *infeasible )
12015 return SCIP_OKAY;
12016
12017 /* compute new greatest common divisor due to normalization */
12018 gcd = (SCIP_Longint)(gcd / (oldcoef/vals[w]) + feastol);
12019 assert(gcd >= 1);
12020
12021 /* update side */
12022 if( hasrhs )
12023 {
12024 /* replace old with new right hand side */
12025 SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
12026 rhs = consdata->rhs;
12027 }
12028 else
12029 {
12030 if( SCIPisFeasGT(scip, oldcoef/vals[w], 1.0) )
12031 {
12032 SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
12033 lhs = consdata->lhs;
12034 }
12035 else
12036 assert(offsetv == -1 || SCIPisEQ(scip, vals[offsetv], consdata->lhs));
12037 }
12038 ++(*nchgsides);
12039
12040 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12041 assert(!haslhs || !SCIPisNegative(scip, lhs));
12042
12043 /* get new constraint data */
12044 nvars = consdata->nvars;
12045 assert(nvars > 0);
12046
12048
12049#ifndef NDEBUG
12050 /* check integrality */
12051 for( w = offsetv + 1; w < nvars; ++w )
12052 {
12053 assert(SCIPisIntegral(scip, vals[w]));
12054 }
12055#endif
12057 }
12058
12059 /* try to find a better gcd, when having large coefficients */
12060 if( offsetv >= 0 && gcd == 1 )
12061 {
12062 /* calculate greatest common divisor for all general variables */
12063 gcd = (SCIP_Longint)(REALABS(vals[nvars - 1]) + feastol);
12064
12065 if( gcd > 1 )
12066 {
12067 gcd = -1;
12068 candpos = -1;
12069
12070 for( v = nvars - 1; v > offsetv; --v )
12071 {
12072 assert(!SCIPisZero(scip, vals[v]));
12074 break;
12075
12076 if( !SCIPisIntegral(scip, vals[v]) )
12077 {
12079 break;
12080 }
12081
12082 oldgcd = gcd;
12083
12084 if( gcd == -1 )
12085 {
12086 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12087 assert(gcd >= 1);
12088 }
12089 else
12090 {
12091 /* calculate greatest common divisor for all general and binary variables */
12092 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12093 }
12094
12095 /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12096 * can stop searching
12097 */
12098 if( gcd == 1 )
12099 {
12100 if( !SCIPvarIsBinary(vars[v]) )
12101 break;
12102
12103 /* found candidate */
12104 if( candpos == -1 )
12105 {
12106 gcd = oldgcd;
12107 candpos = v;
12108 }
12109 /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12110 else
12111 break;
12112 }
12113 }
12114 assert(v > offsetv || candpos > offsetv);
12115 }
12116 else
12117 candpos = -1;
12118 }
12119 else
12120 candpos = nvars - 1;
12121
12122 /* check last coefficient for integrality */
12123 if( gcd > 1 && allcoefintegral && !redundant )
12124 {
12125 if( !SCIPisIntegral(scip, vals[nvars - 1]) )
12127 }
12128
12129 /* check for further necessary coefficient adjustments */
12130 if( offsetv >= 0 && gcd > 1 && allcoefintegral )
12131 {
12132 assert(offsetv + 1 < nvars);
12133 assert(0 <= candpos && candpos < nvars);
12134
12136 {
12137 SCIP_Bool notchangable = FALSE;
12138
12139#ifndef NDEBUG
12140 /* check integrality */
12141 for( w = offsetv + 1; w < nvars; ++w )
12142 {
12143 assert(SCIPisIntegral(scip, vals[w]));
12144 }
12145#endif
12146
12147 if( vals[candpos] > 0 && SCIPvarIsBinary(vars[candpos]) &&
12148 SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) < gcd )
12149 {
12150 /* determine the remainder of the side and the gcd */
12151 if( hasrhs )
12152 rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12153 else
12154 rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12155 assert(rest >= 0);
12156 assert(rest < gcd);
12157
12158 /* determine the remainder of the coefficient candidate and the gcd */
12159 restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12160 assert(restcoef >= 1);
12161 assert(restcoef < gcd);
12162
12163 if( hasrhs )
12164 {
12165 /* calculate new coefficient */
12166 if( restcoef > rest )
12167 newcoef = vals[candpos] - restcoef + gcd;
12168 else
12169 newcoef = vals[candpos] - restcoef;
12170 }
12171 else
12172 {
12173 /* calculate new coefficient */
12174 if( rest == 0 || restcoef < rest )
12175 newcoef = vals[candpos] - restcoef;
12176 else
12177 newcoef = vals[candpos] - restcoef + gcd;
12178 }
12179
12180 /* done */
12181
12182 /* new coeffcient must not be zero if we would loose the implication that a variable needs to be 0 if
12183 * another with the big coefficient was set to 1
12184 */
12185 if( hasrhs && SCIPisZero(scip, newcoef) )
12186 {
12188 }
12189 else if( SCIPisZero(scip, newcoef) )
12190 {
12191 /* delete old redundant coefficient */
12192 SCIP_CALL( delCoefPos(scip, cons, candpos) );
12193 ++(*nchgcoefs);
12194 }
12195 else
12196 {
12197 /* replace old with new coefficient */
12199 ++(*nchgcoefs);
12200 }
12201 }
12202 else if( vals[candpos] < 0 || !SCIPvarIsBinary(vars[candpos]) )
12203 {
12204 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol));
12205 }
12206
12207 /* correct side and big coefficients */
12208 if( (!notchangable && hasrhs && ((!SCIPisFeasIntegral(scip, rhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(rhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd))) ||
12209 ( haslhs && (!SCIPisFeasIntegral(scip, lhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(lhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd)) )
12210 {
12211 if( haslhs )
12212 {
12213 newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasCeil(scip, lhs/gcd) * gcd + feastol));
12214
12215 SCIP_CALL( chgLhs(scip, cons, newcoef) );
12216 ++(*nchgsides);
12217 }
12218 else
12219 {
12220 assert(hasrhs);
12221 newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasFloor(scip, rhs/gcd) * gcd + feastol));
12222
12223 SCIP_CALL( chgRhs(scip, cons, newcoef) );
12224 ++(*nchgsides);
12225 }
12226
12227 /* correct coefficients up front */
12228 for( w = offsetv; w >= 0; --w )
12229 {
12230 assert(vals[w] > 0);
12231
12232 SCIP_CALL( chgCoefPos(scip, cons, w, newcoef) );
12233 }
12234 (*nchgcoefs) += (offsetv + 1);
12235 }
12236
12237 if( !notchangable )
12238 {
12239 /* normalize constraint */
12240 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12241 assert(vars == consdata->vars);
12242 assert(vals == consdata->vals);
12243
12244 if( *infeasible )
12245 return SCIP_OKAY;
12246
12247 /* get new constraint data */
12248 nvars = consdata->nvars;
12249 assert(nvars >= 2);
12250
12252
12253 lhs = consdata->lhs;
12254 rhs = consdata->rhs;
12255 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12256 assert(!haslhs || !SCIPisNegative(scip, lhs));
12257 }
12258 }
12259 }
12260 }
12261
12262 /* @todo we still can remove continuous variables if they are redundant due to the non-integrality argument */
12263 /* no continuous variables are left over */
12265 return SCIP_OKAY;
12266
12267 onlybin = TRUE;
12269 /* check if all variables are of binary type */
12270 for( v = nvars - 1; v >= 0; --v )
12271 {
12272 if( !SCIPvarIsBinary(vars[v]) )
12273 onlybin = FALSE;
12274 if( !SCIPisIntegral(scip, vals[v]) )
12276 }
12277
12278 /* check if the non-integrality part of all integral variables is smaller than the non-inegrality part of the right
12279 * hand side or bigger than the left hand side respectively, so we can make all of them integral
12280 *
12281 * @todo there are some steps missing ....
12282 */
12283 if( (hasrhs && !SCIPisFeasIntegral(scip, rhs)) || (haslhs && !SCIPisFeasIntegral(scip, lhs)) )
12284 {
12285 SCIP_Real val;
12286 SCIP_Real newval;
12287 SCIP_Real frac = 0.0;
12288 SCIP_Bool found = FALSE;
12289
12290 if( hasrhs )
12291 {
12292 if( allcoefintegral )
12293 {
12294 /* replace old with new right hand side */
12295 SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12296 ++(*nchgsides);
12297 }
12298 else
12299 {
12300 siderest = rhs - SCIPfloor(scip, rhs);
12301
12302 /* try to round down all non-integral coefficients */
12303 for( v = nvars - 1; v >= 0; --v )
12304 {
12305 val = vals[v];
12306
12307 /* add up all possible fractional parts */
12308 if( !SCIPisIntegral(scip, val) )
12309 {
12310 lb = SCIPvarGetLbGlobal(vars[v]);
12311 ub = SCIPvarGetUbGlobal(vars[v]);
12312
12313 /* at least one bound need to be at zero */
12314 if( !onlybin && !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12315 return SCIP_OKAY;
12316
12317 /* swap bounds for 'standard' form */
12318 if( !SCIPisFeasZero(scip, lb) )
12319 {
12320 ub = lb;
12321 val *= -1;
12322 }
12323
12324 found = TRUE;
12325
12326 frac += (val - SCIPfloor(scip, val)) * ub;
12327
12328 /* if we exceed the fractional part of the right hand side, we cannot tighten the coefficients
12329 *
12330 * e.g. 1.1x1 + 1.1x2 + 1.4x3 + 1.02x4 <= 2.4, here we cannot floor all fractionals because
12331 * x3, x4 set to 1 would be infeasible but feasible after flooring
12332 */
12333 if( SCIPisGT(scip, frac, siderest) )
12334 return SCIP_OKAY;
12335 }
12336 }
12337 assert(v == -1);
12338
12339 SCIPdebugMsg(scip, "rounding all non-integral coefficients and the right hand side down\n");
12340
12341 /* round rhs and coefficients to integral values */
12342 if( found )
12343 {
12344 for( v = nvars - 1; v >= 0; --v )
12345 {
12346 val = vals[v];
12347
12348 /* add the whole fractional part */
12349 if( !SCIPisIntegral(scip, val) )
12350 {
12351 lb = SCIPvarGetLbGlobal(vars[v]);
12352
12353 if( SCIPisFeasZero(scip, lb) )
12354 newval = SCIPfloor(scip, val);
12355 else
12356 newval = SCIPceil(scip, val);
12357
12358 if( SCIPisZero(scip, newval) )
12359 {
12360 /* delete old redundant coefficient */
12361 SCIP_CALL( delCoefPos(scip, cons, v) );
12362 ++(*nchgcoefs);
12363 }
12364 else
12365 {
12366 /* replace old with new coefficient */
12367 SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12368 ++(*nchgcoefs);
12369 }
12370 }
12371 }
12372 }
12373
12374 /* replace old with new right hand side */
12375 SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12376 ++(*nchgsides);
12377 }
12378 }
12379 else
12380 {
12381 if( allcoefintegral )
12382 {
12383 /* replace old with new left hand side */
12384 SCIP_CALL( chgLhs(scip, cons, SCIPceil(scip, lhs)) );
12385 ++(*nchgsides);
12386 }
12387 else
12388 {
12389 /* cannot floor left hand side to zero */
12390 if( SCIPisLT(scip, lhs, 1.0) )
12391 return SCIP_OKAY;
12392
12393 siderest = lhs - SCIPfloor(scip, lhs);
12394
12395 /* try to round down all non-integral coefficients */
12396 for( v = nvars - 1; v >= 0; --v )
12397 {
12398 val = vals[v];
12399
12400 /* add up all possible fractional parts */
12401 if( !SCIPisIntegral(scip, val) )
12402 {
12403 lb = SCIPvarGetLbGlobal(vars[v]);
12404 ub = SCIPvarGetUbGlobal(vars[v]);
12405
12406 /* at least one bound need to be at zero */
12407 if( !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12408 return SCIP_OKAY;
12409
12410 /* swap bounds for 'standard' form */
12411 if( !SCIPisFeasZero(scip, lb) )
12412 {
12413 ub = lb;
12414 val *= -1;
12415 }
12416
12417 /* cannot floor to zero */
12418 if( SCIPisLT(scip, val, 1.0) )
12419 return SCIP_OKAY;
12420
12421 /* the fractional part on each variable need to exceed the fractional part on the left hand side */
12422 if( SCIPisLT(scip, val - SCIPfloor(scip, val), siderest) )
12423 return SCIP_OKAY;
12424
12425 found = TRUE;
12426
12427 frac += (val - SCIPfloor(scip, val)) * ub;
12428
12429 /* if we exceed the fractional part of the left hand side plus one by summing up all maximal
12430 * fractional parts of the variables, we cannot tighten the coefficients
12431 *
12432 * e.g. 4.3x1 + 1.3x2 + 1.3x3 + 1.6x4 >= 4.2, here we cannot floor all fractionals because
12433 * x2-x4 set to 1 would be feasible but not after flooring
12434 */
12435 if( SCIPisGE(scip, frac, 1 + siderest) )
12436 return SCIP_OKAY;
12437 }
12438 /* all coefficients need to be integral, otherwise we might do an invalid reduction */
12439 else
12440 return SCIP_OKAY;
12441 }
12442 assert(v == -1);
12443
12444 SCIPdebugMsg(scip, "rounding all non-integral coefficients and the left hand side down\n");
12445
12446 /* round lhs and coefficients to integral values */
12447 if( found )
12448 {
12449 for( v = nvars - 1; v >= 0; --v )
12450 {
12451 val = vals[v];
12452
12453 /* add the whole fractional part */
12454 if( !SCIPisIntegral(scip, val) )
12455 {
12456 lb = SCIPvarGetLbGlobal(vars[v]);
12457
12458 if( SCIPisFeasZero(scip, lb) )
12459 newval = SCIPfloor(scip, val);
12460 else
12461 newval = SCIPceil(scip, val);
12462
12463 if( SCIPisZero(scip, newval) )
12464 {
12465 /* delete old redundant coefficient */
12466 SCIP_CALL( delCoefPos(scip, cons, v) );
12467 ++(*nchgcoefs);
12468 }
12469 else
12470 {
12471 /* replace old with new coefficient */
12472 SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12473 ++(*nchgcoefs);
12474 }
12475 }
12476 }
12477 }
12478
12479 /* replace old with new left hand side */
12480 SCIP_CALL( chgLhs(scip, cons, SCIPfloor(scip, lhs)) );
12481 ++(*nchgsides);
12482 }
12483 }
12484
12485 /* normalize constraint */
12486 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12487 assert(vars == consdata->vars);
12488 assert(vals == consdata->vals);
12489
12490 if( *infeasible )
12491 return SCIP_OKAY;
12492
12493 rhs = consdata->rhs;
12494 lhs = consdata->lhs;
12495
12496 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12497 assert(!haslhs || !SCIPisNegative(scip, lhs));
12498
12500
12501 nvars = consdata->nvars;
12502 if( nvars < 2 )
12503 return SCIP_OKAY;
12504
12506#ifndef NDEBUG
12507 /* debug check if all coefficients are really integral */
12508 for( v = nvars - 1; v >= 0; --v )
12509 assert(SCIPisIntegral(scip, vals[v]));
12510#endif
12511 }
12512
12513 /* @todo following can also work on non integral coefficients, need more investigation */
12514 /* only check constraints with integral coefficients on all integral variables */
12515 if( !allcoefintegral )
12516 return SCIP_OKAY;
12517
12518 /* we want to avoid numerical troubles, therefore we do not change non-integral sides */
12519 if( (hasrhs && !SCIPisIntegral(scip, rhs)) || (haslhs && !SCIPisIntegral(scip, lhs)) )
12520 return SCIP_OKAY;
12521
12522 /* maximal absolute value of coefficients in constraint is one, so we cannot tighten it further */
12523 if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) )
12524 return SCIP_OKAY;
12525
12526 /* stop if the last coeffcients is one in absolute value and the variable is not binary */
12527 if( !SCIPvarIsBinary(vars[nvars - 1]) && SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) )
12528 return SCIP_OKAY;
12529
12530 assert(nvars >= 2);
12531
12532 /* start gcd procedure for all variables */
12533 do
12534 {
12535 SCIPdebug( oldnchgcoefs = *nchgcoefs; )
12536 SCIPdebug( oldnchgsides = *nchgsides; )
12537
12538 /* stop if we have two coeffcients which are one in absolute value */
12539 if( SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) && SCIPisEQ(scip, REALABS(vals[nvars - 2]), 1.0) )
12540 return SCIP_OKAY;
12541
12542 gcd = -1;
12543
12544 /* calculate greatest common divisor over all integer variables; note that the onlybin flag needs to be recomputed
12545 * because coefficients of non-binary variables might have changed to zero */
12546 if( !onlybin )
12547 {
12548 foundbin = -1;
12549 onlybin = TRUE;
12550
12551 for( v = nvars - 1; v >= 0; --v )
12552 {
12553 assert(!SCIPisZero(scip, vals[v]));
12555
12556 if( SCIPvarIsBinary(vars[v]) )
12557 {
12558 if( foundbin == -1 )
12559 foundbin = v;
12560 continue;
12561 }
12562 else
12563 onlybin = FALSE;
12564
12565 absval = REALABS(vals[v]);
12566 /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12567 * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12568 */
12570
12571 if( gcd == -1 )
12572 {
12573 gcd = (SCIP_Longint)(absval + feastol);
12574 assert(gcd >= 1);
12575 }
12576 else
12577 {
12578 /* calculate greatest common divisor for all general variables */
12579 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(absval + feastol));
12580 }
12581 if( gcd == 1 )
12582 break;
12583 }
12584 }
12585 else
12586 foundbin = nvars - 1;
12587
12588 /* we need at least one binary variable and a gcd greater than 1 to try to perform further coefficient changes */
12589 if( gcd == 1 || foundbin == -1)
12590 return SCIP_OKAY;
12591
12592 assert((onlybin && gcd == -1) || (!onlybin && gcd > 1));
12593
12594 candpos = -1;
12595 candpos2 = -1;
12596
12597 /* calculate greatest common divisor over all integer and binary variables and determine the candidate where we might
12598 * change the coefficient
12599 */
12600 for( v = foundbin; v >= 0; --v )
12601 {
12602 if( onlybin || SCIPvarIsBinary(vars[v]) )
12603 {
12604 absval = REALABS(vals[v]);
12605 /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12606 * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12607 */
12609
12610 oldgcd = gcd;
12611
12612 if( gcd == -1 )
12613 {
12614 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12615 assert(gcd >= 1);
12616 }
12617 else
12618 {
12619 /* calculate greatest common divisor for all general and binary variables */
12620 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12621 }
12622
12623 /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12624 * can terminate
12625 */
12626 if( gcd == 1 )
12627 {
12628 /* found candidate */
12629 if( candpos == -1 )
12630 {
12631 gcd = oldgcd;
12632 candpos = v;
12633
12634 /* if we have only binary variables and both first coefficients have a gcd of 1, both are candidates for
12635 * the coefficient change
12636 */
12637 if( onlybin && v == foundbin - 1 )
12639 }
12640 /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12641 else
12642 {
12643 if( onlybin && candpos == v + 1 && candpos2 == v + 2 )
12644 {
12645 assert(candpos2 == nvars - 1);
12646
12647 /* take new candidates */
12648 candpos = candpos2;
12649
12650 /* recalculate gcd from scratch */
12651 gcd = (SCIP_Longint)(REALABS(vals[v+1]) + feastol);
12652 assert(gcd >= 1);
12653
12654 /* calculate greatest common divisor for all general and binary variables */
12655 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12656 if( gcd == 1 )
12657 return SCIP_OKAY;
12658 }
12659 else
12660 /* cannot determine a possible coefficient for reduction */
12661 return SCIP_OKAY;
12662 }
12663 }
12664 }
12665 }
12666 assert(gcd >= 2);
12667
12668 /* we should have found one coefficient, that led to a gcd of 1, otherwise we could normalize the constraint
12669 * further
12670 */
12671 assert(candpos >= 0 && candpos < nvars);
12672
12673 /* all variables and all coefficients are integral, so the side should be too */
12674 assert((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs)));
12675
12676 /* check again, if we have a normalized inequality (not ranged) the one side should be positive,
12677 * @see normalizeCons()
12678 */
12679 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12680 assert(!haslhs || !SCIPisNegative(scip, lhs));
12681
12682 /* determine the remainder of the side and the gcd */
12683 if( hasrhs )
12684 rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12685 else
12686 rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12687 assert(rest >= 0);
12688 assert(rest < gcd);
12689
12690 /* determine the remainder of the coefficient candidate and the gcd */
12691 if( vals[candpos] < 0 )
12692 {
12693 restcoef = ((SCIP_Longint)(vals[candpos] - feastol)) % gcd;
12694 assert(restcoef <= -1);
12695 restcoef += gcd;
12696 }
12697 else
12698 restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12699 assert(restcoef >= 1);
12700 assert(restcoef < gcd);
12701
12702 if( hasrhs )
12703 {
12704 if( rest > 0 )
12705 {
12706 /* replace old with new right hand side */
12707 SCIP_CALL( chgRhs(scip, cons, rhs - rest) );
12708 ++(*nchgsides);
12709 }
12710
12711 /* calculate new coefficient */
12712 if( restcoef > rest )
12713 newcoef = vals[candpos] - restcoef + gcd;
12714 else
12715 newcoef = vals[candpos] - restcoef;
12716 }
12717 else
12718 {
12719 if( rest > 0 )
12720 {
12721 /* replace old with new left hand side */
12722 SCIP_CALL( chgLhs(scip, cons, lhs - rest + gcd) );
12723 ++(*nchgsides);
12724 }
12725
12726 /* calculate new coefficient */
12727 if( rest == 0 || restcoef < rest )
12728 newcoef = vals[candpos] - restcoef;
12729 else
12730 newcoef = vals[candpos] - restcoef + gcd;
12731 }
12732 assert(SCIPisZero(scip, newcoef) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(newcoef) + feastol)) == gcd);
12733
12734 SCIPdebugMsg(scip, "gcd = %" SCIP_LONGINT_FORMAT ", rest = %" SCIP_LONGINT_FORMAT ", restcoef = %" SCIP_LONGINT_FORMAT "; changing coef of variable <%s> to %g and %s by %" SCIP_LONGINT_FORMAT "\n", gcd, rest, restcoef, SCIPvarGetName(vars[candpos]), newcoef, hasrhs ? "reduced rhs" : "increased lhs", hasrhs ? rest : (rest > 0 ? gcd - rest : 0));
12735
12736 if( SCIPisZero(scip, newcoef) )
12737 {
12738 /* delete redundant coefficient */
12739 SCIP_CALL( delCoefPos(scip, cons, candpos) );
12740 }
12741 else
12742 {
12743 /* replace old with new coefficient */
12745 }
12746 ++(*nchgcoefs);
12747
12748 /* now constraint can be normalized, might be directly done by dividing it by the gcd */
12749 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12750 assert(vars == consdata->vars);
12751 assert(vals == consdata->vals);
12752
12753 if( *infeasible )
12754 return SCIP_OKAY;
12755
12757
12758 rhs = consdata->rhs;
12759 lhs = consdata->lhs;
12760 assert(!hasrhs || !SCIPisNegative(scip, rhs));
12761 assert(!haslhs || !SCIPisNegative(scip, lhs));
12762
12763 nvars = consdata->nvars;
12764
12765 SCIPdebugMsg(scip, "we did %d coefficient changes and %d side changes on constraint %s when applying one round of the gcd algorithm\n", *nchgcoefs - oldnchgcoefs, *nchgsides - oldnchgsides, SCIPconsGetName(cons));
12766 }
12767 while( nvars >= 2 );
12768
12769 return SCIP_OKAY;
12770}
12771
12772
12773/** tries to aggregate an (in)equality and an equality in order to decrease the number of variables in the (in)equality:
12774 * cons0 := a * cons0 + b * cons1,
12775 * where a = val1[v] and b = -val0[v] for common variable v which removes most variable weight;
12776 * for numerical stability, we will only accept integral a and b;
12777 * the variable weight is a weighted sum over all included variables, where each binary variable weighs BINWEIGHT,
12778 * each integer or implicit integer variable weighs INTWEIGHT and each continuous variable weighs CONTWEIGHT
12779 */
12780static
12782 SCIP* scip, /**< SCIP data structure */
12783 SCIP_CONS* cons0, /**< (in)equality to modify */
12784 SCIP_CONS* cons1, /**< equality to use for aggregation of cons0 */
12785 int* commonidx0, /**< array with indices of variables in cons0, that appear also in cons1 */
12786 int* commonidx1, /**< array with indices of variables in cons1, that appear also in cons0 */
12787 int* diffidx0minus1, /**< array with indices of variables in cons0, that don't appear in cons1 */
12788 int* diffidx1minus0, /**< array with indices of variables in cons1, that don't appear in cons0 */
12789 int nvarscommon, /**< number of variables, that appear in both constraints */
12790 int commonidxweight, /**< variable weight sum of common variables */
12791 int diffidx0minus1weight, /**< variable weight sum of variables in cons0, that don't appear in cons1 */
12792 int diffidx1minus0weight, /**< variable weight sum of variables in cons1, that don't appear in cons0 */
12793 SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
12794 int* nchgcoefs, /**< pointer to count the number of changed coefficients */
12795 SCIP_Bool* aggregated, /**< pointer to store whether an aggregation was made */
12796 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
12797 )
12798{
12801 SCIP_Real a;
12802 SCIP_Real b;
12803 SCIP_Real aggrcoef;
12804 SCIP_Real scalarsum;
12805 SCIP_Real bestscalarsum;
12806 SCIP_Bool betterscalarsum;
12807 SCIP_Bool commonvarlindependent; /* indicates whether coefficient vector of common variables in linearly dependent */
12808 int varweight;
12809 int nvars;
12810 int bestvarweight;
12811 int bestnvars;
12812 int bestv;
12813 int v;
12814 int i;
12815
12816 assert(scip != NULL);
12817 assert(cons0 != NULL);
12818 assert(cons1 != NULL);
12823 assert(nvarscommon >= 1);
12825 assert(nchgcoefs != NULL);
12827
12830
12831 *infeasible = FALSE;
12832
12833 SCIPdebugMsg(scip, "try aggregation of <%s> and <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
12834
12835 /* cons0 is an (in)equality */
12837 assert(consdata0 != NULL);
12838 assert(consdata0->nvars >= 1);
12839 assert(SCIPisLE(scip, consdata0->lhs, consdata0->rhs));
12841
12842 /* cons1 is an equality */
12844 assert(consdata1 != NULL);
12845 assert(consdata1->nvars >= 1);
12846 assert(SCIPisEQ(scip, consdata1->lhs, consdata1->rhs));
12848
12849 *aggregated = FALSE;
12850
12851 /* search for the best common variable such that
12852 * val1[var] * consdata0 - val0[var] * consdata1
12853 * has least weighted number of variables
12854 */
12856 bestnvars = consdata0->nvars;
12857 bestv = -1;
12858 bestscalarsum = 0.0;
12860 for( v = 0; v < nvarscommon; ++v )
12861 {
12862 assert(consdata0->vars[commonidx0[v]] == consdata1->vars[commonidx1[v]]);
12863 a = consdata1->vals[commonidx1[v]];
12864 b = -consdata0->vals[commonidx0[v]];
12865
12866 /* only try aggregation, if coefficients are integral (numerical stability) */
12868 {
12869 /* count the number of variables in the potential new constraint a * consdata0 + b * consdata1 */
12871 nvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12872 scalarsum = REALABS(a) + REALABS(b);
12874 for( i = 0; i < nvarscommon
12876 {
12877 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12878 if( !SCIPisZero(scip, aggrcoef) )
12879 {
12881 nvars++;
12882 }
12883 }
12885 {
12886 bestv = v;
12888 bestnvars = nvars;
12890 }
12891 }
12892
12893 /* update commonvarlindependent flag, if still TRUE:
12894 * v's common coefficient in cons1 / v's common coefficient in cons0 should be constant, i.e., equal 0's common coefficient in cons1 / 0's common coefficient in cons0
12895 */
12896 if( commonvarlindependent && v > 0 )
12898 consdata1->vals[commonidx1[v]] * consdata0->vals[commonidx0[0]],
12899 consdata1->vals[commonidx1[0]] * consdata0->vals[commonidx0[v]]);
12900 }
12901
12902 /* if better aggregation was found, create new constraint and delete old one */
12904 {
12907 SCIP_VAR** newvars;
12908 SCIP_Real* newvals;
12909 SCIP_Real newlhs;
12910 SCIP_Real newrhs;
12911 int newnvars;
12912
12913 if( bestv != -1 )
12914 {
12915 /* choose multipliers such that the multiplier for the (in)equality cons0 is positive */
12916 if( consdata1->vals[commonidx1[bestv]] > 0.0 )
12917 {
12918 a = consdata1->vals[commonidx1[bestv]];
12919 b = -consdata0->vals[commonidx0[bestv]];
12920 }
12921 else
12922 {
12923 a = -consdata1->vals[commonidx1[bestv]];
12924 b = consdata0->vals[commonidx0[bestv]];
12925 }
12929 assert(!SCIPisZero(scip, b));
12930 }
12931 else
12932 {
12934 if( consdata1->vals[commonidx1[0]] > 0.0 )
12935 {
12936 a = consdata1->vals[commonidx1[0]];
12937 b = -consdata0->vals[commonidx0[0]];
12938 }
12939 else
12940 {
12941 a = -consdata1->vals[commonidx1[0]];
12942 b = consdata0->vals[commonidx0[0]];
12943 }
12945 assert(!SCIPisZero(scip, b));
12946
12947 /* if a/b is integral, then we can easily choose integer multipliers */
12948 if( SCIPisIntegral(scip, a/b) )
12949 {
12950 if( a/b > 0 )
12951 {
12952 a /= b;
12953 b = 1.0;
12954 }
12955 else
12956 {
12957 a /= -b;
12958 b = -1.0;
12959 }
12960 }
12961
12962 /* setup best* variables that were not setup above because we are in the commonvarlindependent case */
12964 bestnvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12965 }
12966
12967 SCIPdebugMsg(scip, "aggregate linear constraints <%s> := %.15g*<%s> + %.15g*<%s> -> nvars: %d -> %d, weight: %d -> %d\n",
12972
12973 /* get temporary memory for creating the new linear constraint */
12976
12977 /* calculate the common coefficients, if we have not recognized linear dependency */
12978 newnvars = 0;
12980 {
12981 for( i = 0; i < nvarscommon; ++i )
12982 {
12983 assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12984 assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12985
12986 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12987 if( !SCIPisZero(scip, aggrcoef) )
12988 {
12990 newvars[newnvars] = consdata0->vars[commonidx0[i]];
12992 newnvars++;
12993 }
12994 }
12995 }
12996 else
12997 {
12998 /* if we recognized linear dependency of the common coefficients, then the aggregation coefficient should be 0.0 for every common variable */
12999#ifndef NDEBUG
13000 for( i = 0; i < nvarscommon; ++i )
13001 {
13002 assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
13003 assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
13004
13005 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
13007 }
13008#endif
13009 }
13010
13011 /* calculate the coefficients appearing in cons0 but not in cons1 */
13012 for( i = 0; i < consdata0->nvars - nvarscommon; ++i )
13013 {
13014 assert(0 <= diffidx0minus1[i] && diffidx0minus1[i] < consdata0->nvars);
13015
13016 aggrcoef = a * consdata0->vals[diffidx0minus1[i]];
13019 newvars[newnvars] = consdata0->vars[diffidx0minus1[i]];
13021 newnvars++;
13022 }
13023
13024 /* calculate the coefficients appearing in cons1 but not in cons0 */
13025 for( i = 0; i < consdata1->nvars - nvarscommon; ++i )
13026 {
13027 assert(0 <= diffidx1minus0[i] && diffidx1minus0[i] < consdata1->nvars);
13028
13029 aggrcoef = b * consdata1->vals[diffidx1minus0[i]];
13032 newvars[newnvars] = consdata1->vars[diffidx1minus0[i]];
13034 newnvars++;
13035 }
13037
13038 /* calculate the new left and right hand side of the (in)equality */
13041 if( SCIPisInfinity(scip, -consdata0->lhs) )
13043 else
13044 newlhs = a * consdata0->lhs + b * consdata1->lhs;
13045 if( SCIPisInfinity(scip, consdata0->rhs) )
13047 else
13048 newrhs = a * consdata0->rhs + b * consdata1->rhs;
13049
13050 /* create the new linear constraint */
13056
13059
13060 /* copy the upgraded flag from the old cons0 to the new constraint */
13061 newconsdata->upgraded = consdata0->upgraded;
13062
13063 /* normalize the new constraint */
13064 SCIP_CALL( normalizeCons(scip, newcons, infeasible) );
13065
13066 if( *infeasible )
13067 goto TERMINATE;
13068
13069 /* check, if we really want to use the new constraint instead of the old one:
13070 * use the new one, if the maximum norm doesn't grow too much
13071 */
13073 {
13074 SCIPdebugMsg(scip, " -> aggregated to <%s>\n", SCIPconsGetName(newcons));
13076
13077 /* update the statistics: we changed all coefficients */
13078 if( !consdata0->upgraded )
13079 (*nchgcoefs) += consdata0->nvars + consdata1->nvars - nvarscommon;
13080 *aggregated = TRUE;
13081
13082 /* delete the old constraint, and add the new linear constraint to the problem */
13085 }
13086
13087 TERMINATE:
13088 /* release the new constraint */
13090
13091 /* free temporary memory */
13093 SCIPfreeBufferArray(scip, &newvars);
13094 }
13095
13096 return SCIP_OKAY;
13097}
13098
13099/** gets the key of the given element */
13100static
13102{ /*lint --e{715}*/
13103 /* the key is the element itself */
13104 return elem;
13105}
13106
13107/** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables and the
13108 * coefficients are either equal or negated
13109 */
13110static
13112{
13113 SCIP* scip;
13116 SCIP_Real cons1scale;
13117 SCIP_Real cons2scale;
13118 int i;
13119
13120 assert(key1 != NULL);
13121 assert(key2 != NULL);
13124 assert(consdata1->indexsorted);
13125 assert(consdata2->indexsorted);
13126
13127 scip = (SCIP*)userptr;
13128 assert(scip != NULL);
13129
13130 /* if it is the same constraint we dont need to check anything */
13131 if( key1 == key2 )
13132 return TRUE;
13133
13134 /* checks trivial case */
13135 if( consdata1->nvars != consdata2->nvars )
13136 return FALSE;
13137
13138 /* tests if variables are equal */
13139 for( i = 0; i < consdata1->nvars; ++i )
13140 {
13141 if( consdata1->vars[i] != consdata2->vars[i] )
13142 {
13143 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
13144 SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
13145 return FALSE;
13146 }
13147 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
13148 }
13149
13150 /* compute scale before comparing coefficients of constraints */
13151 cons1scale = COPYSIGN(1.0/consdata1->maxabsval, consdata1->vals[0]);
13152 cons2scale = COPYSIGN(1.0/consdata2->maxabsval, consdata2->vals[0]);
13153
13154 /* tests if coefficients are equal with the computed scale */
13155 for( i = 0; i < consdata1->nvars; ++i )
13156 {
13157 SCIP_Real val1;
13158 SCIP_Real val2;
13159
13160 val1 = consdata1->vals[i] * cons1scale;
13161 val2 = consdata2->vals[i] * cons2scale;
13162
13163 if( !SCIPisEQ(scip, val1, val2) )
13164 return FALSE;
13165 }
13166
13167 return TRUE;
13168}
13169
13170/** returns the hash value of the key */
13171static
13173{
13174 SCIP_CONSDATA* consdata;
13175 int minidx;
13176 int mididx;
13177 int maxidx;
13178 SCIP_Real scale;
13179#ifndef NDEBUG
13180 SCIP* scip;
13181
13182 scip = (SCIP*)userptr;
13183 assert(scip != NULL);
13184#endif
13185
13186 assert(key != NULL);
13187 consdata = SCIPconsGetData((SCIP_CONS*)key);
13188 assert(consdata != NULL);
13189 assert(consdata->nvars > 0);
13190
13191 assert(consdata->indexsorted);
13192
13193 minidx = SCIPvarGetIndex(consdata->vars[0]);
13194 mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
13195 maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
13196 scale = COPYSIGN(1.0/consdata->maxabsval, consdata->vals[0]);
13197
13198 /* using only the variable indices as hash, since the values are compared by epsilon */
13199 return SCIPhashSeven(consdata->nvars, minidx, SCIPrealHashCode(consdata->vals[0] * scale),
13200 mididx, SCIPrealHashCode(consdata->vals[consdata->nvars / 2] * scale),
13201 maxidx, SCIPrealHashCode(consdata->vals[consdata->nvars - 1] * scale));
13202}
13203
13204/** returns the key for deciding which of two parallel constraints should be kept (smaller key should be kept);
13205 * prefers non-upgraded constraints and as second criterion the constraint with the smallest position
13206 */
13207static
13209 SCIP_CONS* cons /**< linear constraint */
13210 )
13211{
13212 SCIP_CONSDATA* consdata;
13213
13214 assert(cons != NULL);
13215
13216 consdata = SCIPconsGetData(cons);
13217 assert(consdata != NULL);
13218
13219 return (((unsigned int)consdata->upgraded)<<31) + (unsigned int)SCIPconsGetPos(cons); /*lint !e571*/
13220}
13221
13222/** updates the hashtable such that out of all constraints in the hashtable that are detected
13223 * to be parallel to *querycons, only one is kept in the hashtable and stored into *querycons,
13224 * and all others are removed from the hashtable and stored in the given array
13225 */
13226static
13228 SCIP_HASHTABLE* hashtable, /**< hashtable containing linear constraints */
13229 SCIP_CONS** querycons, /**< pointer to linear constraint used to look for duplicates in the hash table;
13230 * upon return will contain the constraint that should be kept */
13231 SCIP_CONS** parallelconss, /**< array to return constraints that are parallel to the given;
13232 * these constraints where removed from the hashtable */
13233 int* nparallelconss /**< pointer to return number of parallel constraints */
13234 )
13235{
13237 unsigned int querykey;
13238
13239 *nparallelconss = 0;
13241
13242 while( (parallelcons = (SCIP_CONS*)SCIPhashtableRetrieve(hashtable, (void*)(*querycons))) != NULL )
13243 {
13244 unsigned int conskey = getParallelConsKey(parallelcons);
13245
13246 if( conskey < querykey )
13247 {
13248 parallelconss[(*nparallelconss)++] = *querycons;
13250 querykey = conskey;
13251 }
13252 else
13253 {
13254 parallelconss[(*nparallelconss)++] = parallelcons;
13255 }
13256
13257 /* if the constraint that just came out of the hash table is the one that is kept,
13258 * we do not need to look into the hashtable again, since the invariant is that
13259 * in the hashtable only pair-wise non-parallel constraints are contained.
13260 * For the original querycons, however, multiple constraints that compare equal (=parallel)
13261 * could be contained due to non-transitivity of the equality comparison.
13262 * Also we can return immediately, since parallelcons is already contained in the
13263 * hashtable and we do not need to remove and reinsert it.
13264 */
13265 if( *querycons == parallelcons )
13266 return SCIP_OKAY;
13267
13268 /* remove parallelcons from the hashtable, since it will be replaced by querycons */
13269 SCIP_CALL( SCIPhashtableRemove(hashtable, (void*) parallelcons) );
13270 }
13271
13272 /* in debug mode we make sure, that the hashtable cannot contain a constraint that
13273 * comnpares equal to querycons at this point
13274 */
13275#ifndef NDEBUG
13277#else
13278 SCIP_CALL( SCIPhashtableInsert(hashtable, *querycons) );
13279#endif
13280
13281 return SCIP_OKAY;
13282}
13283
13284/** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
13285 * accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
13286 */
13287static
13289 SCIP* scip, /**< SCIP data structure */
13290 BMS_BLKMEM* blkmem, /**< block memory */
13291 SCIP_CONS** conss, /**< constraint set */
13292 int nconss, /**< number of constraints in constraint set */
13293 int* firstchange, /**< pointer to store first changed constraint */
13294 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13295 int* ndelconss, /**< pointer to count number of deleted constraints */
13296 int* nchgsides /**< pointer to count number of changed left/right hand sides */
13297 )
13298{
13299 SCIP_HASHTABLE* hashtable;
13301 int nparallelconss;
13302 int hashtablesize;
13303 int c;
13304
13305 assert(scip != NULL);
13306 assert(blkmem != NULL);
13307 assert(conss != NULL);
13309 assert(cutoff != NULL);
13310 assert(ndelconss != NULL);
13311 assert(nchgsides != NULL);
13312
13313 /* create a hash table for the constraint set */
13314 hashtablesize = nconss;
13315 SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
13317
13319
13320 /* check all constraints in the given set for redundancy */
13321 for( c = 0; c < nconss; ++c )
13322 {
13325
13326 cons0 = conss[c];
13327
13329 continue;
13330
13331 /* do not check for parallel constraints if they should not be upgraded */
13333 continue;
13334
13335 /* check for interuption */
13336 if( c % 1000 == 0 && SCIPisStopped(scip) )
13337 break;
13338
13339 /* sorts the constraint */
13341 assert(consdata0 != NULL);
13343 assert(consdata0->indexsorted);
13344
13345 /* get constraints from current hash table with same variables as cons0 and with coefficients equal
13346 * to the ones of cons0 when both are scaled such that maxabsval is 1.0 and the coefficient of the
13347 * first variable is positive
13348 * Also inserts cons0 into the hashtable.
13349 */
13351
13352 if( nparallelconss != 0 )
13353 {
13354 SCIP_Real lhs;
13355 SCIP_Real rhs;
13356
13357 int i;
13358
13359 /* cons0 may have been changed in retrieveParallelConstraints() */
13361
13362 lhs = consdata0->lhs;
13363 rhs = consdata0->rhs;
13364
13365 for( i = 0; i < nparallelconss; ++i )
13366 {
13369 SCIP_Real scale;
13370
13373
13374 /* do not delete constraint if it should not be upgraded */
13376 continue;
13377
13380
13381 /* constraint found: create a new constraint with same coefficients and best left and right hand side;
13382 * delete old constraints afterwards
13383 */
13385 assert(consdata0->nvars >= 1 && consdata0->nvars == consdatadel->nvars);
13386
13387 assert(consdatadel->indexsorted);
13388 assert(consdata0->vars[0] == consdatadel->vars[0]);
13389
13390 scale = consdata0->vals[0] / consdatadel->vals[0];
13391 assert(scale != 0.0);
13392
13393 /* in debug mode, check that all coefficients are equal with respect to epsilon
13394 * if the constraints are in equilibrium scale
13395 */
13396#ifndef NDEBUG
13397 {
13398 int k;
13399 SCIP_Real scale0 = 1.0 / consdata0->maxabsval;
13400 SCIP_Real scaledel = COPYSIGN(1.0 / consdatadel->maxabsval, scale);
13401
13402 for( k = 0; k < consdata0->nvars; ++k )
13403 {
13404 assert(SCIPisEQ(scip, scale0 * consdata0->vals[k], scaledel * consdatadel->vals[k]));
13405 }
13406 }
13407#endif
13408
13409 if( scale > 0.0 )
13410 {
13411 /* the coefficients of both constraints are parallel with a positive scale */
13412 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with equal coefficients into single ranged row\n",
13416
13417 if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13418 lhs = MAX(scale * consdatadel->lhs, lhs);
13419
13420 if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13421 rhs = MIN(scale * consdatadel->rhs, rhs);
13422 }
13423 else
13424 {
13425 /* the coefficients of both rows are negations */
13426 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with negated coefficients into single ranged row\n",
13430
13431 if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13432 lhs = MAX(scale * consdatadel->rhs, lhs);
13433
13434 if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13435 rhs = MIN(scale * consdatadel->lhs, rhs);
13436 }
13437
13438 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13440
13441 /* delete consdel */
13442 assert( ! consdata0->upgraded || consdatadel->upgraded );
13444 if( !consdatadel->upgraded )
13445 (*ndelconss)++;
13446 }
13447
13448 if( SCIPisFeasLT(scip, rhs, lhs) )
13449 {
13450 SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13451 *cutoff = TRUE;
13452 break;
13453 }
13454
13455 /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
13456 if( lhs > rhs )
13457 {
13458 rhs = (lhs + rhs)/2;
13459 lhs = rhs;
13460 }
13461
13462 /* update lhs and rhs of cons0 */
13463 SCIP_CALL( chgLhs(scip, cons0, lhs) );
13464 SCIP_CALL( chgRhs(scip, cons0, rhs) );
13465
13466 /* update the first changed constraint to begin the next aggregation round with */
13467 if( consdata0->changed && SCIPconsGetPos(cons0) < *firstchange )
13469
13471 }
13472 }
13473#ifdef SCIP_MORE_DEBUG
13474 SCIPinfoMessage(scip, NULL, "linear pairwise comparison hashtable statistics:\n");
13476#endif
13477
13479
13480 /* free hash table */
13481 SCIPhashtableFree(&hashtable);
13482
13483 return SCIP_OKAY;
13484}
13485
13486/** compares constraint with all prior constraints for possible redundancy or aggregation,
13487 * and removes or changes constraint accordingly
13488 */
13489static
13491 SCIP* scip, /**< SCIP data structure */
13492 SCIP_CONS** conss, /**< constraint set */
13493 int firstchange, /**< first constraint that changed since last pair preprocessing round */
13494 int chkind, /**< index of constraint to check against all prior indices upto startind */
13495 SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
13496 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13497 int* ndelconss, /**< pointer to count number of deleted constraints */
13498 int* nchgsides, /**< pointer to count number of changed left/right hand sides */
13499 int* nchgcoefs /**< pointer to count number of changed coefficients */
13500 )
13501{
13504 int* commonidx0;
13505 int* commonidx1;
13506 int* diffidx0minus1;
13507 int* diffidx1minus0;
13508 uint64_t possignature0;
13509 uint64_t negsignature0;
13510 SCIP_Bool cons0changed;
13511 SCIP_Bool cons0isequality;
13513 int c;
13514 SCIP_Real cons0lhs;
13515 SCIP_Real cons0rhs;
13516 SCIP_Bool cons0upgraded;
13517
13518 assert(scip != NULL);
13519 assert(conss != NULL);
13521 assert(cutoff != NULL);
13522 assert(ndelconss != NULL);
13523 assert(nchgsides != NULL);
13524 assert(nchgcoefs != NULL);
13525
13526 /* get the constraint to be checked against all prior constraints */
13527 cons0 = conss[chkind];
13528 assert(cons0 != NULL);
13531
13533 assert(consdata0 != NULL);
13534 assert(consdata0->nvars >= 1);
13536
13537 /* sort the constraint */
13539
13540 /* calculate bit signatures of cons0 for potentially positive and negative coefficients */
13542 possignature0 = consdata0->possignature;
13543 negsignature0 = consdata0->negsignature;
13544
13545 /* get temporary memory for indices of common variables */
13551
13552 cons0lhs = consdata0->lhs;
13553 cons0rhs = consdata0->rhs;
13554 cons0upgraded = consdata0->upgraded;
13555
13556 /* check constraint against all prior constraints */
13557 cons0changed = consdata0->changed;
13558 consdata0->changed = FALSE;
13559 for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && conss[chkind] != NULL; ++c )
13560 {
13563 uint64_t possignature1;
13564 uint64_t negsignature1;
13565 SCIP_Bool cons0dominateslhs;
13566 SCIP_Bool cons1dominateslhs;
13567 SCIP_Bool cons0dominatesrhs;
13568 SCIP_Bool cons1dominatesrhs;
13569 SCIP_Bool cons1isequality;
13570 SCIP_Bool coefsequal;
13571 SCIP_Bool coefsnegated;
13572 SCIP_Bool tryaggregation;
13573 int nvarscommon;
13574 int nvars0minus1;
13575 int nvars1minus0;
13576 int commonidxweight;
13579 int v0;
13580 int v1;
13581
13582 assert(cons0lhs == consdata0->lhs); /*lint !e777*/
13583 assert(cons0rhs == consdata0->rhs); /*lint !e777*/
13584 assert(cons0upgraded == consdata0->upgraded);
13585
13586 cons1 = conss[c];
13587
13588 /* cons1 has become inactive during presolving of constraint pairs */
13589 if( cons1 == NULL )
13590 continue;
13591
13594
13596 assert(consdata1 != NULL);
13597
13598 /* SCIPdebugMsg(scip, "preprocess linear constraint pair <%s>[chgd:%d, upgd:%d] and <%s>[chgd:%d, upgd:%d]\n",
13599 SCIPconsGetName(cons0), cons0changed, cons0upgraded,
13600 SCIPconsGetName(cons1), consdata1->changed, consdata1->upgraded); */
13601
13602 /* if both constraints didn't change since last pair processing, we can ignore the pair */
13603 if( !cons0changed && !consdata1->changed )
13604 continue;
13605
13606 /* if both constraints are already upgraded, skip the pair;
13607 * because changes on these constraints cannot be applied to the instance anymore */
13608 if( cons0upgraded && consdata1->upgraded )
13609 continue;
13610
13611 assert(consdata1->nvars >= 1);
13612
13613 /* sort the constraint */
13615
13616 /* calculate bit signatures of cons1 for potentially positive and negative coefficients */
13618 possignature1 = consdata1->possignature;
13619 negsignature1 = consdata1->negsignature;
13620
13621 /* the signatures give a quick test to check for domination and equality of coefficients */
13625 && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13626 && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13628 && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13629 && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13631 && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13632 && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13634 && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13635 && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13637 tryaggregation = (cons0isequality || cons1isequality) && (maxaggrnormscale > 0.0);
13640 continue;
13641
13642 /* make sure, we have enough memory for the index set of V_1 \ V_0 */
13644 {
13647 }
13648
13649 /* check consdata0 against consdata1:
13650 * - if lhs0 >= lhs1 and for each variable v and each solution value x_v val0[v]*x_v <= val1[v]*x_v,
13651 * consdata0 dominates consdata1 w.r.t. left hand side
13652 * - if rhs0 <= rhs1 and for each variable v and each solution value x_v val0[v]*x_v >= val1[v]*x_v,
13653 * consdata0 dominates consdata1 w.r.t. right hand side
13654 * - if val0[v] == -val1[v] for all variables v, the two inequalities can be replaced by a single
13655 * ranged row (or equality)
13656 * - if at least one constraint is an equality, count the weighted number of common variables W_c
13657 * and the weighted number of variable in the difference sets W_0 = w(V_0 \ V_1), W_1 = w(V_1 \ V_0),
13658 * where the weight of each variable depends on its type, such that aggregations in order to remove the
13659 * number of continuous and integer variables are preferred:
13660 * - if W_c > W_1, try to aggregate consdata0 := a * consdata0 + b * consdata1 in order to decrease the
13661 * variable weight in consdata0, where a = +/- val1[v] and b = -/+ val0[v] for common v which leads to
13662 * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13663 * to be positive to not switch the sense of the (in)equality cons0
13664 * - if W_c > W_0, try to aggregate consdata1 := a * consdata1 + b * consdata0 in order to decrease the
13665 * variable weight in consdata1, where a = +/- val0[v] and b = -/+ val1[v] for common v which leads to
13666 * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13667 * to be positive to not switch the sense of the (in)equality cons1
13668 */
13669
13670 /* check consdata0 against consdata1 for redundancy, or ranged row accumulation */
13671 nvarscommon = 0;
13672 commonidxweight = 0;
13673 nvars0minus1 = 0;
13675 nvars1minus0 = 0;
13677 v0 = 0;
13678 v1 = 0;
13682 {
13683 SCIP_VAR* var;
13684 SCIP_Real val0;
13685 SCIP_Real val1;
13686 int varcmp;
13687
13688 /* test, if variable appears in only one or in both constraints */
13690 varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
13691 else if( v0 < consdata0->nvars )
13692 varcmp = -1;
13693 else
13694 varcmp = +1;
13695
13696 switch( varcmp )
13697 {
13698 case -1:
13699 /* variable doesn't appear in consdata1 */
13700 var = consdata0->vars[v0];
13701 val0 = consdata0->vals[v0];
13702 val1 = 0.0;
13703 if( tryaggregation )
13704 {
13706 nvars0minus1++;
13708 }
13709 v0++;
13710 coefsequal = FALSE;
13712 break;
13713
13714 case +1:
13715 /* variable doesn't appear in consdata0 */
13716 var = consdata1->vars[v1];
13717 val0 = 0.0;
13718 val1 = consdata1->vals[v1];
13719 if( tryaggregation )
13720 {
13722 nvars1minus0++;
13724 }
13725 v1++;
13726 coefsequal = FALSE;
13728 break;
13729
13730 case 0:
13731 /* variable appears in both constraints */
13732 assert(consdata0->vars[v0] == consdata1->vars[v1]);
13733 var = consdata0->vars[v0];
13734 val0 = consdata0->vals[v0];
13735 val1 = consdata1->vals[v1];
13736 if( tryaggregation )
13737 {
13740 nvarscommon++;
13742 }
13743 v0++;
13744 v1++;
13747 break;
13748
13749 default:
13750 SCIPerrorMessage("invalid comparison result\n");
13751 SCIPABORT();
13752 var = NULL;
13753 val0 = 0.0;
13754 val1 = 0.0;
13755 }
13756 assert(var != NULL);
13757
13758 /* update domination criteria w.r.t. the coefficient and the variable's bounds */
13759 if( SCIPisGT(scip, val0, val1) )
13760 {
13762 {
13765 }
13767 {
13770 }
13771 }
13772 else if( SCIPisLT(scip, val0, val1) )
13773 {
13775 {
13778 }
13780 {
13783 }
13784 }
13785 }
13786
13787 /* check for disaggregated ranged rows */
13788 if( coefsequal || coefsnegated )
13789 {
13792#ifndef NDEBUG
13794#endif
13796 SCIP_Real lhs;
13797 SCIP_Real rhs;
13798 int consinddel;
13799
13800 /* the coefficients in both rows are either equal or negated: create a new constraint with same coefficients and
13801 * best left and right hand sides; delete the old constraints afterwards
13802 */
13803 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with %s coefficients into single ranged row\n",
13804 SCIPconsGetName(cons0), SCIPconsGetName(cons1), coefsequal ? "equal" : "negated");
13807
13808 if( coefsequal )
13809 {
13810 /* the coefficients of both rows are equal */
13811 lhs = MAX(consdata0->lhs, consdata1->lhs);
13812 rhs = MIN(consdata0->rhs, consdata1->rhs);
13813 }
13814 else
13815 {
13816 /* the coefficients of both rows are negations */
13817 lhs = MAX(consdata0->lhs, -consdata1->rhs);
13818 rhs = MIN(consdata0->rhs, -consdata1->lhs);
13819 }
13820 if( SCIPisFeasLT(scip, rhs, lhs) )
13821 {
13822 SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13823 *cutoff = TRUE;
13824 break;
13825 }
13826
13827 /* check which constraint has to stay;
13828 * changes applied to an upgraded constraint will not be considered in the instance */
13829 if( consdata0->upgraded )
13830 {
13831 assert(!consdata1->upgraded);
13832 consstay = cons1;
13833#ifndef NDEBUG
13835#endif
13836
13837 consdel = cons0;
13840 }
13841 else
13842 {
13843 consstay = cons0;
13844#ifndef NDEBUG
13846#endif
13847
13848 consdel = cons1;
13850 consinddel = c;
13851 }
13852
13853 /* update the sides of consstay */
13854 SCIP_CALL( chgLhs(scip, consstay, lhs) );
13855 SCIP_CALL( chgRhs(scip, consstay, rhs) );
13856 if( !consdata0->upgraded )
13857 {
13858 assert(consstay == cons0);
13859 cons0lhs = consdata0->lhs;
13860 cons0rhs = consdata0->rhs;
13861 }
13862
13863 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13865
13866 assert( !consdatastay->upgraded );
13867 /* delete consdel */
13869 conss[consinddel] = NULL;
13870 if( !consdatadel->upgraded )
13871 (*ndelconss)++;
13872 continue;
13873 }
13874
13875 /* check for domination: remove dominated sides, but don't touch equalities as long as they are not totally
13876 * redundant
13877 */
13879 {
13880 /* left hand side is dominated by consdata1: delete left hand side of consdata0 */
13881 SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13885
13886 /* check for infeasibility */
13887 if( SCIPisFeasGT(scip, consdata1->lhs, consdata0->rhs) )
13888 {
13889 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13890 *cutoff = TRUE;
13891 break;
13892 }
13893
13894 /* remove redundant left hand side */
13895 if( !SCIPisInfinity(scip, -consdata0->lhs) )
13896 {
13898 cons0lhs = consdata0->lhs;
13900 if( !consdata0->upgraded )
13901 {
13902 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13904
13905 (*nchgsides)++;
13906 }
13907 }
13908 }
13910 {
13911 /* left hand side is dominated by consdata0: delete left hand side of consdata1 */
13912 SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13916
13917 /* check for infeasibility */
13918 if( SCIPisFeasGT(scip, consdata0->lhs, consdata1->rhs) )
13919 {
13920 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13921 *cutoff = TRUE;
13922 break;
13923 }
13924
13925 /* remove redundant left hand side */
13926 if( !SCIPisInfinity(scip, -consdata1->lhs) )
13927 {
13930 if( !consdata1->upgraded )
13931 {
13932 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13934
13935 (*nchgsides)++;
13936 }
13937 }
13938 }
13940 {
13941 /* right hand side is dominated by consdata1: delete right hand side of consdata0 */
13942 SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13946
13947 /* check for infeasibility */
13948 if( SCIPisFeasLT(scip, consdata1->rhs, consdata0->lhs) )
13949 {
13950 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13951 *cutoff = TRUE;
13952 break;
13953 }
13954
13955 /* remove redundant right hand side */
13956 if( !SCIPisInfinity(scip, consdata0->rhs) )
13957 {
13959 cons0rhs = consdata0->rhs;
13961 if( !consdata0->upgraded )
13962 {
13963 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13965
13966 (*nchgsides)++;
13967 }
13968 }
13969 }
13971 {
13972 /* right hand side is dominated by consdata0: delete right hand side of consdata1 */
13973 SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13977
13978 /* check for infeasibility */
13979 if( SCIPisFeasLT(scip, consdata0->rhs, consdata1->lhs) )
13980 {
13981 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13982 *cutoff = TRUE;
13983 break;
13984 }
13985
13986 /* remove redundant right hand side */
13987 if( !SCIPisInfinity(scip, consdata1->rhs) )
13988 {
13991 if( !consdata1->upgraded )
13992 {
13993 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13995
13996 (*nchgsides)++;
13997 }
13998 }
13999 }
14000
14001 /* check for now redundant constraints */
14003 {
14004 /* consdata0 became redundant */
14005 SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons0));
14007 conss[chkind] = NULL;
14008 if( !consdata0->upgraded )
14009 {
14010 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
14012
14013 (*ndelconss)++;
14014 }
14015 continue;
14016 }
14018 {
14019 /* consdata1 became redundant */
14020 SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons1));
14022 conss[c] = NULL;
14023 if( !consdata1->upgraded )
14024 {
14025 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
14027
14028 (*ndelconss)++;
14029 }
14030 continue;
14031 }
14032
14033 /* check, if we want to aggregate an (in)equality with an equality:
14034 * consdata0 := a * consdata0 + b * consdata1 or consdata1 := a * consdata1 + b * consdata0
14035 */
14036 if( tryaggregation )
14037 {
14038 SCIP_Bool aggregated;
14039
14042
14043 aggregated = FALSE;
14045 {
14046 /* W_c > W_1: try to aggregate consdata0 := a * consdata0 + b * consdata1 */
14049 nchgcoefs, &aggregated, cutoff) );
14050
14051 if( *cutoff )
14052 break;
14053
14054 /* update array of active constraints */
14055 if( aggregated )
14056 {
14059 conss[chkind] = NULL;
14060 }
14061 }
14063 {
14064 /* W_c > W_0: try to aggregate consdata1 := a * consdata1 + b * consdata0 */
14067 nchgcoefs, &aggregated, cutoff) );
14068
14069 if( *cutoff )
14070 break;
14071
14072 /* update array of active constraints */
14073 if( aggregated )
14074 {
14077 conss[c] = NULL;
14078 }
14079 }
14080 }
14081 }
14082
14083 /* free temporary memory */
14088
14089 return SCIP_OKAY;
14090}
14091
14092/** do stuffing presolving on a single constraint */
14093static
14095 SCIP* scip, /**< SCIP data structure */
14096 SCIP_CONS* cons, /**< linear constraint */
14097 SCIP_Bool singletonstuffing, /**< should stuffing of singleton continuous variables be performed? */
14098 SCIP_Bool singlevarstuffing, /**< should single variable stuffing be performed, which tries to fulfill
14099 * constraints using the cheapest variable? */
14100 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14101 int* nfixedvars, /**< pointer to count the total number of fixed variables */
14102 int* nchgbds /**< pointer to count the total number of tightened bounds */
14103 )
14104{
14105 SCIP_CONSDATA* consdata;
14106 SCIP_Real* ratios;
14107 int* varpos;
14108 SCIP_Bool* swapped;
14109 SCIP_VAR** vars;
14110 SCIP_Real* vals;
14111 SCIP_VAR* var;
14112 SCIP_Real lb;
14113 SCIP_Real ub;
14114 SCIP_Real minactivity;
14115 SCIP_Real maxactivity;
14116 SCIP_Real maxcondactivity;
14117 SCIP_Real mincondactivity;
14118 SCIP_Real rhs;
14119 SCIP_Real val;
14120 SCIP_Real obj;
14121 SCIP_Real factor;
14122 SCIP_Bool minactisrelax;
14123 SCIP_Bool maxactisrelax;
14124 SCIP_Bool isminsettoinfinity;
14125 SCIP_Bool ismaxsettoinfinity;
14126 SCIP_Bool tryfixing;
14127 int nsingletons;
14128 int idx;
14129 int v;
14130 int nvars;
14131
14132 assert(scip != NULL);
14133 assert(cons != NULL);
14134 assert(nfixedvars != NULL);
14135
14136 consdata = SCIPconsGetData(cons);
14137
14138 /* we only want to run for inequalities */
14139 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->lhs) )
14140 return SCIP_OKAY;
14141
14142 if( singlevarstuffing )
14143 {
14144 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
14146 }
14147 else
14148 {
14149 minactivity = SCIP_INVALID;
14150 maxactivity = SCIP_INVALID;
14153 }
14154
14155 /* we want to have a <= constraint, if the rhs is infinite, we implicitly multiply the constraint by -1,
14156 * the new maxactivity is minus the old minactivity then
14157 */
14158 if( SCIPisInfinity(scip, consdata->rhs) )
14159 {
14160 rhs = -consdata->lhs;
14161 factor = -1.0;
14162 maxactivity = -minactivity;
14164 }
14165 else
14166 {
14167 assert(SCIPisInfinity(scip, -consdata->lhs));
14168 rhs = consdata->rhs;
14169 factor = 1.0;
14170 }
14171
14172 nvars = consdata->nvars;
14173 vars = consdata->vars;
14174 vals = consdata->vals;
14175
14176 /* check for continuous singletons */
14177 if( singletonstuffing )
14178 {
14179 for( v = 0; v < nvars; ++v )
14180 {
14181 var = vars[v];
14182
14185 break;
14186 }
14187 }
14188 else
14189 /* we don't want to go into the next block */
14190 v = nvars;
14191
14192 /* a singleton was found -> perform singleton variable stuffing */
14193 if( v < nvars )
14194 {
14195 assert(singletonstuffing);
14196
14200
14201 tryfixing = TRUE;
14202 nsingletons = 0;
14203 mincondactivity = 0.0;
14204 maxcondactivity = 0.0;
14205
14206 for( v = 0; v < nvars; ++v )
14207 {
14208 var = vars[v];
14209 lb = SCIPvarGetLbGlobal(var);
14210 ub = SCIPvarGetUbGlobal(var);
14212 val = factor * vals[v];
14213
14214 assert(!SCIPisZero(scip, val));
14215
14216 /* the variable is a singleton and continuous */
14219 {
14220 if( SCIPisNegative(scip, obj) && val > 0 )
14221 {
14222 /* case 1: obj < 0 and coef > 0 */
14223 if( SCIPisInfinity(scip, -lb) )
14224 {
14225 tryfixing = FALSE;
14226 break;
14227 }
14228
14229 maxcondactivity += val * lb;
14230 mincondactivity += val * lb;
14231 swapped[v] = FALSE;
14232 ratios[nsingletons] = obj / val;
14233 varpos[nsingletons] = v;
14234 nsingletons++;
14235 }
14236 else if( SCIPisPositive(scip, obj) && val < 0 )
14237 {
14238 /* case 2: obj > 0 and coef < 0 */
14239 if( SCIPisInfinity(scip, ub) )
14240 {
14241 tryfixing = FALSE;
14242 break;
14243 }
14244 /* multiply column by (-1) to become case 1.
14245 * now bounds are swapped: ub := -lb, lb := -ub
14246 */
14247
14248 maxcondactivity += val * ub;
14249 mincondactivity += val * ub;
14250 swapped[v] = TRUE;
14251 ratios[nsingletons] = obj / val;
14252 varpos[nsingletons] = v;
14253 nsingletons++;
14254 }
14255 else if( val > 0 )
14256 {
14257 /* case 3: obj >= 0 and coef >= 0 is handled by duality fixing.
14258 * we only consider the lower bound for the constants
14259 */
14261
14262 if( SCIPisInfinity(scip, -lb) )
14263 {
14264 /* maybe unbounded */
14265 tryfixing = FALSE;
14266 break;
14267 }
14268
14269 maxcondactivity += val * lb;
14270 mincondactivity += val * lb;
14271 }
14272 else
14273 {
14274 /* case 4: obj <= 0 and coef <= 0 is also handled by duality fixing.
14275 * we only consider the upper bound for the constants
14276 */
14278 assert(val < 0);
14279
14280 if( SCIPisInfinity(scip, ub) )
14281 {
14282 /* maybe unbounded */
14283 tryfixing = FALSE;
14284 break;
14285 }
14286
14287 maxcondactivity += val * ub;
14288 mincondactivity += val * ub;
14289 }
14290 }
14291 else
14292 {
14293 /* consider contribution of discrete variables, non-singleton
14294 * continuous variables and variables with more than one lock
14295 */
14296 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14297 {
14298 tryfixing = FALSE;
14299 break;
14300 }
14301
14302 if( val > 0 )
14303 {
14304 maxcondactivity += val * ub;
14305 mincondactivity += val * lb;
14306 }
14307 else
14308 {
14309 maxcondactivity += val * lb;
14310 mincondactivity += val * ub;
14311 }
14312 }
14313 }
14315 {
14316 SCIP_Real delta;
14317 SCIP_Bool tightened;
14318#ifdef SCIP_DEBUG
14319 int oldnfixedvars = *nfixedvars;
14320 int oldnchgbds = *nchgbds;
14321#endif
14322
14324
14325 /* verify which singleton continuous variables can be fixed */
14326 for( v = 0; v < nsingletons; ++v )
14327 {
14328 idx = varpos[v];
14329 var = vars[idx];
14330 val = factor * vals[idx];
14331 lb = SCIPvarGetLbGlobal(var);
14332 ub = SCIPvarGetUbGlobal(var);
14333
14335 assert((val < 0) == swapped[idx]);
14336 val = REALABS(val);
14337
14338 /* stop fixing if variable bounds are not finite */
14339 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14340 break;
14341
14345
14346 /* calculate the change in the row activities if this variable changes
14347 * its value from its worst to its best bound
14348 */
14349 if( swapped[idx] )
14350 delta = -(lb - ub) * val;
14351 else
14352 delta = (ub - lb) * val;
14353
14354 assert(!SCIPisNegative(scip, delta));
14355
14356 if( SCIPisLE(scip, delta, rhs - maxcondactivity) )
14357 {
14358 if( swapped[idx] )
14359 {
14360 SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14361 SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14362 }
14363 else
14364 {
14365 SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14366 SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14367 }
14368
14369 if( *cutoff )
14370 break;
14371 if( tightened )
14372 {
14373 (*nfixedvars)++;
14374 }
14375 }
14376 /* @note: we could in theory tighten the bound of the first singleton variable which does not fall into the above case,
14377 * since it cannot be fully fixed. However, this is not needed and should be done by activity-based bound tightening
14378 * anyway after all other continuous singleton columns were fixed; doing it here may introduce numerical
14379 * troubles in case of large bounds.
14380 */
14381 else if( SCIPisLE(scip, rhs, mincondactivity) )
14382 {
14383 if( swapped[idx] )
14384 {
14385 SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14386 SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14387 }
14388 else
14389 {
14390 SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14391 SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14392 }
14393
14394 if( *cutoff )
14395 break;
14396 if( tightened )
14397 {
14398 (*nfixedvars)++;
14399 }
14400 }
14401
14402 maxcondactivity += delta;
14403 mincondactivity += delta;
14404 }
14405
14406#ifdef SCIP_DEBUG
14407 if( *nfixedvars - oldnfixedvars > 0 || *nchgbds - oldnchgbds > 0 )
14408 {
14409 SCIPdebugMsg(scip, "### stuffing fixed %d variables and changed %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds);
14410 }
14411#endif
14412 }
14413
14416 SCIPfreeBufferArray(scip, &varpos);
14417 }
14418
14419 /* perform single-variable stuffing:
14420 * for a linear inequality
14421 * a_1 x_1 + a_2 x_2 + ... + a_n x_n <= b
14422 * with a_i > 0 and objective coefficients c_i < 0,
14423 * setting all variables to their upper bound (giving us the maximal activity of the constraint) is worst w.r.t.
14424 * feasibility of the constraint. On the other hand, this gives the best objective function contribution of the
14425 * variables contained in the constraint. The maximal activity should be larger than the rhs, otherwise the constraint
14426 * is redundant.
14427 * Now we are searching for a variable x_k with maximal ratio c_k / a_k (note that all these ratios are negative), so
14428 * that by reducing the value of this variable we reduce the activity of the constraint while having the smallest
14429 * objective deterioration per activity unit. If x_k has no downlocks, is continuous, and can be reduced enough to
14430 * render the constraint feasible, and ALL other variables have only the one uplock installed by the current constraint,
14431 * we can reduce the upper bound of x_k such that the maxactivity equals the rhs and fix all other variables to their
14432 * upper bound.
14433 * Note that the others variables may have downlocks from other constraints, which we do not need to care
14434 * about since we are setting them to the highest possible value. Also, they may be integer or binary, because the
14435 * computed ratio is still a lower bound on the change in the objective caused by reducing those variable to reach
14436 * constraint feasibility. On the other hand, uplocks on x_k from other constraint do no interfer with the method.
14437 * With a slight adjustment, the procedure even works for integral x_k. If (maxactivity - rhs)/val is integral,
14438 * the variable gets an integral value in order to fulfill the constraint tightly, and we can just apply the procedure.
14439 * If (maxactivity - rhs)/val is fractional, we need to check, if overfulfilling the constraint by setting x_k to
14440 * ceil((maxactivity - rhs)/val) is still better than setting x_k to ceil((maxactivity - rhs)/val) - 1 and
14441 * filling the remaining gap in the constraint with the next-best variable. For this, we check that
14442 * c_k * ceil((maxactivity - rhs)/val) is still better than
14443 * c_k * floor((maxactivity - rhs)/val) + c_j * ((maxactivity - rhs) - (floor((maxactivity - rhs)/val) * val))/a_j.
14444 * In this case, the upper bound of x_k is decreased to ub_k - ceil(maxactivity - rhs).
14445 * If there are variables with a_i < 0 and c_i > 0, they are negated to obtain the above form, variables with same
14446 * sign of coefficients in constraint and objective prevent the use of this method.
14447 */
14448 if( singlevarstuffing && !ismaxsettoinfinity )
14449 {
14450 SCIP_Real bestratio = -SCIPinfinity(scip);
14451 SCIP_Real secondbestratio = -SCIPinfinity(scip);
14452 SCIP_Real ratio;
14453 int bestindex = -1;
14454 int bestuplocks = 0;
14455 int bestdownlocks = 1;
14456 int downlocks;
14457 int uplocks;
14458 SCIPdebug( int oldnfixedvars = *nfixedvars; )
14459 SCIPdebug( int oldnchgbds = *nchgbds; )
14460
14461 /* loop over all variables to identify the best and second-best ratio */
14462 for( v = 0; v < nvars; ++v )
14463 {
14464 var = vars[v];
14466 val = factor * vals[v];
14467
14468 assert(!SCIPisZero(scip, val));
14469
14470 ratio = obj / val;
14471
14472 /* if both objective and constraint push the variable to the same direction, we can do nothing here */
14473 if( !SCIPisNegative(scip, ratio) )
14474 {
14475 bestindex = -1;
14476 break;
14477 }
14478
14479 if( val > 0 )
14480 {
14483 }
14484 else
14485 {
14488 }
14489
14490 /* better ratio, update best candidate
14491 * @todo use some tolerance
14492 * @todo check size of domain and updated ratio for integer variables already?
14493 */
14494 if( ratio > bestratio || ((ratio == bestratio) && downlocks == 0 && (bestdownlocks > 0 /*lint !e777*/
14497 {
14498 /* best index becomes second-best*/
14499 if( bestindex != -1 )
14500 {
14501 /* second-best index must not have more than 1 uplock */
14502 if( bestuplocks > 1 )
14503 {
14504 bestindex = -1;
14505 break;
14506 }
14507 else
14508 {
14510 }
14511 }
14512 bestdownlocks = downlocks;
14513 bestuplocks = uplocks;
14514 bestratio = ratio;
14515 bestindex = v;
14516
14517 /* if this variable is the best in the end, we cannot do reductions since it has a downlocks,
14518 * if it is not the best, it has too many uplocks -> not applicable
14519 */
14520 if( bestdownlocks > 0 && bestuplocks > 1 )
14521 {
14522 bestindex = -1;
14523 break;
14524 }
14525 }
14526 else
14527 {
14528 /* non-best index must not have more than 1 uplock */
14529 if( uplocks > 1 )
14530 {
14531 bestindex = -1;
14532 break;
14533 }
14534 /* update second-best ratio */
14535 if( ratio > secondbestratio )
14536 {
14537 secondbestratio = ratio;
14538 }
14539 }
14540 }
14541
14542 /* check if we can apply single variable stuffing */
14543 if( bestindex != -1 && bestdownlocks == 0 )
14544 {
14545 SCIP_Bool tightened = FALSE;
14546 SCIP_Real bounddelta;
14547
14548 var = vars[bestindex];
14550 val = factor * vals[bestindex];
14551 lb = SCIPvarGetLbGlobal(var);
14552 ub = SCIPvarGetUbGlobal(var);
14553 tryfixing = TRUE;
14554
14555 if( val < 0 )
14556 {
14558
14559 /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14560 if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/-val) )
14561 {
14562 SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/-val);
14563 SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * -val);
14565
14567
14568 bounddelta = SCIPceil(scip, (maxactivity - rhs)/-val);
14570 }
14571 else
14572 bounddelta = (maxactivity - rhs)/-val;
14573
14574 tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14575
14576 if( tryfixing )
14577 {
14579
14580 if( SCIPisEQ(scip, lb + bounddelta, ub) )
14581 {
14582 SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), lb + bounddelta);
14583 SCIP_CALL( SCIPfixVar(scip, var, lb + bounddelta, cutoff, &tightened) );
14584 }
14585 else
14586 {
14587 SCIPdebugMsg(scip, "tighten the lower bound of <%s> from %g to %g (ub=%g)\n", SCIPvarGetName(var), lb, lb + bounddelta, ub);
14588 SCIP_CALL( SCIPtightenVarLb(scip, var, lb + bounddelta, FALSE, cutoff, &tightened) );
14589 }
14590 }
14591 }
14592 else
14593 {
14595
14596 /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14597 if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/val))
14598 {
14599 SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/val);
14600 SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * val);
14602
14604
14605 bounddelta = SCIPceil(scip, (maxactivity - rhs)/val);
14607 }
14608 else
14609 bounddelta = (maxactivity - rhs)/val;
14610
14611 tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14612
14613 if( tryfixing )
14614 {
14616
14617 if( SCIPisEQ(scip, ub - bounddelta, lb) )
14618 {
14619 SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), ub - bounddelta);
14620 SCIP_CALL( SCIPfixVar(scip, var, ub - bounddelta, cutoff, &tightened) );
14621 }
14622 else
14623 {
14624 SCIPdebugMsg(scip, "tighten the upper bound of <%s> from %g to %g (lb=%g)\n", SCIPvarGetName(var), ub, ub - bounddelta, lb);
14625 SCIP_CALL( SCIPtightenVarUb(scip, var, ub - bounddelta, FALSE, cutoff, &tightened) );
14626 }
14627 }
14628 }
14629
14630 if( *cutoff )
14631 return SCIP_OKAY;
14632 if( tightened )
14633 {
14635 ++(*nfixedvars);
14636 else
14637 ++(*nchgbds);
14638
14639 SCIPdebugMsg(scip, "cons <%s>: %g <=\n", SCIPconsGetName(cons), factor > 0 ? consdata->lhs : -consdata->rhs);
14640 for( v = 0; v < nvars; ++v )
14641 {
14642 SCIPdebugMsg(scip, "%+g <%s>([%g,%g],%g,[%d,%d],%s)\n", factor * vals[v], SCIPvarGetName(vars[v]),
14646 SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS ? "C" : "I");
14647 }
14648 SCIPdebugMsg(scip, "<= %g\n", factor > 0 ? consdata->rhs : -consdata->lhs);
14649
14650 for( v = 0; v < nvars; ++v )
14651 {
14652 if( v == bestindex )
14653 continue;
14654
14655 if( factor * vals[v] < 0 )
14656 {
14658 SCIPdebugMsg(scip, "fix <%s> to its lower bound (%g)\n",
14660 SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetLbGlobal(vars[v]), cutoff, &tightened) );
14661 }
14662 else
14663 {
14665 SCIPdebugMsg(scip, "fix <%s> to its upper bound (%g)\n",
14667 SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetUbGlobal(vars[v]), cutoff, &tightened) );
14668 }
14669
14670 if( *cutoff )
14671 return SCIP_OKAY;
14672 if( tightened )
14673 ++(*nfixedvars);
14674 }
14675 SCIPdebug( SCIPdebugMsg(scip, "### new stuffing fixed %d vars, tightened %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds); )
14676 }
14677 }
14678 }
14679
14680 return SCIP_OKAY;
14681}
14682
14683/** applies full dual presolving on variables that only appear in linear constraints */
14684static
14686 SCIP* scip, /**< SCIP data structure */
14687 SCIP_CONS** conss, /**< constraint set */
14688 int nconss, /**< number of constraints */
14689 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14690 int* nchgbds /**< pointer to count the number of bound changes */
14691 )
14692{
14693 SCIP_Real* redlb;
14694 SCIP_Real* redub;
14695 int* nlocksdown;
14696 int* nlocksup;
14697 SCIP_Bool* isimplint;
14698 SCIP_VAR** origvars;
14699 SCIP_VAR** vars;
14701 int nvars;
14702 int nbinvars;
14703 int nintvars;
14704 int ncontvars;
14705 int v;
14706 int c;
14707
14708 /* we calculate redundancy bounds with the following meaning:
14709 * redlb[v] == k : if x_v >= k, we can always round x_v down to x_v == k without violating any constraint
14710 * redub[v] == k : if x_v <= k, we can always round x_v up to x_v == k without violating any constraint
14711 * then:
14712 * c_v >= 0 : x_v <= redlb[v] is feasible due to optimality
14713 * c_v <= 0 : x_v >= redub[v] is feasible due to optimality
14714 */
14715
14716 /* Additionally, we detect continuous variables that are implicitly integral.
14717 * A continuous variable j is implicit integral if it only has only +/-1 coefficients,
14718 * and all constraints (including the bounds as trivial constraints) in which:
14719 * c_j > 0: the variable is down-locked,
14720 * c_j < 0: the variable is up-locked,
14721 * c_j = 0: the variable appears
14722 * have, apart from j, only integer variables with integral coefficients and integral sides.
14723 * This is because then, the value of the variable is either determined by one of its bounds or
14724 * by one of these constraints, and in all cases, the value of the variable is integral.
14725 */
14726
14727 assert(scip != NULL);
14728 assert(nconss == 0 || conss != NULL);
14729 assert(nchgbds != NULL);
14731
14732 /* get active variables */
14734 origvars = SCIPgetVars(scip);
14735
14736 /* if the problem is a pure binary program, nothing can be achieved by full dual presolve */
14738 if( nbinvars == nvars )
14739 return SCIP_OKAY;
14740
14741 /* get number of continuous variables */
14742 ncontvars = SCIPgetNContVars(scip);
14743 nintvars = nvars - ncontvars;
14744
14745 /* copy the variable array since this array might change during the curse of this algorithm */
14746 nvars = nvars - nbinvars;
14748
14749 /* allocate temporary memory */
14752 SCIP_CALL( SCIPallocBufferArray(scip, &nlocksdown, nvars) );
14753 SCIP_CALL( SCIPallocBufferArray(scip, &nlocksup, nvars) );
14756
14757 /* initialize redundancy bounds */
14758 for( v = 0; v < nvars; ++v )
14759 {
14761 redlb[v] = SCIPvarGetLbGlobal(vars[v]);
14762 redub[v] = SCIPvarGetUbGlobal(vars[v]);
14763 }
14764 BMSclearMemoryArray(nlocksdown, nvars);
14765 BMSclearMemoryArray(nlocksup, nvars);
14766
14767 /* Initialize isimplint array: variable may be implicit integer if rounded to their best bound they are integral.
14768 * We better not use SCIPisFeasIntegral() in these checks.
14769 */
14770 for( v = 0; v < ncontvars; v++ )
14771 {
14772 SCIP_VAR* var;
14773 SCIP_Real obj;
14774 SCIP_Real lb;
14775 SCIP_Real ub;
14776
14777 var = vars[v + nintvars - nbinvars];
14778 lb = SCIPvarGetLbGlobal(var);
14779 ub = SCIPvarGetUbGlobal(var);
14780
14782 if( SCIPisZero(scip, obj) )
14783 isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb)) && (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14784 else
14785 {
14786 if( SCIPisPositive(scip, obj) )
14787 isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb));
14788 else
14789 {
14791 isimplint[v] = (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14792 }
14793 }
14794 }
14795
14796 /* scan all constraints */
14797 for( c = 0; c < nconss; ++c )
14798 {
14799 /* we only need to consider constraints that have been locked (i.e., checked constraints or constraints that are
14800 * part of checked disjunctions)
14801 */
14802 if( SCIPconsIsLocked(conss[c]) )
14803 {
14804 SCIP_CONSDATA* consdata;
14805 SCIP_Bool lhsexists;
14806 SCIP_Bool rhsexists;
14807 SCIP_Bool hasimpliedpotential;
14808 SCIP_Bool integralcoefs;
14809 int nlockspos;
14810 int contvarpos;
14811 int nconscontvars;
14812 int i;
14813
14814 consdata = SCIPconsGetData(conss[c]);
14815 assert(consdata != NULL);
14816
14817 /* get number of times the constraint was locked */
14818 nlockspos = SCIPconsGetNLocksPos(conss[c]);
14819
14820 /* we do not want to include constraints with locked negation (this would be too weird) */
14821 if( SCIPconsGetNLocksNeg(conss[c]) > 0 )
14822 {
14823 /* mark all continuous variables as not being implicit integral */
14824 for( i = 0; i < consdata->nvars; ++i )
14825 {
14826 SCIP_VAR* var;
14827
14828 var = consdata->vars[i];
14830 {
14831 int contv;
14833 assert(0 <= contv && contv < ncontvars); /* variable should be active due to applyFixings() */
14835 }
14836 }
14837 continue;
14838 }
14839
14840 /* check for existing sides */
14841 lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
14842 rhsexists = !SCIPisInfinity(scip, consdata->rhs);
14843
14844 /* count locks and update redundancy bounds */
14845 contvarpos = -1;
14846 nconscontvars = 0;
14849
14850 for( i = 0; i < consdata->nvars; ++i )
14851 {
14852 SCIP_VAR* var;
14853 SCIP_Real val;
14854 SCIP_Real minresactivity;
14855 SCIP_Real maxresactivity;
14856 SCIP_Real newredlb;
14857 SCIP_Real newredub;
14858 SCIP_Bool minisrelax;
14859 SCIP_Bool maxisrelax;
14860 SCIP_Bool isminsettoinfinity;
14861 SCIP_Bool ismaxsettoinfinity;
14862 int arrayindex;
14863
14864 var = consdata->vars[i];
14865 val = consdata->vals[i];
14866
14867 /* check if still all integer variables have integral coefficients */
14868 if( SCIPvarIsIntegral(var) )
14870
14871 /* we do not need to process binary variables */
14872 if( SCIPvarIsBinary(var) )
14873 continue;
14874
14875 if( SCIPconsIsModifiable(conss[c]) )
14876 {
14881 }
14882 else
14883 {
14884 /* calculate residual activity bounds if variable would be fixed to zero */
14887
14888 /* We called consdataGetGlbActivityResiduals() saying that we do not need a good relaxation,
14889 * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
14890 * This is needed, because we do not want to rely on relaxed finite resactivities.
14891 */
14893
14894 /* check minresactivity for reliability */
14895 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
14897
14898 /* check maxresactivity for reliability */
14899 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
14901 }
14902
14904
14905 assert(0 <= arrayindex && arrayindex < nvars); /* variable should be active due to applyFixings() */
14906
14909 if( val > 0.0 )
14910 {
14911 if( lhsexists )
14912 {
14913 /* lhs <= d*x + a*y, d > 0 -> redundant in y if x >= (lhs - min{a*y})/d */
14914 nlocksdown[arrayindex] += nlockspos;
14915 newredlb = (isminsettoinfinity ? SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14916 }
14917 if( rhsexists )
14918 {
14919 /* d*x + a*y <= rhs, d > 0 -> redundant in y if x <= (rhs - max{a*y})/d */
14920 nlocksup[arrayindex] += nlockspos;
14921 newredub = (ismaxsettoinfinity ? -SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14922 }
14923 }
14924 else
14925 {
14926 if( lhsexists )
14927 {
14928 /* lhs <= d*x + a*y, d < 0 -> redundant in y if x <= (lhs - min{a*y})/d */
14929 nlocksup[arrayindex] += nlockspos;
14930 newredub = (isminsettoinfinity ? -SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14931 }
14932 if( rhsexists )
14933 {
14934 /* d*x + a*y <= rhs, d < 0 -> redundant in y if x >= (rhs - max{a*y})/d */
14935 nlocksdown[arrayindex] += nlockspos;
14936 newredlb = (ismaxsettoinfinity ? SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14937 }
14938 }
14939
14940 /* if the variable is integer, we have to round the value to the next integral value */
14941 if( SCIPvarIsIntegral(var) )
14942 {
14945 if( !SCIPisInfinity(scip, -newredub) )
14947 }
14948
14949 /* update redundancy bounds */
14952
14953 /* collect the continuous variables of the constraint */
14955 {
14956 int contv;
14957
14958 assert(nconscontvars < ncontvars);
14959 contvarpos = i;
14961 nconscontvars++;
14962
14964 assert(0 <= contv && contv < ncontvars);
14966 }
14967 }
14968
14969 /* update implicit integer status of continuous variables */
14971 {
14972 if( nconscontvars > 1 || !integralcoefs )
14973 {
14974 /* there is more than one continuous variable or the integer variables have fractional coefficients:
14975 * none of the continuous variables is implicit integer
14976 */
14977 for( i = 0; i < nconscontvars; i++ )
14978 {
14979 int contv;
14981 assert(0 <= contv && contv < ncontvars);
14983 }
14984 }
14985 else
14986 {
14987 SCIP_VAR* var;
14988 SCIP_Real val;
14989 SCIP_Real absval;
14990 int contv;
14991
14992 /* there is exactly one continuous variable and the integer variables have integral coefficients:
14993 * this is the interesting case, and we have to check whether the coefficient is +/-1 and the corresponding
14994 * side(s) of the constraint is integral
14995 */
14996 assert(nconscontvars == 1);
14998 var = consdata->vars[contvarpos];
14999 val = consdata->vals[contvarpos];
15001 assert(0 <= contv && contv < ncontvars);
15003
15004 absval = REALABS(val);
15005 if( !SCIPisEQ(scip, absval, 1.0) )
15007 else
15008 {
15009 SCIP_Real obj;
15010
15012 if( obj * val >= 0.0 && lhsexists )
15013 {
15014 /* the variable may be blocked by the constraint's left hand side */
15015 isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->lhs);
15016 }
15017 if( obj * val <= 0.0 && rhsexists )
15018 {
15019 /* the variable may be blocked by the constraint's left hand side */
15020 isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->rhs);
15021 }
15022 }
15023 }
15024 }
15025 }
15026 }
15027
15028 /* check if any bounds can be tightened due to optimality */
15029 for( v = 0; v < nvars; ++v )
15030 {
15031 SCIP_VAR* var;
15032 SCIP_Real obj;
15033 SCIP_Bool infeasible;
15034 SCIP_Bool tightened;
15035
15039
15040 var = vars[v];
15042 if( !SCIPisPositive(scip, -obj) )
15043 {
15044 /* making the variable as small as possible does not increase the objective:
15045 * check if all down locks of the variables are due to linear constraints;
15046 * if variable is cost neutral and only upper bounded non-positively or negative largest bound to make
15047 * constraints redundant is huge, we better do nothing for numerical reasons
15048 */
15051 && !SCIPisHugeValue(scip, -redlb[v])
15052 && redlb[v] < SCIPvarGetUbGlobal(var) )
15053 {
15054 SCIP_Real ub;
15055
15056 /* if x_v >= redlb[v], we can always round x_v down to x_v == redlb[v] without violating any constraint
15057 * -> tighten upper bound to x_v <= redlb[v]
15058 */
15059 SCIPdebugMsg(scip, "variable <%s> only locked down in linear constraints: dual presolve <%s>[%.15g,%.15g] <= %.15g\n",
15061 redlb[v]);
15062 SCIP_CALL( SCIPtightenVarUb(scip, var, redlb[v], FALSE, &infeasible, &tightened) );
15063 assert(!infeasible);
15064
15065 ub = SCIPvarGetUbGlobal(var);
15066 redub[v] = MIN(redub[v], ub);
15067 if( tightened )
15068 (*nchgbds)++;
15069 }
15070 }
15071 if( !SCIPisPositive(scip, obj) )
15072 {
15073 /* making the variable as large as possible does not increase the objective:
15074 * check if all up locks of the variables are due to linear constraints;
15075 * if variable is cost neutral and only lower bounded non-negatively or positive smallest bound to make
15076 * constraints redundant is huge, we better do nothing for numerical reasons
15077 */
15080 && !SCIPisHugeValue(scip, redub[v])
15081 && redub[v] > SCIPvarGetLbGlobal(var) )
15082 {
15083 SCIP_Real lb;
15084
15085 /* if x_v <= redub[v], we can always round x_v up to x_v == redub[v] without violating any constraint
15086 * -> tighten lower bound to x_v >= redub[v]
15087 */
15088 SCIPdebugMsg(scip, "variable <%s> only locked up in linear constraints: dual presolve <%s>[%.15g,%.15g] >= %.15g\n",
15090 redub[v]);
15091 SCIP_CALL( SCIPtightenVarLb(scip, var, redub[v], FALSE, &infeasible, &tightened) );
15092 assert(!infeasible);
15093
15094 lb = SCIPvarGetLbGlobal(var);
15095 redlb[v] = MAX(redlb[v], lb);
15096 if( tightened )
15097 (*nchgbds)++;
15098 }
15099 }
15100 }
15101
15102 /* upgrade continuous variables to implicit integers */
15103 for( v = nintvars - nbinvars; v < nvars; ++v )
15104 {
15105 SCIP_VAR* var;
15106 SCIP_Bool infeasible;
15107
15108 var = vars[v];
15109 assert(var != NULL);
15110
15114 assert(0 <= v - nintvars + nbinvars && v - nintvars + nbinvars < ncontvars);
15115
15116 /* we can only conclude implicit integrality if the variable appears in no other constraint */
15117 if( isimplint[v - nintvars + nbinvars]
15119 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v] )
15120 {
15121 /* since we locally copied the variable array we can change the variable type immediately */
15123
15124 if( infeasible )
15125 {
15126 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
15127 *cutoff = TRUE;
15128
15129 break;
15130 }
15131
15132 SCIPdebugMsg(scip, "dual presolve: converting continuous variable <%s>[%g,%g] to implicit integer\n",
15134 }
15135 }
15136
15137 /* free temporary memory */
15140 SCIPfreeBufferArray(scip, &nlocksup);
15141 SCIPfreeBufferArray(scip, &nlocksdown);
15144
15146
15147 return SCIP_OKAY;
15148}
15149
15150/** helper function to enforce constraints */
15151static
15153 SCIP* scip, /**< SCIP data structure */
15154 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
15155 SCIP_CONS** conss, /**< constraints to process */
15156 int nconss, /**< number of constraints */
15157 int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
15158 SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
15159 SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
15160 )
15161{
15162 SCIP_CONSHDLRDATA* conshdlrdata;
15163 SCIP_Bool checkrelmaxabs;
15164 SCIP_Bool violated;
15165 SCIP_Bool cutoff = FALSE;
15166 int c;
15167
15168 assert(scip != NULL);
15169 assert(conshdlr != NULL);
15171 assert(result != NULL);
15172
15173 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15174 assert(conshdlrdata != NULL);
15175
15176 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
15177
15178 SCIPdebugMsg(scip, "Enforcement method of linear constraints for %s solution\n", sol == NULL ? "LP" : "relaxation");
15179
15180 /* check for violated constraints
15181 * LP is processed at current node -> we can add violated linear constraints to the SCIP_LP
15182 */
15184
15185 /* check all useful linear constraints for feasibility */
15186 for( c = 0; c < nusefulconss; ++c )
15187 {
15188 SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15189
15190 if( violated )
15191 {
15192 /* insert LP row as cut */
15193 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15194 if ( cutoff )
15196 else
15198 }
15199 }
15200
15201 /* check all obsolete linear constraints for feasibility */
15202 for( c = nusefulconss; c < nconss && *result == SCIP_FEASIBLE; ++c )
15203 {
15204 SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15205
15206 if( violated )
15207 {
15208 /* insert LP row as cut */
15209 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15210 if ( cutoff )
15212 else
15214 }
15215 }
15216
15217 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
15218
15219 return SCIP_OKAY;
15220}
15221
15222/*
15223 * Callback methods of constraint handler
15224 */
15225
15226/** copy method for constraint handler plugins (called when SCIP copies plugins) */
15227static
15229{ /*lint --e{715}*/
15230 assert(scip != NULL);
15231 assert(conshdlr != NULL);
15233
15234 /* call inclusion method of constraint handler */
15236
15237 *valid = TRUE;
15238
15239 return SCIP_OKAY;
15240}
15241
15242/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
15243static
15245{ /*lint --e{715}*/
15246 SCIP_CONSHDLRDATA* conshdlrdata;
15247
15248 assert(scip != NULL);
15249 assert(conshdlr != NULL);
15251
15252 /* free constraint handler data */
15253 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15254 assert(conshdlrdata != NULL);
15255
15256 conshdlrdataFree(scip, &conshdlrdata);
15257
15258 SCIPconshdlrSetData(conshdlr, NULL);
15259
15260 return SCIP_OKAY;
15261}
15262
15263
15264/** initialization method of constraint handler (called after problem was transformed) */
15265static
15267{
15268 SCIP_CONSHDLRDATA* conshdlrdata;
15269 int c;
15270
15271 assert(scip != NULL);
15272
15273 /* check for event handler */
15274 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15275 assert(conshdlrdata != NULL);
15276 assert(conshdlrdata->eventhdlr != NULL);
15277 assert(nconss == 0 || conss != NULL);
15278
15279 conshdlrdata->naddconss = 0;
15280
15281 /* catch events for the constraints */
15282 for( c = 0; c < nconss; ++c )
15283 {
15284 /* catch all events */
15285 SCIP_CALL( consCatchAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15286 }
15287
15288 return SCIP_OKAY;
15289}
15290
15291
15292/** deinitialization method of constraint handler (called before transformed problem is freed) */
15293static
15295{
15296 SCIP_CONSHDLRDATA* conshdlrdata;
15297 int c;
15298
15299 assert(scip != NULL);
15300
15301 /* check for event handler */
15302 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15303 assert(conshdlrdata != NULL);
15304 assert(conshdlrdata->eventhdlr != NULL);
15305
15306 /* drop events for the constraints */
15307 for( c = nconss - 1; c >= 0; --c )
15308 {
15309 SCIP_CONSDATA* consdata;
15310
15311 consdata = SCIPconsGetData(conss[c]);
15312 assert(consdata != NULL);
15313
15314 if( consdata->eventdata != NULL )
15315 {
15316 /* drop all events */
15317 SCIP_CALL( consDropAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15318 assert(consdata->eventdata == NULL);
15319 }
15320 }
15321
15322 return SCIP_OKAY;
15323}
15324
15325/** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15326static
15327SCIP_Bool isRangedRow(
15328 SCIP* scip, /**< SCIP data structure */
15329 SCIP_Real lhs, /**< left hand side */
15330 SCIP_Real rhs /**< right hand side */
15331 )
15332{
15333 assert(scip != NULL);
15334
15335 return !(SCIPisEQ(scip, lhs, rhs) || SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs) );
15336}
15337
15338/** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15339static
15341 SCIP* scip, /**< SCIP data structure */
15342 SCIP_Real x /**< value */
15343 )
15344{
15345 assert(scip != NULL);
15346
15347 return (!SCIPisInfinity(scip, x) && !SCIPisNegative(scip, x) && SCIPisIntegral(scip, x));
15348}
15349
15350/** performs linear constraint type classification as used for MIPLIB
15351 *
15352 * iterates through all linear constraints and stores relevant statistics in the linear constraint statistics \p linconsstats.
15353 *
15354 * @note only constraints are iterated that belong to the linear constraint handler. If the problem has been presolved already,
15355 * constraints that were upgraded to more special types such as, e.g., varbound constraints, will not be shown correctly anymore.
15356 * Similarly, if specialized constraints were created through the API, these are currently not present.
15357 */
15359 SCIP* scip, /**< SCIP data structure */
15360 SCIP_LINCONSSTATS* linconsstats /**< linear constraint type classification */
15361 )
15362{
15363 int c;
15364 SCIP_CONSHDLR* conshdlr;
15365 SCIP_CONS** conss;
15366 int nconss;
15367
15368 assert(scip != NULL);
15370 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
15371 assert(conshdlr != NULL);
15372
15374 {
15375 conss = SCIPgetConss(scip);
15376 nconss = SCIPgetNConss(scip);
15377 }
15378 else
15379 {
15380 conss = SCIPconshdlrGetConss(conshdlr);
15381 nconss = SCIPconshdlrGetNConss(conshdlr);
15382 }
15383
15384 /* reset linear constraint type classification */
15386
15387 /* loop through all constraints */
15388 for( c = 0; c < nconss; c++ )
15389 {
15390 SCIP_CONS* cons;
15391 SCIP_CONSDATA* consdata;
15392 SCIP_Real lhs;
15393 SCIP_Real rhs;
15394 int i;
15395
15396 /* get constraint */
15397 cons = conss[c];
15398 assert(cons != NULL);
15399
15400 /* skip constraints that are not handled by the constraint handler */
15401 if( SCIPconsGetHdlr(cons) != conshdlr )
15402 continue;
15403
15404 /* get constraint data */
15405 consdata = SCIPconsGetData(cons);
15406 assert(consdata != NULL);
15407 rhs = consdata->rhs;
15408 lhs = consdata->lhs;
15409
15410 /* merge multiples and delete variables with zero coefficient */
15411 SCIP_CALL( mergeMultiples(scip, cons) );
15412 for( i = 0; i < consdata->nvars; i++ )
15413 {
15414 assert(!SCIPisZero(scip, consdata->vals[i]));
15415 }
15416
15417 /* is constraint of type SCIP_CONSTYPE_EMPTY? */
15418 if( consdata->nvars == 0 )
15419 {
15420 SCIPdebugMsg(scip, "classified as EMPTY: ");
15423
15424 continue;
15425 }
15426
15427 /* is constraint of type SCIP_CONSTYPE_FREE? */
15428 if( SCIPisInfinity(scip, rhs) && SCIPisInfinity(scip, -lhs) )
15429 {
15430 SCIPdebugMsg(scip, "classified as FREE: ");
15433
15434 continue;
15435 }
15436
15437 /* is constraint of type SCIP_CONSTYPE_SINGLETON? */
15438 if( consdata->nvars == 1 )
15439 {
15440 SCIPdebugMsg(scip, "classified as SINGLETON: ");
15443
15444 continue;
15445 }
15446
15447 /* is constraint of type SCIP_CONSTYPE_AGGREGATION? */
15448 if( consdata->nvars == 2 && SCIPisEQ(scip, lhs, rhs) )
15449 {
15450 SCIPdebugMsg(scip, "classified as AGGREGATION: ");
15453
15454 continue;
15455 }
15456
15457 /* is constraint of type SCIP_CONSTYPE_{VARBOUND,PRECEDENCE}? */
15458 if( consdata->nvars == 2 )
15459 {
15460 SCIP_LINCONSTYPE constype;
15461
15462 /* precedence constraints have the same coefficient, but with opposite sign for the same variable type */
15463 if( SCIPisEQ(scip, consdata->vals[0], -consdata->vals[1])
15464 && SCIPvarGetType(consdata->vars[0]) == SCIPvarGetType(consdata->vars[1]))
15465 {
15466 constype = SCIP_LINCONSTYPE_PRECEDENCE;
15467 SCIPdebugMsg(scip, "classified as PRECEDENCE: ");
15468 }
15469 else
15470 {
15471 constype = SCIP_LINCONSTYPE_VARBOUND;
15472 SCIPdebugMsg(scip, "classified as VARBOUND: ");
15473 }
15475
15476 SCIPlinConsStatsIncTypeCount(linconsstats, constype, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15477
15478 continue;
15479 }
15480
15481 /* is constraint of type SCIP_CONSTYPE_{SETPARTITION, SETPACKING, SETCOVERING, CARDINALITY, INVKNAPSACK}? */
15482 {
15483 SCIP_Real scale;
15484 SCIP_Real b;
15485 SCIP_Bool unmatched;
15486 int nnegbinvars;
15487
15488 unmatched = FALSE;
15489 nnegbinvars = 0;
15490
15491 scale = REALABS(consdata->vals[0]);
15492
15493 /* scan through variables and detect if all variables are binary and have a coefficient +/-1 */
15494 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15495 {
15497 unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15498 unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15499 unmatched = unmatched || !SCIPisEQ(scip, REALABS(consdata->vals[i]), scale);
15500
15501 if( consdata->vals[i] < 0.0 )
15502 nnegbinvars++;
15503 }
15504
15505 if( !unmatched )
15506 {
15507 if( SCIPisEQ(scip, lhs, rhs) )
15508 {
15509 b = rhs/scale + nnegbinvars;
15510 if( SCIPisEQ(scip, 1.0, b) )
15511 {
15512 SCIPdebugMsg(scip, "classified as SETPARTITION: ");
15515
15516 continue;
15517 }
15518 else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15519 {
15520 SCIPdebugMsg(scip, "classified as CARDINALITY: ");
15523
15524 continue;
15525 }
15526 }
15527
15528 /* compute right hand side divided by scale */
15529 if( !SCIPisInfinity(scip, rhs) )
15530 b = rhs/scale + nnegbinvars;
15531 else
15532 b = SCIPinfinity(scip);
15533
15534 if( SCIPisEQ(scip, 1.0, b) )
15535 {
15536 SCIPdebugMsg(scip, "classified as SETPACKING: ");
15539
15540 /* relax right hand side to prevent further classifications */
15541 rhs = SCIPinfinity(scip);
15542 }
15543 else if( !SCIPisInfinity(scip, b) && SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15544 {
15545 SCIPdebugMsg(scip, "classified as INVKNAPSACK: ");
15547
15549
15550 /* relax right hand side to prevent further classifications */
15551 rhs = SCIPinfinity(scip);
15552 }
15553
15554 if( !SCIPisInfinity(scip, lhs) )
15555 b = lhs/scale + nnegbinvars;
15556 else
15557 b = SCIPinfinity(scip);
15558
15559 if( SCIPisEQ(scip, 1.0, b) )
15560 {
15561 SCIPdebugMsg(scip, "classified as SETCOVERING: ");
15564
15565 /* relax left hand side to prevent further classifications */
15566 lhs = -SCIPinfinity(scip);
15567 }
15568
15569 /* if both sides are infinite at this point, no further classification is necessary for this constraint */
15570 if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
15571 continue;
15572 }
15573 }
15574
15575 /* is constraint of type SCIP_CONSTYPE_{EQKNAPSACK, BINPACKING, KNAPSACK}? */
15576 /* @todo If coefficients or rhs are not integral, we currently do not check
15577 * if the constraint could be scaled (finitely), such that they are.
15578 */
15579 {
15580 SCIP_Real b;
15581 SCIP_Bool unmatched;
15582
15583 b = rhs;
15584 unmatched = FALSE;
15585 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15586 {
15588 unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15589 unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15590 unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15591
15592 if( SCIPisNegative(scip, consdata->vals[i]) )
15593 b -= consdata->vals[i];
15594 }
15596
15597 if( !unmatched )
15598 {
15599 if( SCIPisEQ(scip, lhs, rhs) )
15600 {
15601 SCIPdebugMsg(scip, "classified as EQKNAPSACK: ");
15603
15605
15606 continue;
15607 }
15608 else
15609 {
15610 SCIP_Bool matched;
15611
15612 matched = FALSE;
15613 for( i = 0; i < consdata->nvars && !matched; i++ )
15614 {
15615 matched = matched || SCIPisEQ(scip, b, REALABS(consdata->vals[i]));
15616 }
15617
15618 SCIPdebugMsg(scip, "classified as %s: ", matched ? "BINPACKING" : "KNAPSACK");
15621 }
15622
15623 /* check if finite left hand side allows for a second classification, relax already used right hand side */
15624 if( SCIPisInfinity(scip, -lhs) )
15625 continue;
15626 else
15627 rhs = SCIPinfinity(scip);
15628 }
15629 }
15630
15631 /* is constraint of type SCIP_CONSTYPE_{INTKNAPSACK}? */
15632 {
15633 SCIP_Real b;
15634 SCIP_Bool unmatched;
15635
15636 unmatched = FALSE;
15637
15638 b = rhs;
15640
15641 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15642 {
15645 unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15646 unmatched = unmatched || SCIPisNegative(scip, consdata->vals[i]);
15647 }
15648
15649 if( !unmatched )
15650 {
15651 SCIPdebugMsg(scip, "classified as INTKNAPSACK: ");
15654
15655 /* check if finite left hand side allows for a second classification, relax already used right hand side */
15656 if( SCIPisInfinity(scip, -lhs) )
15657 continue;
15658 else
15659 rhs = SCIPinfinity(scip);
15660 }
15661 }
15662
15663 /* is constraint of type SCIP_CONSTYPE_{MIXEDBINARY}? */
15664 {
15665 SCIP_Bool unmatched;
15666
15667 unmatched = FALSE;
15668 for( i = 0; i < consdata->nvars && !unmatched; i++ )
15669 {
15670 if( SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS
15671 && (SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0)
15672 || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0)) )
15673 unmatched = TRUE;
15674 }
15675
15676 if( !unmatched )
15677 {
15678 SCIPdebugMsg(scip, "classified as MIXEDBINARY (%d): ", isRangedRow(scip, lhs, rhs) ? 2 : 1);
15681
15682 continue;
15683 }
15684 }
15685
15686 /* no special structure detected */
15687 SCIPdebugMsg(scip, "classified as GENERAL: ");
15690 }
15691
15692 return SCIP_OKAY;
15693}
15694
15695
15696/** presolving deinitialization method of constraint handler (called after presolving has been finished) */
15697static
15699{ /*lint --e{715}*/
15700 int c;
15701#ifdef SCIP_STATISTIC
15702 SCIP_CONSHDLRDATA* conshdlrdata;
15703 int ngoodconss;
15704 int nallconss;
15705#endif
15706
15707 /* delete all linear constraints that were upgraded to a more specific constraint type;
15708 * make sure, only active variables remain in the remaining constraints
15709 */
15710 assert(scip != NULL);
15711
15712#ifdef SCIP_STATISTIC
15713 /* count number of well behaved linear constraints */
15714 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15715 assert(conshdlrdata != NULL);
15716
15717 ngoodconss = 0;
15718 nallconss = 0;
15719
15720 for( c = 0; c < nconss; ++c )
15721 {
15722 SCIP_CONSDATA* consdata;
15723
15724 if( SCIPconsIsDeleted(conss[c]) )
15725 continue;
15726
15727 consdata = SCIPconsGetData(conss[c]);
15728 assert(consdata != NULL);
15729
15730 if( consdata->upgraded )
15731 continue;
15732
15733 nallconss++;
15734
15736
15737 if( SCIPisLT(scip, consdata->maxactdelta, conshdlrdata->maxeasyactivitydelta) )
15738 ngoodconss++;
15739 }
15740 if( nallconss )
15741 {
15742 SCIPstatisticMessage("below threshold: %d / %d ratio= %g\n", ngoodconss, nallconss, (100.0 * ngoodconss / nallconss));
15743 }
15744#endif
15745
15746 for( c = 0; c < nconss; ++c )
15747 {
15748 SCIP_CONSDATA* consdata;
15749
15750 if( SCIPconsIsDeleted(conss[c]) )
15751 continue;
15752
15753 consdata = SCIPconsGetData(conss[c]);
15754 assert(consdata != NULL);
15755
15756 if( consdata->upgraded )
15757 {
15758 /* this is no problem reduction, because the upgraded constraint was added to the problem before, and the
15759 * (redundant) linear constraint was only kept in order to support presolving the the linear constraint handler
15760 */
15761 SCIP_CALL( SCIPdelCons(scip, conss[c]) );
15762 }
15763 else
15764 {
15765 /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */
15766 SCIP_CALL( applyFixings(scip, conss[c], NULL) );
15767 }
15768 }
15769
15770 return SCIP_OKAY;
15771}
15772
15773/** solving process initialization method of constraint handler */
15774static
15776{ /*lint --e{715}*/
15777 /* add nlrow representation to NLP, if NLP had been constructed */
15779 {
15780 int c;
15781 for( c = 0; c < nconss; ++c )
15782 {
15783 SCIP_CALL( addNlrow(scip, conss[c]) );
15784 }
15785 }
15786
15787 return SCIP_OKAY;
15788}
15789
15790/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
15791static
15793{ /*lint --e{715}*/
15794 int c;
15795
15796 assert(scip != NULL);
15797
15798 /* release the rows and nlrows of all constraints */
15799 for( c = 0; c < nconss; ++c )
15800 {
15801 SCIP_CONSDATA* consdata;
15802
15803 consdata = SCIPconsGetData(conss[c]);
15804 assert(consdata != NULL);
15805
15806 if( consdata->row != NULL )
15807 {
15808 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
15809 }
15810
15811 if( consdata->nlrow != NULL )
15812 {
15813 SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
15814 }
15815 }
15816
15817 /* if this is a restart, convert cutpool rows into linear constraints */
15818 if( restart )
15819 {
15820 int ncutsadded;
15821
15822 ncutsadded = 0;
15823
15824 /* create out of all active cuts in cutpool linear constraints */
15825 SCIP_CALL( SCIPconvertCutsToConss(scip, NULL, NULL, TRUE, &ncutsadded) );
15826
15827 if( ncutsadded > 0 )
15828 {
15830 "(restart) converted %d cuts from the global cut pool into linear constraints\n", ncutsadded);
15831 /* an extra blank line should be printed separately since the buffer message handler only handles up to one
15832 * line correctly
15833 */
15835 }
15836 }
15837
15838 return SCIP_OKAY;
15839}
15840
15841
15842/** constraint activation notification method of constraint handler */
15843static
15845{ /*lint --e{715}*/
15846 assert(cons != NULL);
15847
15849 {
15850 SCIP_CALL( addNlrow(scip, cons) );
15851 }
15852
15853 return SCIP_OKAY;
15854}
15855
15856/** constraint deactivation notification method of constraint handler */
15857static
15859{ /*lint --e{715}*/
15860 SCIP_CONSDATA* consdata;
15861
15862 assert(scip != NULL);
15863 assert(conshdlr != NULL);
15865 assert(cons != NULL );
15866
15867 /* get constraint data */
15868 consdata = SCIPconsGetData(cons);
15869 assert(consdata != NULL);
15870
15871 if( SCIPconsIsDeleted(cons) )
15872 {
15873 SCIP_CONSHDLRDATA* conshdlrdata;
15874
15875 /* check for event handler */
15876 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15877 assert(conshdlrdata != NULL);
15878 assert(conshdlrdata->eventhdlr != NULL);
15879
15880 /* free event data */
15881 if( consdata->eventdata != NULL )
15882 {
15883 /* drop bound change events of variables */
15884 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15885 }
15886 assert(consdata->eventdata == NULL);
15887 }
15888
15889 /* remove row from NLP, if still in solving
15890 * if we are in exitsolve, the whole NLP will be freed anyway
15891 */
15892 if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
15893 {
15894 SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
15895 }
15896
15897 return SCIP_OKAY;
15898}
15899
15900
15901/** frees specific constraint data */
15902static
15904{ /*lint --e{715}*/
15905 assert(scip != NULL);
15906 assert(conshdlr != NULL);
15908
15909 if( (*consdata)->eventdata != NULL )
15910 {
15911 SCIP_CONSHDLRDATA* conshdlrdata;
15912
15913 conshdlrdata = SCIPconshdlrGetData(conshdlr);
15914 assert(conshdlrdata != NULL);
15915
15916 /* drop all events */
15917 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15918 assert((*consdata)->eventdata == NULL);
15919 }
15920
15921 /* free linear constraint */
15922 SCIP_CALL( consdataFree(scip, consdata) );
15923
15924 return SCIP_OKAY;
15925}
15926
15927
15928/** transforms constraint data into data belonging to the transformed problem */
15929static
15931{ /*lint --e{715}*/
15934
15935 /*debugMsg(scip, "Trans method of linear constraints\n");*/
15936
15937 assert(scip != NULL);
15938 assert(conshdlr != NULL);
15943
15946 assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
15947
15948 /* create linear constraint data for target constraint */
15950
15951#ifndef NDEBUG
15952 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
15954 {
15955 int n;
15956 for(n = targetdata->nvars - 1; n >= 0; --n )
15958 }
15959#endif
15960
15961 /* create target constraint */
15967
15968 return SCIP_OKAY;
15969}
15970
15971
15972/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
15973static
15975{ /*lint --e{715}*/
15976 int c;
15977
15978 assert(scip != NULL);
15980
15981 *infeasible = FALSE;
15982
15983 for( c = 0; c < nconss && !(*infeasible); ++c )
15984 {
15985 assert(SCIPconsIsInitial(conss[c]));
15986 SCIP_CALL( addRelaxation(scip, conss[c], infeasible) );
15987 }
15988
15989 return SCIP_OKAY;
15990}
15991
15992
15993/** separation method of constraint handler for LP solutions */
15994static
15996{ /*lint --e{715}*/
15997 SCIP_CONSHDLRDATA* conshdlrdata;
15998 SCIP_Real loclowerbound;
15999 SCIP_Real glblowerbound;
16000 SCIP_Real cutoffbound;
16001 SCIP_Real maxbound;
16002 SCIP_Bool separatecards;
16003 SCIP_Bool cutoff;
16004 int c;
16005 int depth;
16006 int nrounds;
16007 int maxsepacuts;
16008 int ncuts;
16009
16010 assert(scip != NULL);
16011 assert(conshdlr != NULL);
16013 assert(result != NULL);
16014
16015 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16016 assert(conshdlrdata != NULL);
16019
16020 /*debugMsg(scip, "Sepa method of linear constraints\n");*/
16021
16023
16024 /* only call the separator a given number of times at each node */
16025 if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
16026 || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
16027 return SCIP_OKAY;
16028
16029 /* get the maximal number of cuts allowed in a separation round */
16030 maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
16031
16032 /* check if we want to produce knapsack cardinality cuts at this node */
16035 cutoffbound = SCIPgetCutoffbound(scip);
16036 maxbound = glblowerbound + conshdlrdata->maxcardbounddist * (cutoffbound - glblowerbound);
16039
16041 ncuts = 0;
16042 cutoff = FALSE;
16043
16044 /* check all useful linear constraints for feasibility */
16045 for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
16046 {
16047 /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
16048 SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, NULL, separatecards, conshdlrdata->separateall, &ncuts, &cutoff) );
16049 }
16050
16051 /* adjust return value */
16052 if( cutoff )
16054 else if( ncuts > 0 )
16056
16057 /* combine linear constraints to get more cuts */
16058 /**@todo further cuts of linear constraints */
16059
16060 return SCIP_OKAY;
16061}
16062
16063
16064/** separation method of constraint handler for arbitrary primal solutions */
16065static
16067{ /*lint --e{715}*/
16068 SCIP_CONSHDLRDATA* conshdlrdata;
16069 int c;
16070 int depth;
16071 int nrounds;
16072 int maxsepacuts;
16073 int ncuts;
16074 SCIP_Bool cutoff;
16075
16076 assert(scip != NULL);
16077 assert(conshdlr != NULL);
16079 assert(result != NULL);
16080
16081 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16082 assert(conshdlrdata != NULL);
16085
16086 /*debugMsg(scip, "Sepa method of linear constraints\n");*/
16087
16089
16090 /* only call the separator a given number of times at each node */
16091 if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
16092 || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
16093 return SCIP_OKAY;
16094
16095 /* get the maximal number of cuts allowed in a separation round */
16096 maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
16097
16099 ncuts = 0;
16100 cutoff = FALSE;
16101
16102 /* check all useful linear constraints for feasibility */
16103 for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
16104 {
16105 /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
16106 SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, sol, TRUE, conshdlrdata->separateall, &ncuts, &cutoff) );
16107 }
16108
16109 /* adjust return value */
16110 if( cutoff )
16112 else if( ncuts > 0 )
16114
16115 /* combine linear constraints to get more cuts */
16116 /**@todo further cuts of linear constraints */
16117
16118 return SCIP_OKAY;
16119}
16120
16121
16122/** constraint enforcing method of constraint handler for LP solutions */
16123static
16125{ /*lint --e{715}*/
16126 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
16127
16128 return SCIP_OKAY;
16129}
16130
16131/** constraint enforcing method of constraint handler for relaxation solutions */
16132static
16134{ /*lint --e{715}*/
16135 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
16136
16137 return SCIP_OKAY;
16138}
16139
16140/** constraint enforcing method of constraint handler for pseudo solutions */
16141static
16143{ /*lint --e{715}*/
16144 SCIP_CONSHDLRDATA* conshdlrdata;
16145 SCIP_Bool checkrelmaxabs;
16146 SCIP_Bool violated;
16147 int c;
16148
16149 assert(scip != NULL);
16150 assert(conshdlr != NULL);
16152 assert(result != NULL);
16153
16154 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16155 assert(conshdlrdata != NULL);
16156
16157 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16158
16159 SCIPdebugMsg(scip, "Enfops method of linear constraints\n");
16160
16161 /* if the solution is infeasible anyway due to objective value, skip the enforcement */
16162 if( objinfeasible )
16163 {
16164 SCIPdebugMsg(scip, "-> pseudo solution is objective infeasible, return.\n");
16165
16167 return SCIP_OKAY;
16168 }
16169
16170 /* check all linear constraints for feasibility */
16171 violated = FALSE;
16172 for( c = 0; c < nconss && !violated; ++c )
16173 {
16174 SCIP_CALL( checkCons(scip, conss[c], NULL, TRUE, checkrelmaxabs, &violated) );
16175 }
16176
16177 if( violated )
16179 else
16181
16182 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
16183
16184 return SCIP_OKAY;
16185}
16186
16187
16188/** feasibility check method of constraint handler for integral solutions */
16189static
16191{ /*lint --e{715}*/
16192 SCIP_CONSHDLRDATA* conshdlrdata;
16193 SCIP_Bool checkrelmaxabs;
16194 int c;
16195
16196 assert(scip != NULL);
16197 assert(conshdlr != NULL);
16199 assert(result != NULL);
16200
16202
16203 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16204 assert(conshdlrdata != NULL);
16205
16206 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16207
16208 /*debugMsg(scip, "Check method of linear constraints\n");*/
16209
16210 /* check all linear constraints for feasibility */
16211 for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
16212 {
16213 SCIP_Bool violated = FALSE;
16214 SCIP_CALL( checkCons(scip, conss[c], sol, checklprows, checkrelmaxabs, &violated) );
16215
16216 if( violated )
16217 {
16219
16220 if( printreason )
16221 {
16222 SCIP_CONSDATA* consdata;
16223 SCIP_Real activity;
16224
16225 consdata = SCIPconsGetData(conss[c]);
16226 assert( consdata != NULL);
16227
16228 activity = consdataGetActivity(scip, consdata, sol);
16229
16230 SCIP_CALL( consPrintConsSol(scip, conss[c], sol, NULL ) );
16231 SCIPinfoMessage(scip, NULL, ";\n");
16232
16233 if( activity == SCIP_INVALID ) /*lint !e777*/
16234 SCIPinfoMessage(scip, NULL, "activity invalid due to positive and negative infinity contributions\n");
16235 else if( SCIPisFeasLT(scip, activity, consdata->lhs) )
16236 SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - activity);
16237 else if( SCIPisFeasGT(scip, activity, consdata->rhs) )
16238 SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - consdata->rhs);
16239 }
16240 }
16241 }
16242
16243 return SCIP_OKAY;
16244}
16245
16246
16247/** domain propagation method of constraint handler */
16248static
16250{ /*lint --e{715}*/
16251 SCIP_CONSHDLRDATA* conshdlrdata;
16252 SCIP_Bool rangedrowpropagation = FALSE;
16253 SCIP_Bool tightenbounds;
16254 SCIP_Bool cutoff;
16255
16256 int nchgbds;
16257 int i;
16258
16259 assert(scip != NULL);
16260 assert(conshdlr != NULL);
16262 assert(result != NULL);
16263
16264 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16265 assert(conshdlrdata != NULL);
16266
16267 /*debugMsg(scip, "Prop method of linear constraints\n");*/
16268
16269 /* check, if we want to tighten variable's bounds (in probing, we always want to tighten the bounds) */
16270 if( SCIPinProbing(scip) )
16271 tightenbounds = TRUE;
16272 else
16273 {
16274 int depth;
16275 int propfreq;
16276 int tightenboundsfreq;
16277 int rangedrowfreq;
16278
16280 propfreq = SCIPconshdlrGetPropFreq(conshdlr);
16281 tightenboundsfreq = propfreq * conshdlrdata->tightenboundsfreq;
16282 tightenbounds = (conshdlrdata->tightenboundsfreq >= 0)
16283 && ((tightenboundsfreq == 0 && depth == 0) || (tightenboundsfreq >= 1 && (depth % tightenboundsfreq == 0)));
16284
16285 /* check if we want to do ranged row propagation */
16286 rangedrowpropagation = conshdlrdata->rangedrowpropagation;
16287 rangedrowpropagation = rangedrowpropagation && !SCIPinRepropagation(scip);
16288 rangedrowpropagation = rangedrowpropagation && (depth <= conshdlrdata->rangedrowmaxdepth);
16289 rangedrowfreq = propfreq * conshdlrdata->rangedrowfreq;
16290 rangedrowpropagation = rangedrowpropagation && (conshdlrdata->rangedrowfreq >= 0)
16291 && ((rangedrowfreq == 0 && depth == 0) || (rangedrowfreq >= 1 && (depth % rangedrowfreq == 0)));
16292 }
16293
16294 cutoff = FALSE;
16295 nchgbds = 0;
16296
16297 /* process constraints marked for propagation */
16298 for( i = 0; i < nmarkedconss && !cutoff; i++ )
16299 {
16301 SCIP_CALL( propagateCons(scip, conss[i], tightenbounds, rangedrowpropagation,
16302 conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, &nchgbds) );
16303 }
16304
16305 /* adjust result code */
16306 if( cutoff )
16308 else if( nchgbds > 0 )
16310 else
16312
16313 return SCIP_OKAY;
16314}
16315
16316
16317#define MAXCONSPRESOLROUNDS 10
16318/** presolving method of constraint handler */
16319static
16321{ /*lint --e{715}*/
16322 SCIP_CONSHDLRDATA* conshdlrdata;
16323 SCIP_CONS* cons;
16324 SCIP_CONSDATA* consdata;
16325 SCIP_Real minactivity;
16326 SCIP_Real maxactivity;
16327 SCIP_Bool minactisrelax;
16328 SCIP_Bool maxactisrelax;
16329 SCIP_Bool isminsettoinfinity;
16330 SCIP_Bool ismaxsettoinfinity;
16331 SCIP_Bool cutoff;
16332 int oldnfixedvars;
16333 int oldnaggrvars;
16334 int oldnchgbds;
16335 int oldndelconss;
16336 int oldnupgdconss;
16337 int oldnchgcoefs;
16338 int oldnchgsides;
16339 int firstchange;
16340 int firstupgradetry;
16341 int c;
16342
16343 assert(scip != NULL);
16344 assert(conshdlr != NULL);
16346 assert(result != NULL);
16347
16348 /*debugMsg(scip, "Presol method of linear constraints\n");*/
16349
16350 /* remember old preprocessing counters */
16351 cutoff = FALSE;
16352 oldnfixedvars = *nfixedvars;
16353 oldnaggrvars = *naggrvars;
16354 oldnchgbds = *nchgbds;
16355 oldndelconss = *ndelconss;
16356 oldnupgdconss = *nupgdconss;
16357 oldnchgcoefs = *nchgcoefs;
16358 oldnchgsides = *nchgsides;
16359
16360 /* get constraint handler data */
16361 conshdlrdata = SCIPconshdlrGetData(conshdlr);
16362 assert(conshdlrdata != NULL);
16363
16364 /* process single constraints */
16367 for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
16368 {
16369 int npresolrounds;
16370 SCIP_Bool infeasible;
16371
16372 infeasible = FALSE;
16373
16374 cons = conss[c];
16375 assert(SCIPconsIsActive(cons));
16376 consdata = SCIPconsGetData(cons);
16377 assert(consdata != NULL);
16378
16379 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
16380 if( SCIPisEQ(scip, consdata->rhs, consdata->lhs) )
16381 {
16382 consdata->lhs = consdata->rhs;
16383 assert(consdata->row == NULL);
16384 }
16385
16386 if( consdata->eventdata == NULL )
16387 {
16388 /* catch bound change events of variables */
16389 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
16390 assert(consdata->eventdata != NULL);
16391 }
16392
16393 /* constraint should not be already presolved in the initial round */
16395 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || consdata->boundstightened == 0);
16396 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->presolved);
16397 assert(!SCIPconsIsMarkedPropagate(cons) || !consdata->presolved);
16398
16399 /* incorporate fixings and aggregations in constraint */
16400 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
16401
16402 if( infeasible )
16403 {
16404 SCIPdebugMsg(scip, " -> infeasible fixing\n");
16405 cutoff = TRUE;
16406 break;
16407 }
16408
16409 assert(consdata->removedfixings);
16410
16411 /* we can only presolve linear constraints, that are not modifiable */
16412 if( SCIPconsIsModifiable(cons) )
16413 continue;
16414
16415 /* remember the first changed constraint to begin the next aggregation round with */
16416 if( firstchange == INT_MAX && consdata->changed )
16417 firstchange = c;
16418
16419 /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16420 if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16422
16423 /* check, if constraint is already preprocessed */
16424 if( consdata->presolved )
16425 continue;
16426
16427 assert(SCIPconsIsActive(cons));
16428
16429 SCIPdebugMsg(scip, "presolving linear constraint <%s>\n", SCIPconsGetName(cons));
16431
16432 /* apply presolving as long as possible on the single constraint (however, abort after a certain number of rounds
16433 * to avoid nearly infinite cycling due to very small bound changes)
16434 */
16435 npresolrounds = 0;
16436 while( !consdata->presolved && npresolrounds < MAXCONSPRESOLROUNDS && !SCIPisStopped(scip) )
16437 {
16438 assert(!cutoff);
16439 npresolrounds++;
16440
16441 /* mark constraint being presolved and propagated */
16442 consdata->presolved = TRUE;
16444
16445 /* normalize constraint */
16446 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
16447
16448 if( infeasible )
16449 {
16450 SCIPdebugMsg(scip, " -> infeasible normalization\n");
16451 cutoff = TRUE;
16452 break;
16453 }
16454
16455 /* tighten left and right hand side due to integrality */
16456 SCIP_CALL( tightenSides(scip, cons, nchgsides, &infeasible) );
16457
16458 if( infeasible )
16459 {
16460 SCIPdebugMsg(scip, " -> infeasibility detected during tightening sides\n");
16461 cutoff = TRUE;
16462 break;
16463 }
16464
16465 /* check bounds */
16466 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16467 {
16468 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16469 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16470 cutoff = TRUE;
16471 break;
16472 }
16473
16474 /* tighten variable's bounds */
16475 SCIP_CALL( tightenBounds(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, nchgbds) );
16476 if( cutoff )
16477 break;
16478
16479 /* check for fixed variables */
16480 SCIP_CALL( fixVariables(scip, cons, &cutoff, nfixedvars) );
16481 if( cutoff )
16482 break;
16483
16484 /* check constraint for infeasibility and redundancy */
16485 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
16487 if( SCIPisFeasGT(scip, minactivity, consdata->rhs) || SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
16488 {
16489 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16490 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16491 cutoff = TRUE;
16492 break;
16493 }
16494 else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16495 {
16496 SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16497 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16498 SCIP_CALL( SCIPdelCons(scip, cons) );
16499 assert(!SCIPconsIsActive(cons));
16500
16501 if( !consdata->upgraded )
16502 (*ndelconss)++;
16503 break;
16504 }
16505 else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisGE(scip, minactivity, consdata->lhs) )
16506 {
16507 SCIPdebugMsg(scip, "linear constraint <%s> left hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16508 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16509 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
16510 if( !consdata->upgraded )
16511 (*nchgsides)++;
16512 }
16513 else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16514 {
16515 SCIPdebugMsg(scip, "linear constraint <%s> right hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16516 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16518 if( !consdata->upgraded )
16519 (*nchgsides)++;
16520 }
16521
16522 /* handle empty constraint */
16523 if( consdata->nvars == 0 )
16524 {
16525 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16526 {
16527 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16528 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16529 cutoff = TRUE;
16530 }
16531 else
16532 {
16533 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16534 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16535 SCIP_CALL( SCIPdelCons(scip, cons) );
16536 assert(!SCIPconsIsActive(cons));
16537
16538 if( !consdata->upgraded )
16539 (*ndelconss)++;
16540 }
16541 break;
16542 }
16543
16544 /* reduce big-M coefficients, that make the constraint redundant if the variable is on a bound */
16545 SCIP_CALL( consdataTightenCoefs(scip, cons, nchgcoefs, nchgsides) );
16546
16547 /* try to simplify inequalities */
16548 if( conshdlrdata->simplifyinequalities )
16549 {
16550 SCIP_CALL( simplifyInequalities(scip, cons, nchgcoefs, nchgsides, &cutoff) );
16551
16552 if( cutoff )
16553 break;
16554 }
16555
16556 /* aggregation variable in equations */
16557 if( conshdlrdata->aggregatevariables )
16558 {
16559 SCIP_CALL( aggregateVariables(scip, cons, &cutoff, nfixedvars, naggrvars) );
16560 if( cutoff )
16561 break;
16562 }
16563 }
16564
16565 if( !cutoff && !SCIPisStopped(scip) )
16566 {
16567 /* perform ranged row propagation */
16568 if( conshdlrdata->rangedrowpropagation )
16569 {
16570 int lastnfixedvars;
16571
16572 lastnfixedvars = *nfixedvars;
16573
16574 SCIP_CALL( rangedRowPropagation(scip, cons, &cutoff, nfixedvars, nchgbds, naddconss) );
16575 if( !cutoff )
16576 {
16577 if( lastnfixedvars < *nfixedvars )
16578 {
16579 SCIP_CALL( applyFixings(scip, cons, &cutoff) );
16580 }
16581 }
16582 }
16583
16584 /* extract cliques from constraint */
16585 if( conshdlrdata->extractcliques && !cutoff && SCIPconsIsActive(cons) )
16586 {
16587 SCIP_CALL( extractCliques(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars,
16588 nfixedvars, nchgbds, &cutoff) );
16589
16590 /* check if the constraint got redundant or infeasible */
16591 if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 0 )
16592 {
16593 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16594 {
16595 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16596 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16597 cutoff = TRUE;
16598 }
16599 else
16600 {
16601 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16602 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16603 SCIP_CALL( SCIPdelCons(scip, cons) );
16604 assert(!SCIPconsIsActive(cons));
16605
16606 if( !consdata->upgraded )
16607 (*ndelconss)++;
16608 }
16609 }
16610 }
16611
16612 /* convert special equalities */
16613 if( !cutoff && SCIPconsIsActive(cons) )
16614 {
16615 SCIP_CALL( convertEquality(scip, cons, conshdlrdata, &cutoff, nfixedvars, naggrvars, ndelconss) );
16616 }
16617
16618 /* apply dual presolving for variables that appear in only one constraint */
16619 if( !cutoff && SCIPconsIsActive(cons) && conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) )
16620 {
16621 SCIP_CALL( dualPresolve(scip, conshdlrdata, cons, &cutoff, nfixedvars, naggrvars, ndelconss) );
16622 }
16623
16624 /* check if an inequality is parallel to the objective function */
16625 if( !cutoff && SCIPconsIsActive(cons) )
16626 {
16627 SCIP_CALL( checkParallelObjective(scip, cons, conshdlrdata) );
16628 }
16629
16630 /* remember the first changed constraint to begin the next aggregation round with */
16631 if( firstchange == INT_MAX && consdata->changed )
16632 firstchange = c;
16633
16634 /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16635 if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16637 }
16638
16639 /* singleton column stuffing */
16640 if( !cutoff && SCIPconsIsActive(cons) && SCIPconsIsChecked(cons) &&
16641 (conshdlrdata->singletonstuffing || conshdlrdata->singlevarstuffing) && SCIPallowStrongDualReds(scip) )
16642 {
16643 SCIP_CALL( presolStuffing(scip, cons, conshdlrdata->singletonstuffing,
16644 conshdlrdata->singlevarstuffing, &cutoff, nfixedvars, nchgbds) );
16645
16646 /* handle empty constraint */
16647 if( consdata->nvars == 0 )
16648 {
16649 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16650 {
16651 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16652 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16653 cutoff = TRUE;
16654 }
16655 else
16656 {
16657 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16658 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16659 SCIP_CALL( SCIPdelCons(scip, cons) );
16660 assert(!SCIPconsIsActive(cons));
16661
16662 if( !consdata->upgraded )
16663 (*ndelconss)++;
16664 }
16665 break;
16666 }
16667 }
16668 }
16669
16670 /* process pairs of constraints: check them for redundancy and try to aggregate them;
16671 * only apply this expensive procedure in exhaustive presolving timing
16672 */
16673 if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && (conshdlrdata->presolusehashing || conshdlrdata->presolpairwise) && !SCIPisStopped(scip) )
16674 {
16675 assert(firstchange >= 0);
16676
16677 if( firstchange < nconss && conshdlrdata->presolusehashing )
16678 {
16679 /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
16681 ndelconss, nchgsides) );
16682 }
16683
16684 if( firstchange < nconss && conshdlrdata->presolpairwise )
16685 {
16687 int nusefulconss;
16688 int firstchangenew;
16689 SCIP_Longint npaircomparisons;
16690
16691 npaircomparisons = 0;
16692 oldndelconss = *ndelconss;
16693 oldnchgsides = *nchgsides;
16694 oldnchgcoefs = *nchgcoefs;
16695
16696 /* allocate temporary memory */
16698
16699 nusefulconss = 0;
16700 firstchangenew = -1;
16701 for( c = 0; c < nconss; ++c )
16702 {
16703 /* update firstchange */
16704 if( c == firstchange )
16706
16707 /* ignore inactive and modifiable constraints */
16708 if( !SCIPconsIsActive(conss[c]) || SCIPconsIsModifiable(conss[c]) )
16709 continue;
16710
16711 usefulconss[nusefulconss] = conss[c];
16712 ++nusefulconss;
16713 }
16716
16717 for( c = firstchange; c < nusefulconss && !cutoff && !SCIPisStopped(scip); ++c )
16718 {
16719 /* constraint has become inactive or modifiable during pairwise presolving */
16720 if( usefulconss[c] == NULL )
16721 continue;
16722
16723 npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? c : (c - firstchange); /*lint !e776*/
16724
16726 SCIP_CALL( preprocessConstraintPairs(scip, usefulconss, firstchange, c, conshdlrdata->maxaggrnormscale,
16727 &cutoff, ndelconss, nchgsides, nchgcoefs) );
16728
16729 if( npaircomparisons > conshdlrdata->nmincomparisons )
16730 {
16732 if( ((*ndelconss - oldndelconss) + (*nchgsides - oldnchgsides)/2.0 + (*nchgcoefs - oldnchgcoefs)/10.0) / ((SCIP_Real) npaircomparisons) < conshdlrdata->mingainpernmincomp )
16733 break;
16734 oldndelconss = *ndelconss;
16735 oldnchgsides = *nchgsides;
16736 oldnchgcoefs = *nchgcoefs;
16737 npaircomparisons = 0;
16738 }
16739 }
16740 /* free temporary memory */
16742 }
16743 }
16744
16745 /* before upgrading, check whether we can apply some additional dual presolving, because a variable only appears
16746 * in linear constraints and we therefore have full information about it
16747 */
16748 if( !cutoff && firstupgradetry < nconss
16749 && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
16750 && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides
16751 )
16752 {
16753 if( conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) && !SCIPisStopped(scip) )
16754 {
16755 SCIP_CALL( fullDualPresolve(scip, conss, nconss, &cutoff, nchgbds) );
16756 }
16757 }
16758
16759 /* try to upgrade constraints into a more specific constraint type;
16760 * only upgrade constraints, if no reductions were found in this round (otherwise, the linear constraint handler
16761 * may find additional reductions before giving control away to other (less intelligent?) constraint handlers)
16762 */
16763 if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && SCIPisPresolveFinished(scip) )
16764 {
16765 for( c = firstupgradetry; c < nconss && !SCIPisStopped(scip); ++c )
16766 {
16767 cons = conss[c];
16768
16769 /* don't upgrade modifiable constraints */
16770 if( SCIPconsIsModifiable(cons) )
16771 continue;
16772
16773 consdata = SCIPconsGetData(cons);
16774 assert(consdata != NULL);
16775
16776 /* only upgrade completely presolved constraints, that changed since the last upgrading call */
16777 if( consdata->upgradetried )
16778 continue;
16779 /* @todo force that upgrade will be performed later? */
16780 if( !consdata->presolved )
16781 continue;
16782
16783 consdata->upgradetried = TRUE;
16784 if( SCIPconsIsActive(cons) )
16785 {
16787
16789 if( upgdcons != NULL )
16790 {
16791 /* add the upgraded constraint to the problem */
16794 (*nupgdconss)++;
16795
16796 /* mark the linear constraint being upgraded and to be removed after presolving;
16797 * don't delete it directly, because it may help to preprocess other linear constraints
16798 */
16799 assert(!consdata->upgraded);
16800 consdata->upgraded = TRUE;
16801
16802 /* delete upgraded inequalities immediately;
16803 * delete upgraded equalities, if we don't need it anymore for aggregation and redundancy checking
16804 */
16805 if( SCIPisLT(scip, consdata->lhs, consdata->rhs)
16806 || !conshdlrdata->presolpairwise
16807 || (conshdlrdata->maxaggrnormscale == 0.0) )
16808 {
16809 SCIP_CALL( SCIPdelCons(scip, cons) );
16810 }
16811 }
16812 }
16813 }
16814 }
16815
16816 /* return the correct result code */
16817 if( cutoff )
16819 else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss
16820 || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
16822 else
16824
16825 return SCIP_OKAY;
16826}
16827
16828
16829/** propagation conflict resolving method of constraint handler */
16830static
16832{ /*lint --e{715}*/
16833 assert(scip != NULL);
16834 assert(cons != NULL);
16835 assert(result != NULL);
16836
16837 SCIP_CALL( resolvePropagation(scip, cons, infervar, intToInferInfo(inferinfo), boundtype, bdchgidx, result) );
16838
16839 return SCIP_OKAY;
16840}
16841
16842
16843/** variable rounding lock method of constraint handler */
16844static
16846{ /*lint --e{715}*/
16847 SCIP_CONSDATA* consdata;
16848 SCIP_Bool haslhs;
16849 SCIP_Bool hasrhs;
16850 int i;
16851
16852 assert(scip != NULL);
16853 assert(cons != NULL);
16854 consdata = SCIPconsGetData(cons);
16855 assert(consdata != NULL);
16856
16857 haslhs = !SCIPisInfinity(scip, -consdata->lhs);
16858 hasrhs = !SCIPisInfinity(scip, consdata->rhs);
16859
16860 /* update rounding locks of every single variable */
16861 for( i = 0; i < consdata->nvars; ++i )
16862 {
16863 if( SCIPisPositive(scip, consdata->vals[i]) )
16864 {
16865 if( haslhs )
16866 {
16867 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16868 }
16869 if( hasrhs )
16870 {
16871 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16872 }
16873 }
16874 else
16875 {
16876 if( haslhs )
16877 {
16878 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16879 }
16880 if( hasrhs )
16881 {
16882 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16883 }
16884 }
16885 }
16886
16887 return SCIP_OKAY;
16888}
16889
16890
16891/** variable deletion method of constraint handler */
16892static
16894{
16895 assert(scip != NULL);
16896 assert(conshdlr != NULL);
16897 assert(conss != NULL || nconss == 0);
16898
16899 if( nconss > 0 )
16900 {
16901 SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
16902 }
16903
16904 return SCIP_OKAY;
16905}
16906
16907/** constraint display method of constraint handler */
16908static
16910{ /*lint --e{715}*/
16911 assert(scip != NULL);
16912 assert(conshdlr != NULL);
16913 assert(cons != NULL);
16914
16916
16917 return SCIP_OKAY;
16918}
16919
16920/** constraint copying method of constraint handler */
16921static
16923{ /*lint --e{715}*/
16925 SCIP_Real* sourcecoefs;
16926 const char* consname;
16927 int nvars;
16928
16929 assert(scip != NULL);
16930 assert(sourcescip != NULL);
16932
16933 /* get variables and coefficients of the source constraint */
16936 nvars = SCIPgetNVarsLinear(sourcescip, sourcecons);
16937
16938 if( name != NULL )
16939 consname = name;
16940 else
16941 consname = SCIPconsGetName(sourcecons);
16942
16943 SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, sourcecoefs,
16944 SCIPgetLhsLinear(sourcescip, sourcecons), SCIPgetRhsLinear(sourcescip, sourcecons), varmap, consmap,
16945 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
16946 assert(cons != NULL || *valid == FALSE);
16947
16948 /* @todo should also the checkabsolute flag of the constraint be copied? */
16949
16950 return SCIP_OKAY;
16951}
16952
16953/** find operators '<=', '==', '>=', [free] in input string and return those places
16954 *
16955 * There should only be one operator, except for ranged rows for which exactly two operators '<=' must be present.
16956 */
16957static
16959 const char* str, /**< null terminated input string */
16960 char** firstoperator, /**< pointer to store the string starting at the first operator */
16961 char** secondoperator, /**< pointer to store the string starting at the second operator */
16962 SCIP_Bool* success /**< pointer to store if the line contains a valid operator order */
16963 )
16964{
16965 char* curr;
16966
16967 assert(str != NULL);
16970
16973
16974 curr = (char*)str;
16975 *success = TRUE;
16976
16977 /* loop over the input string to find all operators */
16978 while( *curr && *success )
16979 {
16980 SCIP_Bool found = FALSE;
16981 int increment = 1;
16982
16983 /* try if we found a possible operator */
16984 switch( *curr )
16985 {
16986 case '<':
16987 case '=':
16988 case '>':
16989
16990 /* check if the two characters curr[0,1] form an operator together */
16991 if( curr[1] == '=' )
16992 {
16993 found = TRUE;
16994
16995 /* update increment to continue after this operator */
16996 increment = 2;
16997 }
16998 break;
16999 case '[':
17000 if( strncmp(curr, "[free]", 6) == 0 )
17001 {
17002 found = TRUE;
17003
17004 /* update increment to continue after this operator */
17005 increment = 6;
17006 }
17007 break;
17008 default:
17009 break;
17010 }
17011
17012 /* assign the found operator to the first or second pointer and check for violations of the linear constraint grammar */
17013 if( found )
17014 {
17015 if( *firstoperator == NULL )
17016 {
17017 *firstoperator = curr;
17018 }
17019 else
17020 {
17021 if( *secondoperator != NULL )
17022 {
17023 SCIPerrorMessage("Found more than two operators in line %s\n", str);
17024 *success = FALSE;
17025 }
17026 else if( strncmp(*firstoperator, "<=", 2) != 0 )
17027 {
17028 SCIPerrorMessage("Two operators in line that is not a ranged row: %s", str);
17029 *success = FALSE;
17030 }
17031 else if( strncmp(curr, "<=", 2) != 0 )
17032 {
17033 SCIPerrorMessage("Bad second operator, expected ranged row specification: %s", str);
17034 *success = FALSE;
17035 }
17036
17037 *secondoperator = curr;
17038 }
17039 }
17040
17041 curr += increment;
17042 }
17043
17044 /* check if we did find at least one operator */
17045 if( *success )
17046 {
17047 if( *firstoperator == NULL )
17048 {
17049 SCIPerrorMessage("Could not find any operator in line %s\n", str);
17050 *success = FALSE;
17051 }
17052 }
17053}
17054
17055/** constraint parsing method of constraint handler */
17056static
17058{ /*lint --e{715}*/
17059 SCIP_VAR** vars;
17060 SCIP_Real* coefs;
17061 int nvars;
17062 int coefssize;
17063 int requsize;
17064 SCIP_Real lhs;
17065 SCIP_Real rhs;
17066 char* endptr;
17067 char* firstop;
17068 char* secondop;
17069 SCIP_Bool operatorsuccess;
17070 char* lhsstrptr;
17071 char* rhsstrptr;
17072 char* varstrptr;
17073
17074 assert(scip != NULL);
17075 assert(success != NULL);
17076 assert(str != NULL);
17077 assert(name != NULL);
17078 assert(cons != NULL);
17079
17080 /* set left and right hand side to their default values */
17081 lhs = -SCIPinfinity(scip);
17082 rhs = SCIPinfinity(scip);
17083
17084 (*success) = FALSE;
17085
17086 /* return of string empty */
17087 if( !*str )
17088 return SCIP_OKAY;
17089
17090 /* ignore whitespace */
17091 SCIP_CALL( SCIPskipSpace((char**)&str) );
17092
17093 /* find operators in the line first, all other remaining parsing depends on occurence of the operators '<=', '>=', '==',
17094 * and the special word [free]
17095 */
17097
17098 /* if the grammar is not valid for parsing a linear constraint, return */
17099 if( ! operatorsuccess )
17100 return SCIP_OKAY;
17101
17102 varstrptr = (char *)str;
17104 assert(firstop != NULL);
17105
17106 /* assign the strings for parsing the left hand side, right hand side, and the linear variable sum */
17107 switch( *firstop )
17108 {
17109 case '<':
17110 assert(firstop[1] == '=');
17111 /* we have ranged row lhs <= a_1 x_1 + ... + a_n x_n <= rhs */
17112 if( secondop != NULL )
17113 {
17114 assert(secondop[0] == '<' && secondop[1] == '=');
17115 lhsstrptr = (char *)str;
17116 varstrptr = firstop + 2;
17117 rhsstrptr = secondop + 2;
17118 }
17119 else
17120 {
17121 /* we have an inequality with infinite left hand side a_1 x_1 + ... + a_n x_n <= rhs */
17122 lhsstrptr = NULL;
17123 varstrptr = (char *)str;
17124 rhsstrptr = firstop + 2;
17125 }
17126 break;
17127 case '>':
17128 assert(firstop[1] == '=');
17129 assert(secondop == NULL);
17130 /* we have a_1 x_1 + ... + a_n x_n >= lhs */
17131 lhsstrptr = firstop + 2;
17132 break;
17133 case '=':
17134 assert(firstop[1] == '=');
17135 assert(secondop == NULL);
17136 /* we have a_1 x_1 + ... + a_n x_n == lhs (rhs) */
17137 rhsstrptr = firstop + 2;
17138 lhsstrptr = firstop + 2;
17139 break;
17140 case '[':
17141 assert(strncmp(firstop, "[free]", 6) == 0);
17142 assert(secondop == NULL);
17143 /* nothing to assign in case of a free a_1 x_1 + ... + a_n x_n [free] */
17144 break;
17145 default:
17146 /* it should not be possible that a different character appears in that position */
17147 SCIPerrorMessage("Parsing has wrong operator character '%c', should be one of <=>[", *firstop);
17148 return SCIP_READERROR;
17149 }
17150
17151 /* parse left hand side, if necessary */
17152 if( lhsstrptr != NULL )
17153 {
17154 if( ! SCIPparseReal(scip, lhsstrptr, &lhs, &endptr) )
17155 {
17156 SCIPerrorMessage("error parsing left hand side number from <%s>\n", lhsstrptr);
17157 return SCIP_OKAY;
17158 }
17159
17160 /* in case of an equation, assign the left also to the right hand side */
17161 if( rhsstrptr == lhsstrptr )
17162 rhs = lhs;
17163 }
17164
17165 /* parse right hand side, if different from left hand side */
17166 if( rhsstrptr != NULL && rhsstrptr != lhsstrptr )
17167 {
17168 if( ! SCIPparseReal(scip, rhsstrptr, &rhs, &endptr) )
17169 {
17170 SCIPerrorMessage("error parsing right hand side number from <%s>\n", lhsstrptr);
17171 return SCIP_OKAY;
17172 }
17173 }
17174
17175 /* initialize buffers for storing the variables and coefficients */
17176 coefssize = 100;
17177 SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) );
17178 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
17179
17180 assert(varstrptr != NULL);
17181
17182 /* parse linear sum to get variables and coefficients */
17184
17185 if( *success && requsize > coefssize )
17186 {
17187 /* realloc buffers and try again */
17188 coefssize = requsize;
17189 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, coefssize) );
17190 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
17191
17193 assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
17194 }
17195
17196 if( !*success )
17197 {
17198 SCIPerrorMessage("no luck in parsing linear sum '%s'\n", varstrptr);
17199 }
17200 else
17201 {
17202 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
17203 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17204 }
17205
17206 SCIPfreeBufferArray(scip, &coefs);
17208
17209 return SCIP_OKAY;
17210}
17211
17212
17213/** constraint method of constraint handler which returns the variables (if possible) */
17214static
17216{ /*lint --e{715}*/
17217 SCIP_CONSDATA* consdata;
17218
17219 consdata = SCIPconsGetData(cons);
17220 assert(consdata != NULL);
17221
17223 (*success) = FALSE;
17224 else
17225 {
17226 assert(vars != NULL);
17227
17228 BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
17229 (*success) = TRUE;
17230 }
17231
17232 return SCIP_OKAY;
17233}
17234
17235/**! [Callback for the number of variables]*/
17236/** constraint method of constraint handler which returns the number of variables (if possible) */
17237static
17239{ /*lint --e{715}*/
17240 SCIP_CONSDATA* consdata;
17241
17242 consdata = SCIPconsGetData(cons);
17243 assert(consdata != NULL);
17244
17245 (*nvars) = consdata->nvars;
17246 (*success) = TRUE;
17247
17248 return SCIP_OKAY;
17249}
17250/**! [Callback for the number of variables]*/
17251
17252/*
17253 * Callback methods of event handler
17254 */
17255
17256/** execution method of event handler */
17257static
17259{ /*lint --e{715}*/
17260 SCIP_CONS* cons;
17261 SCIP_CONSDATA* consdata;
17262 SCIP_VAR* var;
17263 SCIP_EVENTTYPE eventtype;
17264
17265 assert(scip != NULL);
17266 assert(eventhdlr != NULL);
17267 assert(eventdata != NULL);
17269 assert(event != NULL);
17270
17271 cons = eventdata->cons;
17272 assert(cons != NULL);
17273 consdata = SCIPconsGetData(cons);
17274 assert(consdata != NULL);
17275
17276 /* we can skip events droped for deleted constraints */
17277 if( SCIPconsIsDeleted(cons) )
17278 return SCIP_OKAY;
17279
17280 eventtype = SCIPeventGetType(event);
17282
17283 if( (eventtype & SCIP_EVENTTYPE_BOUNDCHANGED) != 0 )
17284 {
17285 SCIP_Real oldbound;
17286 SCIP_Real newbound;
17287 SCIP_Real val;
17288 int varpos;
17289
17290 varpos = eventdata->varpos;
17291 assert(0 <= varpos && varpos < consdata->nvars);
17292 oldbound = SCIPeventGetOldbound(event);
17293 newbound = SCIPeventGetNewbound(event);
17294 assert(var != NULL);
17295 assert(consdata->vars[varpos] == var);
17296 val = consdata->vals[varpos];
17297
17298 /* we only need to update the activities if the constraint is active,
17299 * otherwise we mark them to be invalid
17300 */
17301 if( SCIPconsIsActive(cons) )
17302 {
17303 /* update the activity values */
17304 if( (eventtype & SCIP_EVENTTYPE_LBCHANGED) != 0 )
17305 consdataUpdateActivitiesLb(scip, consdata, var, oldbound, newbound, val, TRUE);
17306 else
17307 {
17308 assert((eventtype & SCIP_EVENTTYPE_UBCHANGED) != 0);
17309 consdataUpdateActivitiesUb(scip, consdata, var, oldbound, newbound, val, TRUE);
17310 }
17311 }
17312 else
17314
17315 consdata->presolved = FALSE;
17316 consdata->rangedrowpropagated = 0;
17317
17318 /* bound change can turn the constraint infeasible or redundant only if it was a tightening */
17319 if( (eventtype & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0 )
17320 {
17322
17323 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17324 if( consdata->maxactdeltavar == var )
17325 {
17326 consdata->maxactdelta = SCIP_INVALID;
17327 consdata->maxactdeltavar = NULL;
17328 }
17329
17330 /* check whether bound tightening might now be successful */
17331 if( consdata->boundstightened > 0)
17332 {
17333 switch( eventtype )
17334 {
17336 if( (val > 0.0 ? !SCIPisInfinity(scip, consdata->rhs) : !SCIPisInfinity(scip, -consdata->lhs)) )
17337 consdata->boundstightened = 0;
17338 break;
17340 if( (val > 0.0 ? !SCIPisInfinity(scip, -consdata->lhs) : !SCIPisInfinity(scip, consdata->rhs)) )
17341 consdata->boundstightened = 0;
17342 break;
17343 default:
17344 SCIPerrorMessage("invalid event type %" SCIP_EVENTTYPE_FORMAT "\n", eventtype);
17345 return SCIP_INVALIDDATA;
17346 }
17347 }
17348 }
17349 /* update maximal activity delta if a bound was relaxed */
17350 else if( !SCIPisInfinity(scip, consdata->maxactdelta) )
17351 {
17352 SCIP_Real lb;
17353 SCIP_Real ub;
17354 SCIP_Real domain;
17355 SCIP_Real delta;
17356
17357 assert((eventtype & SCIP_EVENTTYPE_BOUNDRELAXED) != 0);
17358
17359 lb = SCIPvarGetLbLocal(var);
17360 ub = SCIPvarGetUbLocal(var);
17361
17362 domain = ub - lb;
17363 delta = REALABS(val) * domain;
17364
17365 if( delta > consdata->maxactdelta )
17366 {
17367 consdata->maxactdelta = delta;
17368 consdata->maxactdeltavar = var;
17369 }
17370 }
17371 }
17372 else if( (eventtype & SCIP_EVENTTYPE_VARFIXED) != 0 )
17373 {
17374 /* we want to remove the fixed variable */
17375 consdata->presolved = FALSE;
17376 consdata->removedfixings = FALSE;
17377 consdata->rangedrowpropagated = 0;
17378
17379 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17380 if( consdata->maxactdeltavar == var )
17381 {
17382 consdata->maxactdelta = SCIP_INVALID;
17383 consdata->maxactdeltavar = NULL;
17384 }
17385 }
17386 else if( (eventtype & SCIP_EVENTTYPE_VARUNLOCKED) != 0 )
17387 {
17388 /* there is only one lock left: we may multi-aggregate the variable as slack of an equation */
17391 consdata->presolved = FALSE;
17392 }
17393 else if( (eventtype & SCIP_EVENTTYPE_GBDCHANGED) != 0 )
17394 {
17395 SCIP_Real oldbound;
17396 SCIP_Real newbound;
17397 SCIP_Real val;
17398 int varpos;
17399
17400 varpos = eventdata->varpos;
17401 assert(0 <= varpos && varpos < consdata->nvars);
17402 oldbound = SCIPeventGetOldbound(event);
17403 newbound = SCIPeventGetNewbound(event);
17404 assert(var != NULL);
17405 assert(consdata->vars[varpos] == var);
17406 val = consdata->vals[varpos];
17407
17408 consdata->rangedrowpropagated = 0;
17409
17410 /* update the activity values */
17411 if( (eventtype & SCIP_EVENTTYPE_GLBCHANGED) != 0 )
17412 consdataUpdateActivitiesGlbLb(scip, consdata, oldbound, newbound, val, TRUE);
17413 else
17414 {
17415 assert((eventtype & SCIP_EVENTTYPE_GUBCHANGED) != 0);
17416 consdataUpdateActivitiesGlbUb(scip, consdata, oldbound, newbound, val, TRUE);
17417 }
17418
17419 /* if the variable is binary but not fixed it had to become binary due to this global change */
17421 {
17423 consdata->indexsorted = FALSE;
17424 else
17425 consdata->coefsorted = FALSE;
17426 }
17427 }
17428 else if( (eventtype & SCIP_EVENTTYPE_TYPECHANGED) != 0 )
17429 {
17431
17432 /* for presolving it only matters if a variable type changed from continuous to some kind of integer */
17433 consdata->presolved = (consdata->presolved && SCIPeventGetOldtype(event) < SCIP_VARTYPE_CONTINUOUS);
17434
17435 /* the ordering is preserved if the type changes from something different to binary to binary but SCIPvarIsBinary() is true */
17436 consdata->indexsorted = (consdata->indexsorted && SCIPeventGetNewtype(event) == SCIP_VARTYPE_BINARY && SCIPvarIsBinary(var));
17437 }
17438 else
17439 {
17440 assert((eventtype & SCIP_EVENTTYPE_VARDELETED) != 0);
17441 consdata->varsdeleted = TRUE;
17442 }
17443
17444 return SCIP_OKAY;
17445}
17446
17447
17448/*
17449 * Callback methods of conflict handler
17450 */
17451
17452/** conflict processing method of conflict handler (called when conflict was found) */
17453static
17455{ /*lint --e{715}*/
17456 SCIP_VAR** vars;
17457 SCIP_Real* vals;
17458 SCIP_Real lhs;
17459 int i;
17460
17461 assert(scip != NULL);
17464 assert(bdchginfos != NULL || nbdchginfos == 0);
17465 assert(result != NULL);
17466
17467 /* don't process already resolved conflicts */
17468 if( resolved )
17469 {
17471 return SCIP_OKAY;
17472 }
17473
17475
17476 /* create array of variables and coefficients: sum_{i \in P} x_i - sum_{i \in N} x_i >= 1 - |N| */
17477 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
17478 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nbdchginfos) );
17479 lhs = 1.0;
17480 for( i = 0; i < nbdchginfos; ++i )
17481 {
17482 assert(bdchginfos != NULL);
17483
17484 vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
17485
17486 /* we can only treat binary variables */
17487 /**@todo extend linear conflict constraints to some non-binary cases */
17488 if( !SCIPvarIsBinary(vars[i]) )
17489 break;
17490
17491 /* check whether the variable is fixed to zero (P) or one (N) in the conflict set */
17492 if( SCIPbdchginfoGetNewbound(bdchginfos[i]) < 0.5 )
17493 vals[i] = 1.0;
17494 else
17495 {
17496 vals[i] = -1.0;
17497 lhs -= 1.0;
17498 }
17499 }
17500
17501 if( i == nbdchginfos )
17502 {
17503 SCIP_CONS* cons;
17505 char consname[SCIP_MAXSTRLEN];
17506
17507 /* create a constraint out of the conflict set */
17509 SCIP_CALL( SCIPcreateConsLinear(scip, &cons, consname, nbdchginfos, vars, vals, lhs, SCIPinfinity(scip),
17510 FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
17511
17512 /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
17514 if( upgdcons != NULL )
17515 {
17516 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
17517 cons = upgdcons;
17518 }
17519
17520 /* add conflict to SCIP */
17522
17524 }
17525
17526 /* free temporary memory */
17527 SCIPfreeBufferArray(scip, &vals);
17529
17530 return SCIP_OKAY;
17531}
17532
17533
17534/*
17535 * Nonlinear constraint upgrading
17536 */
17537
17538/** tries to upgrade a nonlinear constraint into a linear constraint */
17539static
17541{
17542 SCIP_CONSDATA* consdata;
17543 SCIP_EXPR* expr;
17544 SCIP_Real lhs;
17545 SCIP_Real rhs;
17546 int i;
17547
17548 assert(nupgdconss != NULL);
17549 assert(upgdconss != NULL);
17550 assert(upgdconsssize > 0);
17551
17552 expr = SCIPgetExprNonlinear(cons);
17553 assert(expr != NULL);
17554
17555 /* not a linear constraint if the expression is not a sum
17556 * (unless the expression is a variable or a constant or a constant*variable, but these are simplified away in cons_nonlinear)
17557 */
17558 if( !SCIPisExprSum(scip, expr) )
17559 return SCIP_OKAY;
17560
17561 /* if at least one child is not a variable, then not a linear constraint */
17562 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17563 if( !SCIPisExprVar(scip, SCIPexprGetChildren(expr)[i]) )
17564 return SCIP_OKAY;
17565
17566 /* consider constant part of the sum expression */
17569
17571 0, NULL, NULL, lhs, rhs,
17575 SCIPconsIsStickingAtNode(cons)) );
17576 assert(upgdconss[0] != NULL);
17577
17578 consdata = SCIPconsGetData(upgdconss[0]);
17579
17580 /* add linear terms */
17582 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17583 {
17585 }
17586
17587 /* check violation of this linear constraint with absolute tolerances, to be consistent with the original nonlinear constraint */
17588 consdata->checkabsolute = TRUE;
17589
17590 *nupgdconss = 1;
17591
17592 SCIPdebugMsg(scip, "created linear constraint:\n");
17594
17595 return SCIP_OKAY;
17596} /*lint !e715*/
17597
17598/*
17599 * constraint specific interface methods
17600 */
17601
17602/** creates the handler for linear constraints and includes it in SCIP */
17604 SCIP* scip /**< SCIP data structure */
17605 )
17606{
17607 SCIP_CONSHDLRDATA* conshdlrdata;
17608 SCIP_CONSHDLR* conshdlr;
17609 SCIP_EVENTHDLR* eventhdlr;
17611
17612 assert(scip != NULL);
17613
17614 /* create event handler for bound change events */
17617
17618 /* create conflict handler for linear constraints */
17621
17622 /* create constraint handler data */
17623 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
17624
17625 /* include constraint handler */
17629 conshdlrdata) );
17630
17631 assert(conshdlr != NULL);
17632
17633 /* set non-fundamental callbacks via specific setter functions */
17658
17659 if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
17660 {
17661 /* include the linear constraint upgrade in the nonlinear constraint handler */
17663 }
17664
17665 /* add linear constraint handler parameters */
17667 "constraints/" CONSHDLR_NAME "/tightenboundsfreq",
17668 "multiplier on propagation frequency, how often the bounds are tightened (-1: never, 0: only at root)",
17669 &conshdlrdata->tightenboundsfreq, TRUE, DEFAULT_TIGHTENBOUNDSFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17671 "constraints/" CONSHDLR_NAME "/maxrounds",
17672 "maximal number of separation rounds per node (-1: unlimited)",
17673 &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
17675 "constraints/" CONSHDLR_NAME "/maxroundsroot",
17676 "maximal number of separation rounds per node in the root node (-1: unlimited)",
17677 &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
17679 "constraints/" CONSHDLR_NAME "/maxsepacuts",
17680 "maximal number of cuts separated per separation round",
17681 &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
17683 "constraints/" CONSHDLR_NAME "/maxsepacutsroot",
17684 "maximal number of cuts separated per separation round in the root node",
17685 &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
17687 "constraints/" CONSHDLR_NAME "/presolpairwise",
17688 "should pairwise constraint comparison be performed in presolving?",
17689 &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
17691 "constraints/" CONSHDLR_NAME "/presolusehashing",
17692 "should hash table be used for detecting redundant constraints in advance",
17693 &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
17695 "constraints/" CONSHDLR_NAME "/nmincomparisons",
17696 "number for minimal pairwise presolve comparisons",
17697 &conshdlrdata->nmincomparisons, TRUE, DEFAULT_NMINCOMPARISONS, 1, INT_MAX, NULL, NULL) );
17699 "constraints/" CONSHDLR_NAME "/mingainpernmincomparisons",
17700 "minimal gain per minimal pairwise presolve comparisons to repeat pairwise comparison round",
17701 &conshdlrdata->mingainpernmincomp, TRUE, DEFAULT_MINGAINPERNMINCOMP, 0.0, 1.0, NULL, NULL) );
17703 "constraints/" CONSHDLR_NAME "/maxaggrnormscale",
17704 "maximal allowed relative gain in maximum norm for constraint aggregation (0.0: disable constraint aggregation)",
17705 &conshdlrdata->maxaggrnormscale, TRUE, DEFAULT_MAXAGGRNORMSCALE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17707 "constraints/" CONSHDLR_NAME "/maxeasyactivitydelta",
17708 "maximum activity delta to run easy propagation on linear constraint (faster, but numerically less stable)",
17709 &conshdlrdata->maxeasyactivitydelta, TRUE, DEFAULT_MAXEASYACTIVITYDELTA, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17711 "constraints/" CONSHDLR_NAME "/maxcardbounddist",
17712 "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for separating knapsack cardinality cuts",
17713 &conshdlrdata->maxcardbounddist, TRUE, DEFAULT_MAXCARDBOUNDDIST, 0.0, 1.0, NULL, NULL) );
17715 "constraints/" CONSHDLR_NAME "/separateall",
17716 "should all constraints be subject to cardinality cut generation instead of only the ones with non-zero dual value?",
17717 &conshdlrdata->separateall, FALSE, DEFAULT_SEPARATEALL, NULL, NULL) );
17719 "constraints/" CONSHDLR_NAME "/aggregatevariables",
17720 "should presolving search for aggregations in equations",
17721 &conshdlrdata->aggregatevariables, TRUE, DEFAULT_AGGREGATEVARIABLES, NULL, NULL) );
17723 "constraints/" CONSHDLR_NAME "/simplifyinequalities",
17724 "should presolving try to simplify inequalities",
17725 &conshdlrdata->simplifyinequalities, TRUE, DEFAULT_SIMPLIFYINEQUALITIES, NULL, NULL) );
17727 "constraints/" CONSHDLR_NAME "/dualpresolving",
17728 "should dual presolving steps be performed?",
17729 &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
17731 "constraints/" CONSHDLR_NAME "/singletonstuffing",
17732 "should stuffing of singleton continuous variables be performed?",
17733 &conshdlrdata->singletonstuffing, TRUE, DEFAULT_SINGLETONSTUFFING, NULL, NULL) );
17735 "constraints/" CONSHDLR_NAME "/singlevarstuffing",
17736 "should single variable stuffing be performed, which tries to fulfill constraints using the cheapest variable?",
17737 &conshdlrdata->singlevarstuffing, TRUE, DEFAULT_SINGLEVARSTUFFING, NULL, NULL) );
17739 "constraints/" CONSHDLR_NAME "/sortvars", "apply binaries sorting in decr. order of coeff abs value?",
17740 &conshdlrdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL) );
17742 "constraints/" CONSHDLR_NAME "/checkrelmaxabs",
17743 "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)?",
17744 &conshdlrdata->checkrelmaxabs, TRUE, DEFAULT_CHECKRELMAXABS, NULL, NULL) );
17746 "constraints/" CONSHDLR_NAME "/detectcutoffbound",
17747 "should presolving try to detect constraints parallel to the objective function defining an upper bound and prevent these constraints from entering the LP?",
17748 &conshdlrdata->detectcutoffbound, TRUE, DEFAULT_DETECTCUTOFFBOUND, NULL, NULL) );
17750 "constraints/" CONSHDLR_NAME "/detectlowerbound",
17751 "should presolving try to detect constraints parallel to the objective function defining a lower bound and prevent these constraints from entering the LP?",
17752 &conshdlrdata->detectlowerbound, TRUE, DEFAULT_DETECTLOWERBOUND, NULL, NULL) );
17754 "constraints/" CONSHDLR_NAME "/detectpartialobjective",
17755 "should presolving try to detect subsets of constraints parallel to the objective function?",
17756 &conshdlrdata->detectpartialobjective, TRUE, DEFAULT_DETECTPARTIALOBJECTIVE, NULL, NULL) );
17758 "constraints/" CONSHDLR_NAME "/rangedrowpropagation",
17759 "should presolving and propagation try to improve bounds, detect infeasibility, and extract sub-constraints from ranged rows and equations?",
17760 &conshdlrdata->rangedrowpropagation, TRUE, DEFAULT_RANGEDROWPROPAGATION, NULL, NULL) );
17762 "constraints/" CONSHDLR_NAME "/rangedrowartcons",
17763 "should presolving and propagation extract sub-constraints from ranged rows and equations?",
17764 &conshdlrdata->rangedrowartcons, TRUE, DEFAULT_RANGEDROWARTCONS, NULL, NULL) );
17766 "constraints/" CONSHDLR_NAME "/rangedrowmaxdepth",
17767 "maximum depth to apply ranged row propagation",
17768 &conshdlrdata->rangedrowmaxdepth, TRUE, DEFAULT_RANGEDROWMAXDEPTH, 0, INT_MAX, NULL, NULL) );
17770 "constraints/" CONSHDLR_NAME "/rangedrowfreq",
17771 "frequency for applying ranged row propagation",
17772 &conshdlrdata->rangedrowfreq, TRUE, DEFAULT_RANGEDROWFREQ, 1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17774 "constraints/" CONSHDLR_NAME "/multaggrremove",
17775 "should multi-aggregations only be performed if the constraint can be removed afterwards?",
17776 &conshdlrdata->multaggrremove, TRUE, DEFAULT_MULTAGGRREMOVE, NULL, NULL) );
17778 "constraints/" CONSHDLR_NAME "/maxmultaggrquot",
17779 "maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation",
17780 &conshdlrdata->maxmultaggrquot, TRUE, DEFAULT_MAXMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17782 "constraints/" CONSHDLR_NAME "/maxdualmultaggrquot",
17783 "maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation",
17784 &conshdlrdata->maxdualmultaggrquot, TRUE, DEFAULT_MAXDUALMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17786 "constraints/" CONSHDLR_NAME "/extractcliques",
17787 "should Cliques be extracted?",
17788 &conshdlrdata->extractcliques, TRUE, DEFAULT_EXTRACTCLIQUES, NULL, NULL) );
17789
17790 return SCIP_OKAY;
17791}
17792
17793/** includes a linear constraint update method into the linear constraint handler */
17795 SCIP* scip, /**< SCIP data structure */
17796 SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
17797 int priority, /**< priority of upgrading method */
17798 const char* conshdlrname /**< name of the constraint handler */
17799 )
17800{
17801 SCIP_CONSHDLR* conshdlr;
17802 SCIP_CONSHDLRDATA* conshdlrdata;
17806
17807 assert(scip != NULL);
17810
17811 /* find the linear constraint handler */
17812 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17813 if( conshdlr == NULL )
17814 {
17815 SCIPerrorMessage("linear constraint handler not found\n");
17816 return SCIP_PLUGINNOTFOUND;
17817 }
17818
17819 conshdlrdata = SCIPconshdlrGetData(conshdlr);
17820 assert(conshdlrdata != NULL);
17821
17822 /* check if linear constraint update method already exists in constraint handler data */
17823 if( !conshdlrdataHasUpgrade(scip, conshdlrdata, linconsupgd, conshdlrname) )
17824 {
17825 /* create a linear constraint upgrade data object */
17827
17828 /* insert linear constraint update method into constraint handler data */
17830
17831 /* adds parameter to turn on and off the upgrading step */
17832 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/linear/upgrade/%s", conshdlrname);
17833 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "enable linear upgrading for constraint handler <%s>", conshdlrname);
17836 &linconsupgrade->active, FALSE, TRUE, NULL, NULL) );
17837 }
17838
17839 return SCIP_OKAY;
17840}
17841
17842/** creates and captures a linear constraint
17843 *
17844 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17845 */
17847 SCIP* scip, /**< SCIP data structure */
17848 SCIP_CONS** cons, /**< pointer to hold the created constraint */
17849 const char* name, /**< name of constraint */
17850 int nvars, /**< number of nonzeros in the constraint */
17851 SCIP_VAR** vars, /**< array with variables of constraint entries */
17852 SCIP_Real* vals, /**< array with coefficients of constraint entries */
17853 SCIP_Real lhs, /**< left hand side of constraint */
17854 SCIP_Real rhs, /**< right hand side of constraint */
17855 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
17856 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
17857 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
17858 * Usually set to TRUE. */
17859 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
17860 * TRUE for model constraints, FALSE for additional, redundant constraints. */
17861 SCIP_Bool check, /**< should the constraint be checked for feasibility?
17862 * TRUE for model constraints, FALSE for additional, redundant constraints. */
17863 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
17864 * Usually set to TRUE. */
17865 SCIP_Bool local, /**< is constraint only valid locally?
17866 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
17867 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
17868 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
17869 * adds coefficients to this constraint. */
17870 SCIP_Bool dynamic, /**< is constraint subject to aging?
17871 * Usually set to FALSE. Set to TRUE for own cuts which
17872 * are separated as constraints. */
17873 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
17874 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
17875 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
17876 * if it may be moved to a more global node?
17877 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
17878 )
17879{
17880 SCIP_CONSHDLR* conshdlr;
17881 SCIP_CONSDATA* consdata;
17882
17883 assert(scip != NULL);
17884 assert(cons != NULL);
17885
17886 /* find the linear constraint handler */
17887 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17888 if( conshdlr == NULL )
17889 {
17890 SCIPerrorMessage("linear constraint handler not found\n");
17891 return SCIP_PLUGINNOTFOUND;
17892 }
17893
17894 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
17895 * constraint after presolving we have to ensure that it holds active variables
17896 */
17898 {
17899 SCIP_VAR** consvars;
17900 SCIP_Real* consvals;
17901 SCIP_Real constant = 0.0;
17902 int nconsvars;
17903 int requiredsize;
17904
17905 nconsvars = nvars;
17906 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, vars, nconsvars) );
17907 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) );
17908
17909 /* get active variables for new constraint */
17910 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
17911
17912 /* if space was not enough we need to resize the buffers */
17913 if( requiredsize > nconsvars )
17914 {
17917
17918 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
17919 assert(requiredsize <= nconsvars);
17920 }
17921
17922 /* adjust sides and check that we do not subtract infinity values */
17923 if( SCIPisInfinity(scip, REALABS(constant)) )
17924 {
17925 if( constant < 0.0 )
17926 {
17927 if( SCIPisInfinity(scip, lhs) )
17928 {
17930 SCIPfreeBufferArray(scip, &consvars);
17931
17932 SCIPerrorMessage("try to generate inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite left hand side of the constraint\n", name);
17933
17934 SCIPABORT();
17935 return SCIP_INVALIDDATA; /*lint !e527*/
17936 }
17937 if( SCIPisInfinity(scip, rhs) )
17938 {
17940 SCIPfreeBufferArray(scip, &consvars);
17941
17942 SCIPerrorMessage("try to generate inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite right hand side of the constraint\n", name);
17943
17944 SCIPABORT();
17945 return SCIP_INVALIDDATA; /*lint !e527*/
17946 }
17947
17948 lhs = -SCIPinfinity(scip);
17949 rhs = -SCIPinfinity(scip);
17950 }
17951 else
17952 {
17953 if( SCIPisInfinity(scip, -lhs) )
17954 {
17956 SCIPfreeBufferArray(scip, &consvars);
17957
17958 SCIPerrorMessage("try to generate inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite left hand side of the constraint\n", name);
17959
17960 SCIPABORT();
17961 return SCIP_INVALIDDATA; /*lint !e527*/
17962 }
17963 if( SCIPisInfinity(scip, -rhs) )
17964 {
17966 SCIPfreeBufferArray(scip, &consvars);
17967
17968 SCIPerrorMessage("try to generate inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite right hand side of the constraint\n", name);
17969
17970 SCIPABORT();
17971 return SCIP_INVALIDDATA; /*lint !e527*/
17972 }
17973
17974 lhs = SCIPinfinity(scip);
17975 rhs = SCIPinfinity(scip);
17976 }
17977 }
17978 else
17979 {
17980 if( !SCIPisInfinity(scip, REALABS(lhs)) )
17981 lhs -= constant;
17982 if( !SCIPisInfinity(scip, REALABS(rhs)) )
17983 rhs -= constant;
17984
17985 if( SCIPisInfinity(scip, -lhs) )
17986 lhs = -SCIPinfinity(scip);
17987 else if( SCIPisInfinity(scip, lhs) )
17988 lhs = SCIPinfinity(scip);
17989
17990 if( SCIPisInfinity(scip, rhs) )
17991 rhs = SCIPinfinity(scip);
17992 else if( SCIPisInfinity(scip, -rhs) )
17993 rhs = -SCIPinfinity(scip);
17994 }
17995
17996 /* create constraint data */
17997 SCIP_CALL( consdataCreate(scip, &consdata, nconsvars, consvars, consvals, lhs, rhs) );
17998 assert(consdata != NULL);
17999
18001 SCIPfreeBufferArray(scip, &consvars);
18002 }
18003 else
18004 {
18005 /* create constraint data */
18006 SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, vals, lhs, rhs) );
18007 assert(consdata != NULL);
18008 }
18009
18010#ifndef NDEBUG
18011 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18012 if( check || enforce )
18013 {
18014 int n;
18015 for(n = consdata->nvars - 1; n >= 0; --n )
18016 assert(!SCIPvarIsRelaxationOnly(consdata->vars[n]));
18017 }
18018#endif
18019
18020 /* create constraint */
18021 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
18022 local, modifiable, dynamic, removable, stickingatnode) );
18023
18024 return SCIP_OKAY;
18025}
18026
18027/** creates and captures a linear constraint
18028 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
18029 * method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
18030 *
18031 * @see SCIPcreateConsLinear() for information about the basic constraint flag configuration
18032 *
18033 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
18034 */
18036 SCIP* scip, /**< SCIP data structure */
18037 SCIP_CONS** cons, /**< pointer to hold the created constraint */
18038 const char* name, /**< name of constraint */
18039 int nvars, /**< number of nonzeros in the constraint */
18040 SCIP_VAR** vars, /**< array with variables of constraint entries */
18041 SCIP_Real* vals, /**< array with coefficients of constraint entries */
18042 SCIP_Real lhs, /**< left hand side of constraint */
18043 SCIP_Real rhs /**< right hand side of constraint */
18044 )
18045{
18046 assert(scip != NULL);
18047
18048 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, vals, lhs, rhs,
18050
18051 return SCIP_OKAY;
18052}
18053
18054/** creates by copying and captures a linear constraint */
18056 SCIP* scip, /**< target SCIP data structure */
18057 SCIP_CONS** cons, /**< pointer to store the created target constraint */
18058 SCIP* sourcescip, /**< source SCIP data structure */
18059 const char* name, /**< name of constraint */
18060 int nvars, /**< number of variables in source variable array */
18061 SCIP_VAR** sourcevars, /**< source variables of the linear constraints */
18062 SCIP_Real* sourcecoefs, /**< coefficient array of the linear constraint, or NULL if all coefficients are one */
18063 SCIP_Real lhs, /**< left hand side of the linear constraint */
18064 SCIP_Real rhs, /**< right hand side of the linear constraint */
18065 SCIP_HASHMAP* varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
18066 * variables of the target SCIP */
18067 SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
18068 * target constraints */
18069 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
18070 SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
18071 SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
18072 SCIP_Bool check, /**< should the constraint be checked for feasibility? */
18073 SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
18074 SCIP_Bool local, /**< is constraint only valid locally? */
18075 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
18076 SCIP_Bool dynamic, /**< is constraint subject to aging? */
18077 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
18078 SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even
18079 * if it may be moved to a more global node? */
18080 SCIP_Bool global, /**< create a global or a local copy? */
18081 SCIP_Bool* valid /**< pointer to store if the copying was valid */
18082 )
18083{
18084 SCIP_VAR** vars;
18085 SCIP_Real* coefs;
18086
18087 SCIP_Real constant;
18088 int requiredsize;
18089 int v;
18090 SCIP_Bool success;
18091
18092 if( SCIPisGT(scip, lhs, rhs) )
18093 {
18094 *valid = FALSE;
18095 return SCIP_OKAY;
18096 }
18097
18098 (*valid) = TRUE;
18099
18100 if( nvars == 0 )
18101 {
18102 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, 0, NULL, NULL, lhs, rhs,
18103 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18104 return SCIP_OKAY;
18105 }
18106
18107 /* duplicate variable array */
18109
18110 /* duplicate coefficient array */
18111 if( sourcecoefs != NULL )
18112 {
18114 }
18115 else
18116 {
18118 for( v = 0; v < nvars; ++v )
18119 coefs[v] = 1.0;
18120 }
18121
18122 constant = 0.0;
18123
18124 /* transform source variable to active variables of the source SCIP since only these can be mapped to variables of
18125 * the target SCIP
18126 */
18127 if( !SCIPvarIsOriginal(vars[0]) )
18128 {
18129 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize, TRUE) );
18130
18131 if( requiredsize > nvars )
18132 {
18135
18136 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize, TRUE) );
18138 }
18139 }
18140 else
18141 {
18142 for( v = 0; v < nvars; ++v )
18143 {
18145 SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &coefs[v], &constant) );
18146 assert(vars[v] != NULL);
18147 }
18148 }
18149
18150 success = TRUE;
18151 /* map variables of the source constraint to variables of the target SCIP */
18152 for( v = 0; v < nvars && success; ++v )
18153 {
18154 SCIP_VAR* var;
18155 var = vars[v];
18156
18157 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18158 assert(!SCIPvarIsRelaxationOnly(var) || (!check && !enforce));
18159
18160 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &vars[v], varmap, consmap, global, &success) );
18161 assert(!(success) || vars[v] != NULL);
18162 }
18163
18164 /* only create the target constraint, if all variables could be copied */
18165 if( success )
18166 {
18167 if( !SCIPisInfinity(scip, -lhs) )
18168 lhs -= constant;
18169
18170 if( !SCIPisInfinity(scip, rhs) )
18171 rhs -= constant;
18172
18173 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
18174 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18175 }
18176 else
18177 *valid = FALSE;
18178
18179 /* free buffer array */
18180 SCIPfreeBufferArray(scip, &coefs);
18182
18183 return SCIP_OKAY;
18184}
18185
18186/** adds coefficient to linear constraint (if it is not zero) */
18188 SCIP* scip, /**< SCIP data structure */
18189 SCIP_CONS* cons, /**< constraint data */
18190 SCIP_VAR* var, /**< variable of constraint entry */
18191 SCIP_Real val /**< coefficient of constraint entry */
18192 )
18193{
18194 assert(scip != NULL);
18195 assert(cons != NULL);
18196 assert(var != NULL);
18197
18199 {
18200 SCIPerrorMessage("constraint is not linear\n");
18201 return SCIP_INVALIDDATA;
18202 }
18203
18204 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
18205 * constraint after presolving we have to ensure that it holds active variables
18206 */
18208 {
18209 SCIP_CONSDATA* consdata;
18210 SCIP_VAR** consvars;
18211 SCIP_Real* consvals;
18212 SCIP_Real constant = 0.0;
18213 SCIP_Real rhs;
18214 SCIP_Real lhs;
18215 int nconsvars;
18216 int requiredsize;
18217 int v;
18218
18219 nconsvars = 1;
18220 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
18222 consvars[0] = var;
18223 consvals[0] = val;
18224
18225 /* get active variables for new constraint */
18226 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
18227
18228 /* if space was not enough we need to resize the buffers */
18229 if( requiredsize > nconsvars )
18230 {
18233
18234 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
18235 assert(requiredsize <= nconsvars);
18236 }
18237
18238 consdata = SCIPconsGetData(cons);
18239 assert(consdata != NULL);
18240
18241 lhs = consdata->lhs;
18242 rhs = consdata->rhs;
18243
18244 /* adjust sides and check that we do not subtract infinity values */
18245 /* constant is infinite */
18246 if( SCIPisInfinity(scip, REALABS(constant)) )
18247 {
18248 if( constant < 0.0 )
18249 {
18250 if( SCIPisInfinity(scip, lhs) )
18251 {
18253 SCIPfreeBufferArray(scip, &consvars);
18254
18255 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));
18256
18257 SCIPABORT();
18258 return SCIP_INVALIDDATA; /*lint !e527*/
18259 }
18260 if( SCIPisInfinity(scip, rhs) )
18261 {
18263 SCIPfreeBufferArray(scip, &consvars);
18264
18265 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));
18266
18267 SCIPABORT();
18268 return SCIP_INVALIDDATA; /*lint !e527*/
18269 }
18270
18271 lhs = -SCIPinfinity(scip);
18272 rhs = -SCIPinfinity(scip);
18273 }
18274 else
18275 {
18276 if( SCIPisInfinity(scip, -lhs) )
18277 {
18279 SCIPfreeBufferArray(scip, &consvars);
18280
18281 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));
18282
18283 SCIPABORT();
18284 return SCIP_INVALIDDATA; /*lint !e527*/
18285 }
18286 if( SCIPisInfinity(scip, -rhs) )
18287 {
18289 SCIPfreeBufferArray(scip, &consvars);
18290
18291 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));
18292
18293 SCIPABORT();
18294 return SCIP_INVALIDDATA; /*lint !e527*/
18295 }
18296
18297 lhs = SCIPinfinity(scip);
18298 rhs = SCIPinfinity(scip);
18299 }
18300 }
18301 /* constant is not infinite */
18302 else
18303 {
18304 if( !SCIPisInfinity(scip, REALABS(lhs)) )
18305 lhs -= constant;
18306 if( !SCIPisInfinity(scip, REALABS(rhs)) )
18307 rhs -= constant;
18308
18309 if( SCIPisInfinity(scip, -lhs) )
18310 lhs = -SCIPinfinity(scip);
18311 else if( SCIPisInfinity(scip, lhs) )
18312 lhs = SCIPinfinity(scip);
18313
18314 if( SCIPisInfinity(scip, rhs) )
18315 rhs = SCIPinfinity(scip);
18316 else if( SCIPisInfinity(scip, -rhs) )
18317 rhs = -SCIPinfinity(scip);
18318 }
18319
18320 /* add all active variables to constraint */
18321 for( v = nconsvars - 1; v >= 0; --v )
18322 {
18323 SCIP_CALL( addCoef(scip, cons, consvars[v], consvals[v]) );
18324 }
18325
18326 /* update left and right hand sides */
18327 SCIP_CALL( chgLhs(scip, cons, lhs));
18328 SCIP_CALL( chgRhs(scip, cons, rhs));
18329
18331 SCIPfreeBufferArray(scip, &consvars);
18332 }
18333 else
18334 {
18335 SCIP_CALL( addCoef(scip, cons, var, val) );
18336 }
18337
18338 return SCIP_OKAY;
18339}
18340
18341/** changes coefficient of variable in linear constraint; deletes the variable if coefficient is zero; adds variable if
18342 * not yet contained in the constraint
18343 *
18344 * @note This method may only be called during problem creation stage for an original constraint and variable.
18345 *
18346 * @note This method requires linear time to search for occurences of the variable in the constraint data.
18347 */
18349 SCIP* scip, /**< SCIP data structure */
18350 SCIP_CONS* cons, /**< constraint data */
18351 SCIP_VAR* var, /**< variable of constraint entry */
18352 SCIP_Real val /**< new coefficient of constraint entry */
18353 )
18354{
18355 SCIP_CONSDATA* consdata;
18356 SCIP_VAR** vars;
18357 SCIP_Bool found;
18358 int i;
18359
18360 assert(scip != NULL);
18361 assert(cons != NULL);
18362 assert(var != NULL);
18363
18365 {
18366 SCIPerrorMessage("constraint is not linear\n");
18367 return SCIP_INVALIDDATA;
18368 }
18369
18371 {
18372 SCIPerrorMessage("method may only be called during problem creation stage for original constraints and variables\n");
18373 return SCIP_INVALIDDATA;
18374 }
18375
18376 consdata = SCIPconsGetData(cons);
18377 assert(consdata != NULL);
18378
18379 vars = consdata->vars;
18380 found = FALSE;
18381 i = 0;
18382 while( i < consdata->nvars )
18383 {
18384 if( vars[i] == var )
18385 {
18386 if( found || SCIPisZero(scip, val) )
18387 {
18388 SCIP_CALL( delCoefPos(scip, cons, i) );
18389
18390 /* decrease i by one since otherwise we would skip the coefficient which has been switched to position i */
18391 i--;
18392 }
18393 else
18394 {
18395 SCIP_CALL( chgCoefPos(scip, cons, i, val) );
18396 }
18397 found = TRUE;
18398 }
18399 i++;
18400 }
18401
18402 if( !found && !SCIPisZero(scip, val) )
18403 {
18404 SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
18405 }
18406
18407 return SCIP_OKAY;
18408}
18409
18410/** deletes variable from linear constraint
18411 *
18412 * @note This method may only be called during problem creation stage for an original constraint and variable.
18413 *
18414 * @note This method requires linear time to search for occurences of the variable in the constraint data.
18415 */
18417 SCIP* scip, /**< SCIP data structure */
18418 SCIP_CONS* cons, /**< constraint data */
18419 SCIP_VAR* var /**< variable of constraint entry */
18420 )
18421{
18422 assert(scip != NULL);
18423 assert(cons != NULL);
18424 assert(var != NULL);
18425
18426 SCIP_CALL( SCIPchgCoefLinear(scip, cons, var, 0.0) );
18427
18428 return SCIP_OKAY;
18429}
18430
18431/** gets left hand side of linear constraint */
18433 SCIP* scip, /**< SCIP data structure */
18434 SCIP_CONS* cons /**< constraint data */
18435 )
18436{
18437 SCIP_CONSDATA* consdata;
18438
18439 assert(scip != NULL);
18440 assert(cons != NULL);
18441
18443 {
18444 SCIPerrorMessage("constraint is not linear\n");
18445 SCIPABORT();
18446 return SCIP_INVALID; /*lint !e527*/
18447 }
18448
18449 consdata = SCIPconsGetData(cons);
18450 assert(consdata != NULL);
18451
18452 return consdata->lhs;
18453}
18454
18455/** gets right hand side of linear constraint */
18457 SCIP* scip, /**< SCIP data structure */
18458 SCIP_CONS* cons /**< constraint data */
18459 )
18460{
18461 SCIP_CONSDATA* consdata;
18462
18463 assert(scip != NULL);
18464 assert(cons != NULL);
18465
18467 {
18468 SCIPerrorMessage("constraint is not linear\n");
18469 SCIPABORT();
18470 return SCIP_INVALID; /*lint !e527*/
18471 }
18472
18473 consdata = SCIPconsGetData(cons);
18474 assert(consdata != NULL);
18475
18476 return consdata->rhs;
18477}
18478
18479/** changes left hand side of linear constraint */
18481 SCIP* scip, /**< SCIP data structure */
18482 SCIP_CONS* cons, /**< constraint data */
18483 SCIP_Real lhs /**< new left hand side */
18484 )
18485{
18486 assert(scip != NULL);
18487 assert(cons != NULL);
18488
18490 {
18491 SCIPerrorMessage("constraint is not linear\n");
18492 return SCIP_INVALIDDATA;
18493 }
18494
18495 SCIP_CALL( chgLhs(scip, cons, lhs) );
18496
18497 return SCIP_OKAY;
18498}
18499
18500/** changes right hand side of linear constraint */
18502 SCIP* scip, /**< SCIP data structure */
18503 SCIP_CONS* cons, /**< constraint data */
18504 SCIP_Real rhs /**< new right hand side */
18505 )
18506{
18508 {
18509 SCIPerrorMessage("constraint is not linear\n");
18510 return SCIP_INVALIDDATA;
18511 }
18512
18513 SCIP_CALL( chgRhs(scip, cons, rhs) );
18514
18515 return SCIP_OKAY;
18516}
18517
18518/** gets the number of variables in the linear constraint */
18520 SCIP* scip, /**< SCIP data structure */
18521 SCIP_CONS* cons /**< constraint data */
18522 )
18523{
18524 SCIP_CONSDATA* consdata;
18525
18526 assert(scip != NULL);
18527 assert(cons != NULL);
18528
18530 {
18531 SCIPerrorMessage("constraint is not linear\n");
18532 SCIPABORT();
18533 return -1; /*lint !e527*/
18534 }
18535
18536 consdata = SCIPconsGetData(cons);
18537 assert(consdata != NULL);
18538
18539 return consdata->nvars;
18540}
18541
18542/** gets the array of variables in the linear constraint; the user must not modify this array! */
18544 SCIP* scip, /**< SCIP data structure */
18545 SCIP_CONS* cons /**< constraint data */
18546 )
18547{
18548 SCIP_CONSDATA* consdata;
18549
18550 assert(scip != NULL);
18551 assert(cons != NULL);
18552
18554 {
18555 SCIPerrorMessage("constraint is not linear\n");
18556 SCIPABORT();
18557 return NULL; /*lint !e527*/
18558 }
18559
18560 consdata = SCIPconsGetData(cons);
18561 assert(consdata != NULL);
18562
18563 return consdata->vars;
18564}
18565
18566/** gets the array of coefficient values in the linear constraint; the user must not modify this array! */
18568 SCIP* scip, /**< SCIP data structure */
18569 SCIP_CONS* cons /**< constraint data */
18570 )
18571{
18572 SCIP_CONSDATA* consdata;
18573
18574 assert(scip != NULL);
18575 assert(cons != NULL);
18576
18578 {
18579 SCIPerrorMessage("constraint is not linear\n");
18580 SCIPABORT();
18581 return NULL; /*lint !e527*/
18582 }
18583
18584 consdata = SCIPconsGetData(cons);
18585 assert(consdata != NULL);
18586
18587 return consdata->vals;
18588}
18589
18590/** gets the activity of the linear constraint in the given solution
18591 *
18592 * @note if the solution contains values at infinity, this method will return SCIP_INVALID in case the activity
18593 * comprises positive and negative infinity contributions
18594 */
18596 SCIP* scip, /**< SCIP data structure */
18597 SCIP_CONS* cons, /**< constraint data */
18598 SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18599 )
18600{
18601 SCIP_CONSDATA* consdata;
18602
18603 assert(scip != NULL);
18604 assert(cons != NULL);
18605
18607 {
18608 SCIPerrorMessage("constraint is not linear\n");
18609 SCIPABORT();
18610 return SCIP_INVALID; /*lint !e527*/
18611 }
18612
18613 consdata = SCIPconsGetData(cons);
18614 assert(consdata != NULL);
18615
18616 if( consdata->row != NULL )
18617 return SCIPgetRowSolActivity(scip, consdata->row, sol);
18618 else
18619 return consdataGetActivity(scip, consdata, sol);
18620}
18621
18622/** gets the feasibility of the linear constraint in the given solution */
18624 SCIP* scip, /**< SCIP data structure */
18625 SCIP_CONS* cons, /**< constraint data */
18626 SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18627 )
18628{
18629 SCIP_CONSDATA* consdata;
18630
18631 assert(scip != NULL);
18632 assert(cons != NULL);
18633
18635 {
18636 SCIPerrorMessage("constraint is not linear\n");
18637 SCIPABORT();
18638 return SCIP_INVALID; /*lint !e527*/
18639 }
18640
18641 consdata = SCIPconsGetData(cons);
18642 assert(consdata != NULL);
18643
18644 if( consdata->row != NULL )
18645 return SCIPgetRowSolFeasibility(scip, consdata->row, sol);
18646 else
18647 return consdataGetFeasibility(scip, consdata, sol);
18648}
18649
18650/** gets the dual solution of the linear constraint in the current LP */
18652 SCIP* scip, /**< SCIP data structure */
18653 SCIP_CONS* cons /**< constraint data */
18654 )
18655{
18656 SCIP_CONSDATA* consdata;
18657
18658 assert(scip != NULL);
18659 assert(cons != NULL);
18660 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18661
18663 {
18664 SCIPerrorMessage("constraint is not linear\n");
18665 SCIPABORT();
18666 return SCIP_INVALID; /*lint !e527*/
18667 }
18668
18669 consdata = SCIPconsGetData(cons);
18670 assert(consdata != NULL);
18671
18672 if( consdata->row != NULL )
18673 return SCIProwGetDualsol(consdata->row);
18674 else
18675 return 0.0;
18676}
18677
18678/** gets the dual Farkas value of the linear constraint in the current infeasible LP */
18680 SCIP* scip, /**< SCIP data structure */
18681 SCIP_CONS* cons /**< constraint data */
18682 )
18683{
18684 SCIP_CONSDATA* consdata;
18685
18686 assert(scip != NULL);
18687 assert(cons != NULL);
18688 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18689
18691 {
18692 SCIPerrorMessage("constraint is not linear\n");
18693 SCIPABORT();
18694 return SCIP_INVALID; /*lint !e527*/
18695 }
18696
18697 consdata = SCIPconsGetData(cons);
18698 assert(consdata != NULL);
18699
18700 if( consdata->row != NULL )
18701 return SCIProwGetDualfarkas(consdata->row);
18702 else
18703 return 0.0;
18704}
18705
18706/** returns the linear relaxation of the given linear constraint; may return NULL if no LP row was yet created;
18707 * the user must not modify the row!
18708 */
18710 SCIP* scip, /**< SCIP data structure */
18711 SCIP_CONS* cons /**< constraint data */
18712 )
18713{
18714 SCIP_CONSDATA* consdata;
18715
18716 assert(scip != NULL);
18717 assert(cons != NULL);
18718
18720 {
18721 SCIPerrorMessage("constraint is not linear\n");
18722 SCIPABORT();
18723 return NULL; /*lint !e527*/
18724 }
18725
18726 consdata = SCIPconsGetData(cons);
18727 assert(consdata != NULL);
18728
18729 return consdata->row;
18730}
18731
18732/** tries to automatically convert a linear constraint into a more specific and more specialized constraint */
18734 SCIP* scip, /**< SCIP data structure */
18735 SCIP_CONS* cons, /**< source constraint to try to convert */
18736 SCIP_CONS** upgdcons /**< pointer to store upgraded constraint, or NULL if not successful */
18737 )
18738{
18739 SCIP_CONSHDLR* conshdlr;
18740 SCIP_CONSHDLRDATA* conshdlrdata;
18741 SCIP_CONSDATA* consdata;
18742 SCIP_VAR* var;
18743 SCIP_Real val;
18744 SCIP_Real lb;
18745 SCIP_Real ub;
18746 SCIP_Real poscoeffsum;
18747 SCIP_Real negcoeffsum;
18748 SCIP_Bool infeasible;
18749 SCIP_Bool integral;
18750 int nchgsides = 0;
18751 int nposbin;
18752 int nnegbin;
18753 int nposint;
18754 int nnegint;
18755 int nposimpl;
18756 int nnegimpl;
18757 int nposimplbin;
18758 int nnegimplbin;
18759 int nposcont;
18760 int nnegcont;
18761 int ncoeffspone;
18762 int ncoeffsnone;
18763 int ncoeffspint;
18764 int ncoeffsnint;
18765 int ncoeffspfrac;
18766 int ncoeffsnfrac;
18767 int i;
18768
18769 assert(scip != NULL);
18770 assert(cons != NULL);
18771 assert(upgdcons != NULL);
18772
18773 *upgdcons = NULL;
18774
18775 /* we cannot upgrade a modifiable linear constraint, since we don't know what additional coefficients to expect */
18776 if( SCIPconsIsModifiable(cons) )
18777 return SCIP_OKAY;
18778
18779 /* check for upgradability */
18780 if( SCIPconsGetNUpgradeLocks(cons) > 0 )
18781 return SCIP_OKAY;
18782
18783 /* get the constraint handler and check, if it's really a linear constraint */
18784 conshdlr = SCIPconsGetHdlr(cons);
18785 if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
18786 {
18787 SCIPerrorMessage("constraint is not linear\n");
18788 return SCIP_INVALIDDATA;
18789 }
18790
18791 /* get constraint handler data and constraint data */
18792 conshdlrdata = SCIPconshdlrGetData(conshdlr);
18793 assert(conshdlrdata != NULL);
18794 consdata = SCIPconsGetData(cons);
18795 assert(consdata != NULL);
18796
18797 /* check, if the constraint was already upgraded and will be deleted anyway after preprocessing */
18798 if( consdata->upgraded )
18799 return SCIP_OKAY;
18800
18801 /* check, if the constraint is already stored as LP row */
18802 if( consdata->row != NULL )
18803 {
18804 if( SCIProwIsInLP(consdata->row) )
18805 {
18806 SCIPerrorMessage("cannot upgrade linear constraint that is already stored as row in the LP\n");
18807 return SCIP_INVALIDDATA;
18808 }
18809 else
18810 {
18811 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
18812 }
18813 }
18814
18815 /* normalize constraint */
18816 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
18817
18818 /* normalizeCons() can only detect infeasibility when scaling with the gcd. in that case, the scaling was
18819 * skipped and we hope that the infeasibility gets detected later again.
18820 *
18821 * TODO: do we want to try to upgrade the constraint anyway?
18822 *
18823 * TODO: this needs to be fixed on master by changing the API and passing a pointer to whether the constraint is
18824 * proven to be infeasible.
18825 */
18826 if( infeasible ) /*lint !e774*/
18827 return SCIP_OKAY;
18828
18829 /* tighten sides */
18830 SCIP_CALL( tightenSides(scip, cons, &nchgsides, &infeasible) );
18831
18832 if( infeasible ) /*lint !e774*/
18833 return SCIP_OKAY;
18834
18835 /*
18836 * calculate some statistics on linear constraint
18837 */
18838
18839 nposbin = 0;
18840 nnegbin = 0;
18841 nposint = 0;
18842 nnegint = 0;
18843 nposimpl = 0;
18844 nnegimpl = 0;
18845 nposimplbin = 0;
18846 nnegimplbin = 0;
18847 nposcont = 0;
18848 nnegcont = 0;
18849 ncoeffspone = 0;
18850 ncoeffsnone = 0;
18851 ncoeffspint = 0;
18852 ncoeffsnint = 0;
18853 ncoeffspfrac = 0;
18854 ncoeffsnfrac = 0;
18855 integral = TRUE;
18856 poscoeffsum = 0.0;
18857 negcoeffsum = 0.0;
18858
18859 for( i = 0; i < consdata->nvars; ++i )
18860 {
18861 var = consdata->vars[i];
18862 val = consdata->vals[i];
18863 lb = SCIPvarGetLbLocal(var);
18864 ub = SCIPvarGetUbLocal(var);
18865 assert(!SCIPisZero(scip, val));
18866
18867 switch( SCIPvarGetType(var) )
18868 {
18870 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18871 integral = integral && SCIPisIntegral(scip, val);
18872 if( val >= 0.0 )
18873 nposbin++;
18874 else
18875 nnegbin++;
18876 break;
18878 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18879 integral = integral && SCIPisIntegral(scip, val);
18880 if( val >= 0.0 )
18881 nposint++;
18882 else
18883 nnegint++;
18884 break;
18886 if( SCIPvarIsBinary(var) )
18887 {
18888 if( val >= 0.0 )
18889 nposimplbin++;
18890 else
18891 nnegimplbin++;
18892 }
18893 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18894 integral = integral && SCIPisIntegral(scip, val);
18895 if( val >= 0.0 )
18896 nposimpl++;
18897 else
18898 nnegimpl++;
18899 break;
18901 integral = integral && SCIPisEQ(scip, lb, ub) && SCIPisIntegral(scip, val * lb);
18902 if( val >= 0.0 )
18903 nposcont++;
18904 else
18905 nnegcont++;
18906 break;
18907 default:
18908 SCIPerrorMessage("unknown variable type\n");
18909 return SCIP_INVALIDDATA;
18910 }
18911 if( SCIPisEQ(scip, val, 1.0) )
18912 ncoeffspone++;
18913 else if( SCIPisEQ(scip, val, -1.0) )
18914 ncoeffsnone++;
18915 else if( SCIPisIntegral(scip, val) )
18916 {
18917 if( SCIPisPositive(scip, val) )
18918 ncoeffspint++;
18919 else
18920 ncoeffsnint++;
18921 }
18922 else
18923 {
18924 if( SCIPisPositive(scip, val) )
18925 ncoeffspfrac++;
18926 else
18927 ncoeffsnfrac++;
18928 }
18929 if( SCIPisPositive(scip, val) )
18930 poscoeffsum += val;
18931 else
18932 negcoeffsum += val;
18933 }
18934
18935 /*
18936 * call the upgrading methods
18937 */
18938
18939 SCIPdebugMsg(scip, "upgrading linear constraint <%s> (%d upgrade methods):\n",
18940 SCIPconsGetName(cons), conshdlrdata->nlinconsupgrades);
18941 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",
18944 poscoeffsum, negcoeffsum, integral);
18945
18946 /* try all upgrading methods in priority order in case the upgrading step is enable */
18947 for( i = 0; i < conshdlrdata->nlinconsupgrades && *upgdcons == NULL; ++i )
18948 {
18949 if( conshdlrdata->linconsupgrades[i]->active )
18950 {
18951 SCIP_CALL( conshdlrdata->linconsupgrades[i]->linconsupgd(scip, cons, consdata->nvars,
18952 consdata->vars, consdata->vals, consdata->lhs, consdata->rhs,
18955 poscoeffsum, negcoeffsum, integral,
18956 upgdcons) );
18957 }
18958 }
18959
18960#ifdef SCIP_DEBUG
18961 if( *upgdcons != NULL )
18962 {
18964 SCIPdebugMsg(scip, " -> upgraded to constraint type <%s>\n", SCIPconshdlrGetName(SCIPconsGetHdlr(*upgdcons)));
18966 }
18967#endif
18968
18969 return SCIP_OKAY; /*lint !e438*/
18970}
18971
18972/** cleans up (multi-)aggregations and fixings from linear constraints */
18974 SCIP* scip, /**< SCIP data structure */
18975 SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
18976 SCIP_Bool* infeasible /**< pointer to return whether the problem was detected to be infeasible */
18977 )
18978{
18979 SCIP_CONSHDLR* conshdlr;
18980 SCIP_CONS** conss;
18981 int nconss;
18982 int i;
18983
18984 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
18985 if( conshdlr == NULL )
18986 return SCIP_OKAY;
18987
18988 assert(infeasible != NULL);
18989 *infeasible = FALSE;
18990
18992 conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);
18993
18994 for( i = 0; i < nconss; ++i )
18995 {
18996 SCIP_CALL( applyFixings(scip, conss[i], infeasible) );
18997
18998 if( *infeasible )
18999 break;
19000 }
19001
19002 return SCIP_OKAY;
19003}
static long bound
SCIP_VAR * w
SCIP_VAR * a
SCIP_VAR ** b
SCIP_VAR ** x
enum Proprule PROPRULE
Definition cons_and.c:176
Proprule
Definition cons_and.c:169
struct InferInfo INFERINFO
Constraint handler for knapsack constraints of the form , x binary and .
#define MAX_CLIQUE_NONZEROS_PER_CONS
enum Proprule PROPRULE
static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
#define DEFAULT_AGGREGATEVARIABLES
static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file)
#define DEFAULT_NMINCOMPARISONS
#define DEFAULT_MULTAGGRREMOVE
#define DEFAULT_DUALPRESOLVING
#define DEFAULT_EXTRACTCLIQUES
static void permSortConsdata(SCIP_CONSDATA *consdata, int *perm, int nvars)
#define CONSHDLR_NEEDSCONS
static void consdataRecomputeMaxActivityDelta(SCIP *scip, SCIP_CONSDATA *consdata)
#define CONSHDLR_SEPAFREQ
Definition cons_linear.c:99
static SCIP_RETCODE checkCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool checklprows, SCIP_Bool checkrelmaxabs, SCIP_Bool *violated)
static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff)
#define CONFLICTHDLR_PRIORITY
static void consdataGetReliableResidualActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *cancelvar, SCIP_Real *resactivity, SCIP_Bool isminresact, SCIP_Bool useglobalbounds)
static SCIP_Bool checkEqualObjective(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real *scale, SCIP_Real *offset)
#define CONFLICTHDLR_NAME
#define MAXDNOM
static SCIP_RETCODE conshdlrdataIncludeUpgrade(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_LINCONSUPGRADE *linconsupgrade)
static SCIP_RETCODE extractCliques(SCIP *scip, SCIP_CONS *cons, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, int *nfixedvars, int *nchgbds, SCIP_Bool *cutoff)
static void getMaxActivity(SCIP *scip, SCIP_CONSDATA *consdata, int posinf, int neginf, int poshuge, int neghuge, SCIP_Real delta, SCIP_Bool global, SCIP_Bool goodrelax, SCIP_Real *maxactivity, SCIP_Bool *isrelax, SCIP_Bool *issettoinfinity)
#define CONSHDLR_CHECKPRIORITY
Definition cons_linear.c:98
#define CONSHDLR_DESC
Definition cons_linear.c:95
static SCIP_RETCODE createRow(SCIP *scip, SCIP_CONS *cons)
static int getVarWeight(SCIP_VAR *var)
static SCIP_RETCODE convertBinaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss)
static void consdataRecomputeMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
static SCIP_RETCODE addConflictFixedVars(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, int inferpos)
#define DEFAULT_DETECTCUTOFFBOUND
static SCIP_RETCODE tightenVarLb(SCIP *scip, SCIP_CONS *cons, int pos, PROPRULE proprule, SCIP_Real newlb, SCIP_Real oldlb, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
#define CONSHDLR_PROP_TIMING
static SCIP_Real consdataComputePseudoActivity(SCIP *scip, SCIP_CONSDATA *consdata)
static SCIP_RETCODE conshdlrdataEnsureLinconsupgradesSize(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, int num)
static SCIP_RETCODE retrieveParallelConstraints(SCIP_HASHTABLE *hashtable, SCIP_CONS **querycons, SCIP_CONS **parallelconss, int *nparallelconss)
#define CONFLICTHDLR_DESC
static void conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
static void calculateMinvalAndMaxval(SCIP *scip, SCIP_Real side, SCIP_Real val, SCIP_Real minresactivity, SCIP_Real maxresactivity, SCIP_Real *minval, SCIP_Real *maxval)
static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
static void consdataRecomputeGlbMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
static void consdataGetActivityResiduals(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool goodrelax, SCIP_Real *minresactivity, SCIP_Real *maxresactivity, SCIP_Bool *minisrelax, SCIP_Bool *maxisrelax, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
static void consdataUpdateActivitiesUb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldub, SCIP_Real newub, SCIP_Real val, SCIP_Bool checkreliability)
static SCIP_RETCODE tightenSides(SCIP *scip, SCIP_CONS *cons, int *nchgsides, SCIP_Bool *infeasible)
static void consdataUpdateActivitiesGlbLb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real val, SCIP_Bool checkreliability)
static void consdataUpdateActivitiesLb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real val, SCIP_Bool checkreliability)
#define CONSHDLR_MAXPREROUNDS
static SCIP_Bool conshdlrdataHasUpgrade(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_DECL_LINCONSUPGD((*linconsupgd)), const char *conshdlrname)
static SCIP_RETCODE chgCoefPos(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Real newval)
static void consdataRecomputeMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
static SCIP_RETCODE linconsupgradeCreate(SCIP *scip, SCIP_LINCONSUPGRADE **linconsupgrade, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority)
#define DEFAULT_PRESOLPAIRWISE
#define DEFAULT_MAXAGGRNORMSCALE
static SCIP_RETCODE performVarDeletions(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss)
#define checkMaxActivityDelta(scip, consdata)
#define CONSHDLR_SEPAPRIORITY
Definition cons_linear.c:96
static SCIP_Bool isFiniteNonnegativeIntegral(SCIP *scip, SCIP_Real x)
#define DEFAULT_SINGLETONSTUFFING
#define DEFAULT_MAXROUNDSROOT
static void consdataUpdateSignatures(SCIP_CONSDATA *consdata, int pos)
#define MINVALRECOMP
#define DEFAULT_MAXCARDBOUNDDIST
#define DEFAULT_MAXEASYACTIVITYDELTA
static SCIP_RETCODE scaleCons(SCIP *scip, SCIP_CONS *cons, SCIP_Real scalar)
static int inferInfoGetPos(INFERINFO inferinfo)
static SCIP_RETCODE detectRedundantConstraints(SCIP *scip, BMS_BLKMEM *blkmem, SCIP_CONS **conss, int nconss, int *firstchange, SCIP_Bool *cutoff, int *ndelconss, int *nchgsides)
static void consdataGetActivityBounds(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Bool goodrelax, SCIP_Real *minactivity, SCIP_Real *maxactivity, SCIP_Bool *minisrelax, SCIP_Bool *maxisrelax, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
#define DEFAULT_CHECKRELMAXABS
#define DEFAULT_MAXDUALMULTAGGRQUOT
static void linconsupgradeFree(SCIP *scip, SCIP_LINCONSUPGRADE **linconsupgrade)
static SCIP_RETCODE aggregateConstraints(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1, int *commonidx0, int *commonidx1, int *diffidx0minus1, int *diffidx1minus0, int nvarscommon, int commonidxweight, int diffidx0minus1weight, int diffidx1minus0weight, SCIP_Real maxaggrnormscale, int *nchgcoefs, SCIP_Bool *aggregated, SCIP_Bool *infeasible)
static SCIP_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons, SCIP_Bool reasonisrhs)
static SCIP_RETCODE rangedRowPropagation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *nchgbds, int *naddconss)
static INFERINFO intToInferInfo(int i)
static SCIP_RETCODE mergeMultiples(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE separateCons(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_SOL *sol, SCIP_Bool separatecards, SCIP_Bool separateall, int *ncuts, SCIP_Bool *cutoff)
static SCIP_RETCODE convertLongEquality(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_CONS *cons, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss)
static void consdataCheckNonbinvar(SCIP_CONSDATA *consdata)
static SCIP_RETCODE chgLhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
#define DEFAULT_SORTVARS
#define DEFAULT_MAXMULTAGGRQUOT
static void consdataUpdateActivitiesGlbUb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldub, SCIP_Real newub, SCIP_Real val, SCIP_Bool checkreliability)
static void consdataGetGlbActivityBounds(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Bool goodrelax, SCIP_Real *glbminactivity, SCIP_Real *glbmaxactivity, SCIP_Bool *minisrelax, SCIP_Bool *maxisrelax, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
static SCIP_RETCODE consCatchEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
static void consdataCalcMinAbsval(SCIP_CONSDATA *consdata)
static SCIP_RETCODE addConflictBounds(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, int inferpos, SCIP_Bool reasonisrhs)
#define MAXCONSPRESOLROUNDS
static SCIP_RETCODE consdataEnsureVarsSize(SCIP *scip, SCIP_CONSDATA *consdata, int num)
#define MAXACTVAL
#define NONLINCONSUPGD_PRIORITY
#define DEFAULT_MAXSEPACUTSROOT
@ PROPRULE_1_RANGEDROW
@ PROPRULE_1_LHS
@ PROPRULE_INVALID
@ PROPRULE_1_RHS
static SCIP_RETCODE tightenBounds(SCIP *scip, SCIP_CONS *cons, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, SCIP_Bool *cutoff, int *nchgbds)
static void consdataCalcMaxAbsval(SCIP_CONSDATA *consdata)
#define DEFAULT_RANGEDROWPROPAGATION
static SCIP_RETCODE consDropAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
#define DEFAULT_PRESOLUSEHASHING
static SCIP_Real consdataGetActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
static SCIP_RETCODE consdataTightenCoefs(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides)
static SCIP_RETCODE normalizeCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
static SCIP_RETCODE presolStuffing(SCIP *scip, SCIP_CONS *cons, SCIP_Bool singletonstuffing, SCIP_Bool singlevarstuffing, SCIP_Bool *cutoff, int *nfixedvars, int *nchgbds)
static SCIP_RETCODE unlockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
static void consdataCalcSignatures(SCIP_CONSDATA *consdata)
static SCIP_RETCODE addConflictReasonVars(SCIP *scip, SCIP_VAR **vars, int nvars, SCIP_VAR *var, SCIP_Real bound)
#define DEFAULT_RANGEDROWFREQ
static SCIP_RETCODE propagateCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool tightenbounds, SCIP_Bool rangedrowpropagation, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, SCIP_Bool *cutoff, int *nchgbds)
static SCIP_RETCODE updateCutoffbound(SCIP *scip, SCIP_CONS *cons, SCIP_Real primalbound)
static void consdataUpdateDelCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
#define DEFAULT_RANGEDROWARTCONS
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, int pos)
#define MAXSCALEDCOEFINTEGER
static void consdataUpdateAddCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
#define BINWEIGHT
static SCIP_RETCODE chgRhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
#define DEFAULT_SIMPLIFYINEQUALITIES
#define CONSHDLR_PROPFREQ
static SCIP_RETCODE tightenVarBoundsEasy(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
static void consdataUpdateActivities(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound, SCIP_Real val, SCIP_BOUNDTYPE boundtype, SCIP_Bool global, SCIP_Bool checkreliability)
static SCIP_RETCODE convertEquality(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss)
static unsigned int getParallelConsKey(SCIP_CONS *cons)
#define CONTWEIGHT
static SCIP_RETCODE fixVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars)
#define CONSHDLR_PRESOLTIMING
#define DEFAULT_DETECTPARTIALOBJECTIVE
static SCIP_RETCODE enforceConstraint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, int nusefulconss, SCIP_SOL *sol, SCIP_RESULT *result)
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
static SCIP_RETCODE dualPresolve(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss)
#define DEFAULT_MAXSEPACUTS
static SCIP_Real consdataGetMaxAbsval(SCIP_CONSDATA *consdata)
static SCIP_RETCODE addNlrow(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE consPrintConsSol(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, FILE *file)
#define CONSHDLR_EAGERFREQ
#define DEFAULT_TIGHTENBOUNDSFREQ
static void getNewSidesAfterAggregation(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *slackvar, SCIP_Real slackcoef, SCIP_Real *newlhs, SCIP_Real *newrhs)
static SCIP_RETCODE convertUnaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *ndelconss)
static void consdataUpdateChgCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldval, SCIP_Real newval, SCIP_Bool checkreliability)
#define EVENTHDLR_DESC
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
static void consdataRecomputeGlbMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
static SCIP_RETCODE applyFixings(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
static void consdataCalcActivities(SCIP *scip, SCIP_CONSDATA *consdata)
#define DEFAULT_MAXROUNDS
#define CONSHDLR_ENFOPRIORITY
Definition cons_linear.c:97
static SCIP_RETCODE tightenVarUb(SCIP *scip, SCIP_CONS *cons, int pos, PROPRULE proprule, SCIP_Real newub, SCIP_Real oldub, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
static int getInferInt(PROPRULE proprule, int pos)
static int inferInfoGetProprule(INFERINFO inferinfo)
#define DEFAULT_MINGAINPERNMINCOMP
static SCIP_Real consdataGetFeasibility(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
static SCIP_RETCODE rangedRowSimplify(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides)
static SCIP_RETCODE aggregateVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars)
#define CONSHDLR_DELAYSEPA
#define MAXSCALEDCOEF
static void consdataInvalidateActivities(SCIP_CONSDATA *consdata)
#define DEFAULT_RANGEDROWMAXDEPTH
static SCIP_RETCODE analyzeConflictRangedRow(SCIP *scip, SCIP_CONS *cons, SCIP_VAR **vars, int nvars, SCIP_VAR *var, SCIP_Real bound)
static SCIP_RETCODE consDropEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
static SCIP_RETCODE tightenVarBounds(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
static SCIP_Real consdataGetMinAbsval(SCIP_CONSDATA *consdata)
#define CONSHDLR_NAME
Definition cons_linear.c:94
static SCIP_Bool consdataIsResidualIntegral(SCIP *scip, SCIP_CONSDATA *consdata, int pos, SCIP_Real val)
static int inferInfoToInt(INFERINFO inferinfo)
static SCIP_RETCODE preprocessConstraintPairs(SCIP *scip, SCIP_CONS **conss, int firstchange, int chkind, SCIP_Real maxaggrnormscale, SCIP_Bool *cutoff, int *ndelconss, int *nchgsides, int *nchgcoefs)
static SCIP_RETCODE consdataSort(SCIP *scip, SCIP_CONSDATA *consdata)
#define DEFAULT_SINGLEVARSTUFFING
#define EVENTHDLR_NAME
#define INTWEIGHT
static SCIP_RETCODE checkParallelObjective(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata)
static SCIP_RETCODE simplifyInequalities(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides, SCIP_Bool *infeasible)
static SCIP_RETCODE consCatchAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
static SCIP_RETCODE resolvePropagation(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, INFERINFO inferinfo, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_RESULT *result)
static SCIP_Bool isRangedRow(SCIP *scip, SCIP_Real lhs, SCIP_Real rhs)
#define DEFAULT_DETECTLOWERBOUND
static SCIP_RETCODE checkPartialObjective(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata)
#define MAXVALRECOMP
#define CONSHDLR_DELAYPROP
static SCIP_Bool canTightenBounds(SCIP_CONS *cons)
#define DEFAULT_SEPARATEALL
static void findOperators(const char *str, char **firstoperator, char **secondoperator, SCIP_Bool *success)
static void getMinActivity(SCIP *scip, SCIP_CONSDATA *consdata, int posinf, int neginf, int poshuge, int neghuge, SCIP_Real delta, SCIP_Bool global, SCIP_Bool goodrelax, SCIP_Real *minactivity, SCIP_Bool *isrelax, SCIP_Bool *issettoinfinity)
static SCIP_RETCODE fullDualPresolve(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_Bool *cutoff, int *nchgbds)
static INFERINFO getInferInfo(PROPRULE proprule, int pos)
static void consdataGetGlbActivityResiduals(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool goodrelax, SCIP_Real *minresactivity, SCIP_Real *maxresactivity, SCIP_Bool *minisrelax, SCIP_Bool *maxisrelax, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
#define MAXTIGHTENROUNDS
Constraint handler for linear constraints in their most general form, .
constraint handler for nonlinear constraints specified by algebraic expressions
defines macros for basic operations in double-double arithmetic giving roughly twice the precision of...
#define QUAD_MEMBER(x)
Definition dbldblarith.h:48
#define SCIPquadprecSumQD(r, a, b)
Definition dbldblarith.h:62
#define QUAD_ASSIGN(a, constant)
Definition dbldblarith.h:51
#define QUAD_ASSIGN_Q(a, b)
Definition dbldblarith.h:52
#define QUAD_TO_DBL(x)
Definition dbldblarith.h:49
methods for debugging
#define SCIPdebugGetSolVal(scip, var, val)
Definition debug.h:299
#define SCIPdebugAddSolVal(scip, var, val)
Definition debug.h:298
#define SCIP_MAXSTRLEN
Definition def.h:302
#define SCIP_Longint
Definition def.h:171
#define SCIP_MAXTREEDEPTH
Definition def.h:330
#define SCIP_REAL_MAX
Definition def.h:187
#define SCIP_INVALID
Definition def.h:206
#define SCIP_Real
Definition def.h:186
#define TRUE
Definition def.h:95
#define FALSE
Definition def.h:96
#define SCIP_CALL_ABORT(x)
Definition def.h:367
#define SCIPABORT()
Definition def.h:360
#define REALABS(x)
Definition def.h:210
#define EPSGT(x, y, eps)
Definition def.h:214
#define SCIP_CALL(x)
Definition def.h:388
SCIP_Real SCIPgetDualsolLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPincludeLinconsUpgrade(SCIP *scip, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority, const char *conshdlrname)
#define SCIP_DECL_NONLINCONSUPGD(x)
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPupgradeConsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_CONS **upgdcons)
SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPchgRhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
SCIP_RETCODE SCIPincludeConsUpgradeNonlinear(SCIP *scip, SCIP_DECL_NONLINCONSUPGD((*nlconsupgd)), int priority, SCIP_Bool active, const char *conshdlrname)
SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_ROW * SCIPgetRowLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsBasicLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
SCIP_EXPR * SCIPgetExprNonlinear(SCIP_CONS *cons)
SCIP_RETCODE SCIPseparateRelaxedKnapsack(SCIP *scip, SCIP_CONS *cons, SCIP_SEPA *sepa, int nknapvars, SCIP_VAR **knapvars, SCIP_Real *knapvals, SCIP_Real valscale, SCIP_Real rhs, SCIP_SOL *sol, SCIP_Bool *cutoff, int *ncuts)
SCIP_Real SCIPgetRhsNonlinear(SCIP_CONS *cons)
SCIP_Real SCIPgetDualfarkasLinear(SCIP *scip, SCIP_CONS *cons)
#define SCIP_DECL_LINCONSUPGD(x)
SCIP_RETCODE SCIPcopyConsLinear(SCIP *scip, SCIP_CONS **cons, SCIP *sourcescip, const char *name, int nvars, SCIP_VAR **sourcevars, SCIP_Real *sourcecoefs, SCIP_Real lhs, SCIP_Real rhs, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode, SCIP_Bool global, SCIP_Bool *valid)
SCIP_RETCODE SCIPcleanupConssLinear(SCIP *scip, SCIP_Bool onlychecked, SCIP_Bool *infeasible)
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_Real SCIPgetActivityLinear(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
SCIP_Real SCIPgetFeasibilityLinear(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
SCIP_RETCODE SCIPclassifyConstraintTypesLinear(SCIP *scip, SCIP_LINCONSSTATS *linconsstats)
SCIP_RETCODE SCIPchgLhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
SCIP_Real SCIPgetLhsNonlinear(SCIP_CONS *cons)
SCIP_RETCODE SCIPchgCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
SCIP_RETCODE SCIPdelCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
SCIP_RETCODE SCIPincludeConshdlrLinear(SCIP *scip)
SCIP_RETCODE SCIPconvertCutsToConss(SCIP *scip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, int *ncutsadded)
Definition scip_copy.c:2068
SCIP_Bool SCIPisConsCompressionEnabled(SCIP *scip)
Definition scip_copy.c:660
SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
Definition scip_copy.c:711
SCIP_Bool SCIPisTransformed(SCIP *scip)
SCIP_Bool SCIPisPresolveFinished(SCIP *scip)
SCIP_Bool SCIPisStopped(SCIP *scip)
SCIP_STAGE SCIPgetStage(SCIP *scip)
int SCIPgetNObjVars(SCIP *scip)
Definition scip_prob.c:2220
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition scip_prob.c:1668
int SCIPgetNContVars(SCIP *scip)
Definition scip_prob.c:2172
SCIP_CONS ** SCIPgetConss(SCIP *scip)
Definition scip_prob.c:3088
SCIP_RETCODE SCIPaddObjoffset(SCIP *scip, SCIP_Real addval)
Definition scip_prob.c:1268
int SCIPgetNVars(SCIP *scip)
Definition scip_prob.c:1992
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition scip_prob.c:2770
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition scip_prob.c:2843
int SCIPgetNConss(SCIP *scip)
Definition scip_prob.c:3042
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition scip_prob.c:1947
int SCIPgetNBinVars(SCIP *scip)
Definition scip_prob.c:2037
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition misc.c:2296
SCIP_RETCODE SCIPhashtableSafeInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition misc.c:2529
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:2246
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition misc.c:2558
#define SCIPhashSeven(a, b, c, d, e, f, g)
Definition pub_misc.h:535
void SCIPhashtablePrintStatistics(SCIP_HASHTABLE *hashtable, SCIP_MESSAGEHDLR *messagehdlr)
Definition misc.c:2754
static INLINE uint32_t SCIPrealHashCode(double x)
Definition pub_misc.h:544
SCIP_RETCODE SCIPhashtableRemove(SCIP_HASHTABLE *hashtable, void *element)
Definition misc.c:2627
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition misc.c:2497
#define SCIPhashSignature64(a)
Definition pub_misc.h:517
SCIP_RETCODE SCIPupdateLocalLowerbound(SCIP *scip, SCIP_Real newbound)
Definition scip_prob.c:3696
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition scip_prob.c:3474
SCIP_Real SCIPgetLocalLowerbound(SCIP *scip)
Definition scip_prob.c:3585
SCIP_RETCODE SCIPaddConflict(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
Definition scip_prob.c:3228
SCIP_RETCODE SCIPaddConsLocal(SCIP *scip, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition scip_prob.c:3393
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
#define SCIPdebugMsgPrint
SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
#define SCIPdebugMsg
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition misc.c:9032
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition misc.c:9284
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition misc.c:9305
SCIP_Real SCIPselectSimpleValue(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom)
Definition misc.c:9735
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition misc.c:11096
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:83
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:139
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:57
SCIP_RETCODE SCIPgetIntParam(SCIP *scip, const char *name, int *value)
Definition scip_param.c:269
int SCIPgetNLPBranchCands(SCIP *scip)
SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
const char * SCIPconflicthdlrGetName(SCIP_CONFLICTHDLR *conflicthdlr)
Definition conflict.c:772
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:4615
void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
Definition cons.c:4210
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:366
SCIP_RETCODE SCIPsetConshdlrActive(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:664
SCIP_CONS ** SCIPconshdlrGetCheckConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4572
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition scip_cons.c:534
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:229
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition scip_cons.c:275
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:317
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:175
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:802
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:825
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:779
int SCIPconshdlrGetPropFreq(SCIP_CONSHDLR *conshdlr)
Definition cons.c:5099
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4595
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4180
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)),)
Definition scip_cons.c:341
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition scip_cons.c:886
SCIP_RETCODE SCIPsetConshdlrInit(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:390
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:572
SCIP_RETCODE SCIPsetConshdlrInitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:438
SCIP_RETCODE SCIPsetConshdlrDeactive(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:687
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4200
int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4629
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:595
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:641
SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:510
SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:462
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4552
SCIP_RETCODE SCIPsetConshdlrDelvars(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:756
SCIP_RETCODE SCIPsetConshdlrExit(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:414
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:618
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:848
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition cons.c:8118
int SCIPconsGetPos(SCIP_CONS *cons)
Definition cons.c:8098
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition cons.c:8347
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition cons.c:8108
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition cons.c:8257
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition scip_cons.c:2482
int SCIPconsGetNUpgradeLocks(SCIP_CONS *cons)
Definition cons.c:8539
SCIP_RETCODE SCIPsetConsSeparated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool separate)
Definition scip_cons.c:1242
SCIP_Bool SCIPconsIsMarkedPropagate(SCIP_CONS *cons)
Definition cons.c:8297
SCIP_Bool SCIPconsIsOriginal(SCIP_CONS *cons)
Definition cons.c:8387
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition cons.c:8287
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition cons.c:8217
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition cons.c:8397
int SCIPconsGetNLocksPos(SCIP_CONS *cons)
Definition cons.c:8437
SCIP_RETCODE SCIPsetConsInitial(SCIP *scip, SCIP_CONS *cons, SCIP_Bool initial)
Definition scip_cons.c:1217
SCIP_RETCODE SCIPsetConsEnforced(SCIP *scip, SCIP_CONS *cons, SCIP_Bool enforce)
Definition scip_cons.c:1267
SCIP_Bool SCIPconsIsLockedType(SCIP_CONS *cons, SCIP_LOCKTYPE locktype)
Definition cons.c:8481
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition cons.c:8277
SCIP_RETCODE SCIPunmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition scip_cons.c:1988
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition cons.c:8149
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:943
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition cons.c:8307
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition cons.c:8327
int SCIPconsGetNLocksNeg(SCIP_CONS *cons)
Definition cons.c:8447
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition cons.c:8088
SCIP_Bool SCIPconsIsLocked(SCIP_CONS *cons)
Definition cons.c:8427
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition scip_cons.c:1758
SCIP_RETCODE SCIPmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition scip_cons.c:1960
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition cons.c:8337
SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
Definition scip_cons.c:1470
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition cons.c:8367
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition scip_cons.c:1119
SCIP_RETCODE SCIPsetConsPropagated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool propagate)
Definition scip_cons.c:1317
SCIP_RETCODE SCIPsetConsChecked(SCIP *scip, SCIP_CONS *cons, SCIP_Bool check)
Definition scip_cons.c:1292
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition cons.c:8267
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition scip_cons.c:1730
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition cons.c:8357
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition scip_cut.c:250
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition scip_event.c:104
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition event.c:324
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition event.c:1030
SCIP_VARTYPE SCIPeventGetNewtype(SCIP_EVENT *event)
Definition event.c:1283
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition scip_event.c:354
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition scip_event.c:400
SCIP_Real SCIPeventGetOldbound(SCIP_EVENT *event)
Definition event.c:1218
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition event.c:1053
SCIP_Real SCIPeventGetNewbound(SCIP_EVENT *event)
Definition event.c:1242
SCIP_VARTYPE SCIPeventGetOldtype(SCIP_EVENT *event)
Definition event.c:1266
int SCIPexprGetNChildren(SCIP_EXPR *expr)
Definition expr.c:3801
SCIP_Bool SCIPisExprSum(SCIP *scip, SCIP_EXPR *expr)
Definition scip_expr.c:1443
SCIP_Real * SCIPgetCoefsExprSum(SCIP_EXPR *expr)
Definition expr_sum.c:1166
SCIP_Bool SCIPisExprVar(SCIP *scip, SCIP_EXPR *expr)
Definition scip_expr.c:1421
SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
Definition expr.c:3811
SCIP_Real SCIPgetConstantExprSum(SCIP_EXPR *expr)
Definition expr_sum.c:1181
SCIP_VAR * SCIPgetVarExprVar(SCIP_EXPR *expr)
Definition expr_var.c:416
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition scip_lp.c:83
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:110
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition scip_mem.c:139
#define SCIPallocBufferArray(scip, ptr, num)
Definition scip_mem.h:124
#define SCIPreallocBufferArray(scip, ptr, num)
Definition scip_mem.h:128
#define SCIPfreeBufferArray(scip, ptr)
Definition scip_mem.h:136
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition scip_mem.h:132
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:93
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition scip_mem.h:99
#define SCIPfreeBlockMemory(scip, ptr)
Definition scip_mem.h:108
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition scip_mem.h:111
#define SCIPallocBlockMemory(scip, ptr)
Definition scip_mem.h:89
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition scip_mem.h:105
SCIP_RETCODE SCIPdelNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition scip_nlp.c:391
SCIP_RETCODE SCIPaddNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition scip_nlp.c:363
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition scip_nlp.c:110
SCIP_RETCODE SCIPreleaseNlRow(SCIP *scip, SCIP_NLROW **nlrow)
Definition scip_nlp.c:1025
SCIP_Bool SCIPnlrowIsInNLP(SCIP_NLROW *nlrow)
Definition nlp.c:1872
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:921
SCIP_Bool SCIPinProbing(SCIP *scip)
void SCIPlinConsStatsIncTypeCount(SCIP_LINCONSSTATS *linconsstats, SCIP_LINCONSTYPE linconstype, int increment)
Definition cons.c:7982
void SCIPlinConsStatsReset(SCIP_LINCONSSTATS *linconsstats)
Definition cons.c:7950
SCIP_Bool SCIProwIsModifiable(SCIP_ROW *row)
Definition lp.c:17411
SCIP_RETCODE SCIPchgRowLhs(SCIP *scip, SCIP_ROW *row, SCIP_Real lhs)
Definition scip_lp.c:1583
SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONS *cons, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition scip_lp.c:1422
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition scip_lp.c:1701
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition scip_lp.c:2212
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition scip_lp.c:2167
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition scip_lp.c:1562
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition lp.c:17325
SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
Definition scip_lp.c:1607
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition lp.c:17523
SCIP_RETCODE SCIPaddVarsToRow(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition scip_lp.c:1727
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition lp.c:17312
SCIP_Real SCIPgetRowSolActivity(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition scip_lp.c:2144
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition scip_sol.c:1361
void SCIPupdateSolLPConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
Definition scip_sol.c:285
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:670
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition var.c:17442
SCIP_RETCODE SCIPgetProbvarLinearSum(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize, SCIP_Bool mergemultiples)
Definition scip_var.c:1738
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition scip_var.c:5203
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition var.c:12763
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition var.c:17462
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition var.c:17737
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition scip_var.c:4351
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition var.c:17704
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition var.c:18012
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition var.c:17716
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition var.c:17570
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition var.c:17421
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:6921
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition scip_var.c:1480
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition var.c:17360
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:3353
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition var.c:17656
SCIP_Bool SCIPdoNotAggr(SCIP *scip)
Definition scip_var.c:8565
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:17966
SCIP_Bool SCIPdoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:8598
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition var.c:17383
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:8401
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:5615
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition var.c:17748
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition var.c:17644
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition scip_var.c:5320
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition var.c:17406
SCIP_RETCODE SCIPgetProbvarSum(SCIP *scip, SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition scip_var.c:1794
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition var.c:17910
int SCIPvarGetIndex(SCIP_VAR *var)
Definition var.c:17580
SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
Definition scip_var.c:4259
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition scip_var.c:4437
SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition scip_var.c:2128
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition var.c:17590
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:17241
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:8535
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:18502
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition scip_var.c:1248
SCIP_Real SCIPadjustedVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real ub)
Definition scip_var.c:4645
SCIP_RETCODE SCIPparseVarsLinearsum(SCIP *scip, const char *str, SCIP_VAR **vars, SCIP_Real *vals, int *nvars, int varssize, int *requiredsize, char **endptr, SCIP_Bool *success)
Definition scip_var.c:704
SCIP_Real SCIPadjustedVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real lb)
Definition scip_var.c:4613
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition var.c:17432
SCIP_RETCODE SCIPchgVarType(SCIP *scip, SCIP_VAR *var, SCIP_VARTYPE vartype, SCIP_Bool *infeasible)
Definition scip_var.c:8176
SCIP_RETCODE SCIPflattenVarAggregationGraph(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:1693
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition var.c:17680
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition var.c:17668
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:6780
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition var.c:17452
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:17956
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition var.c:17396
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition var.c:17528
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition var.c:17726
SCIP_RETCODE SCIPcreateVar(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition scip_var.c:114
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition var.c:17370
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition var.c:17900
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition scip_var.c:8276
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:5501
SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition scip_var.c:1992
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition var.c:11931
SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
Definition scip_var.c:230
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition scip_var.c:4513
SCIP_RETCODE SCIPwriteVarsLinearsum(SCIP *scip, FILE *file, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_Bool type)
Definition scip_var.c:343
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:18492
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:3295
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition scip_var.c:1439
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:1214
SCIP_Bool SCIPallowStrongDualReds(SCIP *scip)
Definition scip_var.c:8629
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:5432
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition var.c:17692
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition var.c:17632
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:5450
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition misc.c:10788
SCIP_RETCODE SCIPskipSpace(char **s)
Definition misc.c:10777
return SCIP_OKAY
int c
int depth
SCIP_Bool cutoff
SCIP_Real objval
static SCIP_SOL * sol
SCIP_Real obj
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
SCIP_VAR * var
SCIP_Real frac
static SCIP_Bool propagate
static SCIP_VAR ** vars
SCIP_Real alpha
int nbinvars
int nintvars
static const SCIP_Real scalars[]
Definition lp.c:5743
static const char * paramname[]
Definition lpi_msk.c:5096
#define NULL
Definition lpi_spx1.cpp:161
memory allocation routines
#define BMScopyMemoryArray(ptr, source, num)
Definition memory.h:136
#define BMSclearMemoryArray(ptr, num)
Definition memory.h:132
struct BMS_BlkMem BMS_BLKMEM
Definition memory.h:439
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition message.c:618
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition scip_mem.c:57
public methods for conflict analysis handlers
public methods for managing constraints
public methods for managing events
public functions to work with algebraic expressions
public methods for LP management
public methods for message output
#define SCIPerrorMessage
Definition pub_message.h:64
#define SCIPstatisticMessage
#define SCIPdebug(x)
Definition pub_message.h:93
#define SCIPdebugPrintCons(x, y, z)
#define SCIPdebugMessage
Definition pub_message.h:96
public data structures and miscellaneous methods
methods for sorting joint arrays of various types
public methods for problem variables
public methods for branching rule plugins and branching
public methods for conflict handler plugins and conflict analysis
public methods for constraint handler plugins and constraints
public methods for problem copies
public methods for cuts and aggregation rows
public methods for event handler plugins and event handlers
general public methods
public methods for the LP relaxation, rows and columns
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for the probing mode
public methods for solutions
public methods for querying solving statistics
public methods for the branch-and-bound tree
public methods for SCIP variables
SCIP_DECL_LINCONSUPGD((*linconsupgd))
#define MAX(x, y)
Definition tclique_def.h:92
#define SCIP_DECL_CONFLICTEXEC(x)
@ SCIP_CONFTYPE_PROPAGATION
#define SCIP_DECL_CONSENFOLP(x)
Definition type_cons.h:362
#define SCIP_DECL_CONSDELETE(x)
Definition type_cons.h:228
#define SCIP_DECL_CONSEXIT(x)
Definition type_cons.h:135
#define SCIP_DECL_CONSGETVARS(x)
Definition type_cons.h:865
#define SCIP_DECL_CONSINITSOL(x)
Definition type_cons.h:200
#define SCIP_DECL_CONSPRINT(x)
Definition type_cons.h:767
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition type_cons.h:64
#define SCIP_DECL_CONSSEPALP(x)
Definition type_cons.h:287
#define SCIP_DECL_CONSENFORELAX(x)
Definition type_cons.h:387
#define SCIP_DECL_CONSPROP(x)
Definition type_cons.h:504
#define SCIP_DECL_CONSGETNVARS(x)
Definition type_cons.h:883
#define SCIP_DECL_CONSRESPROP(x)
Definition type_cons.h:610
@ SCIP_LINCONSTYPE_BINPACKING
Definition type_cons.h:84
@ SCIP_LINCONSTYPE_VARBOUND
Definition type_cons.h:77
@ SCIP_LINCONSTYPE_EMPTY
Definition type_cons.h:72
@ SCIP_LINCONSTYPE_INVKNAPSACK
Definition type_cons.h:82
@ SCIP_LINCONSTYPE_PRECEDENCE
Definition type_cons.h:76
@ SCIP_LINCONSTYPE_AGGREGATION
Definition type_cons.h:75
@ SCIP_LINCONSTYPE_MIXEDBINARY
Definition type_cons.h:87
@ SCIP_LINCONSTYPE_SINGLETON
Definition type_cons.h:74
@ SCIP_LINCONSTYPE_SETCOVERING
Definition type_cons.h:80
@ SCIP_LINCONSTYPE_EQKNAPSACK
Definition type_cons.h:83
@ SCIP_LINCONSTYPE_FREE
Definition type_cons.h:73
@ SCIP_LINCONSTYPE_KNAPSACK
Definition type_cons.h:85
@ SCIP_LINCONSTYPE_SETPARTITION
Definition type_cons.h:78
@ SCIP_LINCONSTYPE_INTKNAPSACK
Definition type_cons.h:86
@ SCIP_LINCONSTYPE_SETPACKING
Definition type_cons.h:79
@ SCIP_LINCONSTYPE_GENERAL
Definition type_cons.h:88
@ SCIP_LINCONSTYPE_CARDINALITY
Definition type_cons.h:81
#define SCIP_DECL_CONSACTIVE(x)
Definition type_cons.h:689
#define SCIP_DECL_CONSENFOPS(x)
Definition type_cons.h:430
#define SCIP_DECL_CONSPARSE(x)
Definition type_cons.h:843
#define SCIP_DECL_CONSTRANS(x)
Definition type_cons.h:238
#define SCIP_DECL_CONSDEACTIVE(x)
Definition type_cons.h:704
#define SCIP_DECL_CONSPRESOL(x)
Definition type_cons.h:559
#define SCIP_DECL_CONSINITLP(x)
Definition type_cons.h:258
#define SCIP_DECL_CONSEXITPRE(x)
Definition type_cons.h:179
#define SCIP_DECL_CONSLOCK(x)
Definition type_cons.h:674
#define SCIP_DECL_CONSCOPY(x)
Definition type_cons.h:808
#define SCIP_DECL_CONSINIT(x)
Definition type_cons.h:125
struct SCIP_ConsData SCIP_CONSDATA
Definition type_cons.h:65
#define SCIP_DECL_CONSCHECK(x)
Definition type_cons.h:473
#define SCIP_DECL_CONSHDLRCOPY(x)
Definition type_cons.h:107
#define SCIP_DECL_CONSEXITSOL(x)
Definition type_cons.h:215
#define SCIP_DECL_CONSFREE(x)
Definition type_cons.h:115
#define SCIP_DECL_CONSSEPASOL(x)
Definition type_cons.h:319
enum SCIP_LinConstype SCIP_LINCONSTYPE
Definition type_cons.h:90
#define SCIP_DECL_CONSDELVARS(x)
Definition type_cons.h:751
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition type_event.h:125
#define SCIP_EVENTTYPE_VARUNLOCKED
Definition type_event.h:73
#define SCIP_EVENTTYPE_TYPECHANGED
Definition type_event.h:86
#define SCIP_EVENTTYPE_GUBCHANGED
Definition type_event.h:76
#define SCIP_EVENTTYPE_GBDCHANGED
Definition type_event.h:120
struct SCIP_EventData SCIP_EVENTDATA
Definition type_event.h:173
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition type_event.h:79
#define SCIP_EVENTTYPE_VARFIXED
Definition type_event.h:72
#define SCIP_EVENTTYPE_VARDELETED
Definition type_event.h:71
#define SCIP_DECL_EVENTEXEC(x)
Definition type_event.h:253
#define SCIP_EVENTTYPE_FORMAT
Definition type_event.h:152
#define SCIP_EVENTTYPE_GLBCHANGED
Definition type_event.h:75
#define SCIP_EVENTTYPE_BOUNDRELAXED
Definition type_event.h:124
#define SCIP_EVENTTYPE_LBCHANGED
Definition type_event.h:121
#define SCIP_EVENTTYPE_UBCHANGED
Definition type_event.h:122
uint64_t SCIP_EVENTTYPE
Definition type_event.h:151
#define SCIP_EVENTTYPE_BOUNDTIGHTENED
Definition type_event.h:123
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition type_event.h:77
@ SCIP_EXPRCURV_LINEAR
Definition type_expr.h:62
@ SCIP_BOUNDTYPE_UPPER
Definition type_lp.h:57
@ SCIP_BOUNDTYPE_LOWER
Definition type_lp.h:56
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition type_lp.h:59
@ SCIP_VERBLEVEL_HIGH
#define SCIP_DECL_HASHKEYEQ(x)
Definition type_misc.h:194
#define SCIP_DECL_SORTINDCOMP(x)
Definition type_misc.h:180
#define SCIP_DECL_HASHGETKEY(x)
Definition type_misc.h:191
#define SCIP_DECL_HASHKEYVAL(x)
Definition type_misc.h:197
@ SCIP_DIDNOTRUN
Definition type_result.h:42
@ SCIP_CUTOFF
Definition type_result.h:48
@ SCIP_FEASIBLE
Definition type_result.h:45
@ SCIP_REDUCEDDOM
Definition type_result.h:51
@ SCIP_DIDNOTFIND
Definition type_result.h:44
@ SCIP_CONSADDED
Definition type_result.h:52
@ SCIP_SEPARATED
Definition type_result.h:49
@ SCIP_SUCCESS
Definition type_result.h:58
@ SCIP_INFEASIBLE
Definition type_result.h:46
enum SCIP_Result SCIP_RESULT
Definition type_result.h:61
@ SCIP_READERROR
@ SCIP_INVALIDDATA
@ SCIP_PLUGINNOTFOUND
enum SCIP_Retcode SCIP_RETCODE
@ SCIP_STAGE_PROBLEM
Definition type_set.h:45
@ SCIP_STAGE_INITSOLVE
Definition type_set.h:52
@ SCIP_STAGE_EXITPRESOLVE
Definition type_set.h:50
@ SCIP_STAGE_SOLVING
Definition type_set.h:53
@ SCIP_STAGE_TRANSFORMING
Definition type_set.h:46
@ SCIP_STAGE_PRESOLVED
Definition type_set.h:51
#define SCIP_PRESOLTIMING_EXHAUSTIVE
Definition type_timing.h:54
#define NLOCKTYPES
Definition type_var.h:94
@ SCIP_VARTYPE_INTEGER
Definition type_var.h:63
@ SCIP_VARTYPE_CONTINUOUS
Definition type_var.h:71
@ SCIP_VARTYPE_IMPLINT
Definition type_var.h:64
@ SCIP_VARTYPE_BINARY
Definition type_var.h:62
@ SCIP_VARSTATUS_ORIGINAL
Definition type_var.h:49
@ SCIP_VARSTATUS_FIXED
Definition type_var.h:52
@ SCIP_VARSTATUS_COLUMN
Definition type_var.h:51
@ SCIP_VARSTATUS_MULTAGGR
Definition type_var.h:54
@ SCIP_VARSTATUS_NEGATED
Definition type_var.h:55
@ SCIP_VARSTATUS_AGGREGATED
Definition type_var.h:53
@ SCIP_VARSTATUS_LOOSE
Definition type_var.h:50
enum SCIP_LockType SCIP_LOCKTYPE
Definition type_var.h:100
@ SCIP_LOCKTYPE_MODEL
Definition type_var.h:97
enum SCIP_Vartype SCIP_VARTYPE
Definition type_var.h:73
enum SCIP_Varstatus SCIP_VARSTATUS
Definition type_var.h:57