SCIP

    Solving Constraint Integer Programs

    cons_linear.c
    Go to the documentation of this file.
    1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    2/* */
    3/* This file is part of the program and library */
    4/* SCIP --- Solving Constraint Integer Programs */
    5/* */
    6/* Copyright (c) 2002-2026 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file cons_linear.c
    26 * @ingroup DEFPLUGINS_CONS
    27 * @brief Constraint handler for linear constraints in their most general form, \f$lhs <= a^T x <= rhs\f$.
    28 * @author Tobias Achterberg
    29 * @author Timo Berthold
    30 * @author Marc Pfetsch
    31 * @author Kati Wolter
    32 * @author Michael Winkler
    33 * @author Gerald Gamrath
    34 * @author Domenico Salvagnin
    35 *
    36 * Linear constraints are separated with a high priority, because they are easy
    37 * to separate. Instead of using the global cut pool, the same effect can be
    38 * implemented by adding linear constraints to the root node, such that they are
    39 * separated each time, the linear constraints are separated. A constraint
    40 * handler, which generates linear constraints in this way should have a lower
    41 * separation priority than the linear constraint handler, and it should have a
    42 * separation frequency that is a multiple of the frequency of the linear
    43 * constraint handler. In this way, it can be avoided to separate the same cut
    44 * twice, because if a separation run of the handler is always preceded by a
    45 * separation of the linear constraints, the priorily added constraints are
    46 * always satisfied.
    47 *
    48 * Linear constraints are enforced and checked with a very low priority. Checking
    49 * of (many) linear constraints is much more involved than checking the solution
    50 * values for integrality. Because we are separating the linear constraints quite
    51 * often, it is only necessary to enforce them for integral solutions. A constraint
    52 * handler which generates pool cuts in its enforcing method should have an
    53 * enforcing priority smaller than that of the linear constraint handler to avoid
    54 * regenerating constraints which already exist.
    55 */
    56
    57/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    58
    60#include "scip/cons_nonlinear.h"
    61#include "scip/cons_knapsack.h"
    62#include "scip/cons_linear.h"
    63#include "scip/debug.h"
    64#include "scip/pub_conflict.h"
    65#include "scip/pub_cons.h"
    66#include "scip/pub_event.h"
    67#include "scip/pub_expr.h"
    68#include "scip/pub_lp.h"
    69#include "scip/pub_message.h"
    70#include "scip/pub_misc.h"
    71#include "scip/pub_misc_sort.h"
    72#include "scip/pub_var.h"
    73#include "scip/scip_branch.h"
    74#include "scip/scip_conflict.h"
    75#include "scip/scip_cons.h"
    76#include "scip/scip_copy.h"
    77#include "scip/scip_cut.h"
    78#include "scip/scip_event.h"
    79#include "scip/scip_general.h"
    80#include "scip/scip_lp.h"
    81#include "scip/scip_mem.h"
    82#include "scip/scip_message.h"
    83#include "scip/scip_numerics.h"
    84#include "scip/scip_param.h"
    85#include "scip/scip_prob.h"
    86#include "scip/scip_probing.h"
    87#include "scip/scip_sol.h"
    89#include "scip/scip_tree.h"
    90#include "scip/scip_var.h"
    91#include "scip/symmetry_graph.h"
    93#include "scip/dbldblarith.h"
    94
    95#define CONSHDLR_NAME "linear"
    96#define CONSHDLR_DESC "linear constraints of the form lhs <= a^T x <= rhs"
    97#define CONSHDLR_SEPAPRIORITY +100000 /**< priority of the constraint handler for separation */
    98#define CONSHDLR_ENFOPRIORITY -1000000 /**< priority of the constraint handler for constraint enforcing */
    99#define CONSHDLR_CHECKPRIORITY -1000000 /**< priority of the constraint handler for checking feasibility */
    100#define CONSHDLR_SEPAFREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
    101#define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
    102#define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
    103 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
    104#define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
    105#define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
    106#define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
    107#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
    108
    109#define CONSHDLR_PRESOLTIMING (SCIP_PRESOLTIMING_FAST | SCIP_PRESOLTIMING_EXHAUSTIVE) /**< presolving timing of the constraint handler (fast, medium, or exhaustive) */
    110#define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
    111
    112#define EVENTHDLR_NAME "linear"
    113#define EVENTHDLR_DESC "bound change event handler for linear constraints"
    114
    115#define CONFLICTHDLR_NAME "linear"
    116#define CONFLICTHDLR_DESC "conflict handler creating linear constraints"
    117#define CONFLICTHDLR_PRIORITY -1000000
    118
    119#define DEFAULT_TIGHTENBOUNDSFREQ 1 /**< multiplier on propagation frequency, how often the bounds are tightened */
    120#define DEFAULT_MAXROUNDS 5 /**< maximal number of separation rounds per node (-1: unlimited) */
    121#define DEFAULT_MAXROUNDSROOT -1 /**< maximal number of separation rounds in the root node (-1: unlimited) */
    122#define DEFAULT_MAXSEPACUTS 50 /**< maximal number of cuts separated per separation round */
    123#define DEFAULT_MAXSEPACUTSROOT 200 /**< maximal number of cuts separated per separation round in root node */
    124#define DEFAULT_PRESOLPAIRWISE TRUE /**< should pairwise constraint comparison be performed in presolving? */
    125#define DEFAULT_PRESOLUSEHASHING TRUE /**< should hash table be used for detecting redundant constraints in advance */
    126#define DEFAULT_NMINCOMPARISONS 200000 /**< number for minimal pairwise presolving comparisons */
    127#define DEFAULT_MINGAINPERNMINCOMP 1e-06 /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise
    128 * comparison round */
    129#define DEFAULT_SORTVARS TRUE /**< should variables be sorted after presolve w.r.t their coefficient absolute for faster
    130 * propagation? */
    131#define DEFAULT_CHECKRELMAXABS FALSE /**< should the violation for a constraint with side 0.0 be checked relative
    132 * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
    133#define DEFAULT_MAXAGGRNORMSCALE 0.0 /**< maximal allowed relative gain in maximum norm for constraint aggregation
    134 * (0.0: disable constraint aggregation) */
    135#define DEFAULT_MAXEASYACTIVITYDELTA 1e6 /**< maximum activity delta to run easy propagation on linear constraint
    136 * (faster, but numerically less stable) */
    137#define DEFAULT_MAXCARDBOUNDDIST 0.0 /**< maximal relative distance from current node's dual bound to primal bound compared
    138 * to best node's dual bound for separating knapsack cardinality cuts */
    139#define DEFAULT_SEPARATEALL FALSE /**< should all constraints be subject to cardinality cut generation instead of only
    140 * the ones with non-zero dual value? */
    141#define DEFAULT_AGGREGATEVARIABLES TRUE /**< should presolving search for redundant variables in equations */
    142#define DEFAULT_SIMPLIFYINEQUALITIES TRUE /**< should presolving try to simplify inequalities */
    143#define DEFAULT_DUALPRESOLVING TRUE /**< should dual presolving steps be performed? */
    144#define DEFAULT_SINGLETONSTUFFING TRUE /**< should stuffing of singleton continuous variables be performed? */
    145#define DEFAULT_SINGLEVARSTUFFING FALSE /**< should single variable stuffing be performed, which tries to fulfill
    146 * constraints using the cheapest variable? */
    147#define DEFAULT_DETECTCUTOFFBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
    148 * function defining an upper bound and prevent these constraints from
    149 * entering the LP */
    150#define DEFAULT_DETECTLOWERBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
    151 * function defining a lower bound and prevent these constraints from
    152 * entering the LP */
    153#define DEFAULT_DETECTPARTIALOBJECTIVE TRUE/**< should presolving try to detect subsets of constraints parallel to the
    154 * objective function */
    155#define DEFAULT_RANGEDROWPROPAGATION TRUE /**< should we perform ranged row propagation */
    156#define DEFAULT_RANGEDROWARTCONS TRUE /**< should presolving and propagation extract sub-constraints from ranged rows and equations? */
    157#define DEFAULT_RANGEDROWMAXDEPTH INT_MAX /**< maximum depth to apply ranged row propagation */
    158#define DEFAULT_RANGEDROWFREQ 1 /**< frequency for applying ranged row propagation */
    159
    160#define DEFAULT_MULTAGGRREMOVE FALSE /**< should multi-aggregations only be performed if the constraint can be
    161 * removed afterwards? */
    162#define DEFAULT_MAXMULTAGGRQUOT 1e+03 /**< maximum coefficient dynamism (ie. maxabsval / minabsval) for multiaggregation */
    163#define DEFAULT_MAXDUALMULTAGGRQUOT 1e+20 /**< maximum coefficient dynamism (ie. maxabsval / minabsval) for multiaggregation */
    164#define DEFAULT_EXTRACTCLIQUES TRUE /**< should cliques be extracted? */
    165
    166#define MAXDNOM 10000LL /**< maximal denominator for simple rational fixed values */
    167#define MAXSCALEDCOEF 0 /**< maximal coefficient value after scaling */
    168#define MAXSCALEDCOEFINTEGER 0 /**< maximal coefficient value after scaling if all variables are of integral
    169 * type
    170 */
    171#define MAXACTVAL 1e+09 /**< maximal absolute value of full and partial activities such that
    172 * redundancy-based simplifications are allowed to be applied
    173 */
    174
    175#define MAXVALRECOMP 1e+06 /**< maximal abolsute value we trust without recomputing the activity */
    176#define MINVALRECOMP 1e-05 /**< minimal abolsute value we trust without recomputing the activity */
    177
    178
    179#define NONLINCONSUPGD_PRIORITY 1000000 /**< priority of the constraint handler for upgrading of expressions constraints */
    180
    181/* @todo add multi-aggregation of variables that are in exactly two equations (, if not numerically an issue),
    182 * maybe in fullDualPresolve(), see convertLongEquality()
    183 */
    184
    185
    186/** constraint data for linear constraints */
    187struct SCIP_ConsData
    188{
    189 SCIP_Real lhs; /**< left hand side of row (for ranged rows) */
    190 SCIP_Real rhs; /**< right hand side of row */
    191 SCIP_Real maxabsval; /**< maximum absolute value of all coefficients */
    192 SCIP_Real minabsval; /**< minimal absolute value of all coefficients */
    193 QUAD_MEMBER(SCIP_Real minactivity); /**< minimal value w.r.t. the variable's local bounds for the constraint's
    194 * activity, ignoring the coefficients contributing with infinite value */
    195 QUAD_MEMBER(SCIP_Real maxactivity); /**< maximal value w.r.t. the variable's local bounds for the constraint's
    196 * activity, ignoring the coefficients contributing with infinite value */
    197 SCIP_Real lastminactivity; /**< last minimal activity which was computed by complete summation
    198 * over all contributing values */
    199 SCIP_Real lastmaxactivity; /**< last maximal activity which was computed by complete summation
    200 * over all contributing values */
    201 QUAD_MEMBER(SCIP_Real glbminactivity); /**< minimal value w.r.t. the variable's global bounds for the constraint's
    202 * activity, ignoring the coefficients contributing with infinite value */
    203 QUAD_MEMBER(SCIP_Real glbmaxactivity); /**< maximal value w.r.t. the variable's global bounds for the constraint's
    204 * activity, ignoring the coefficients contributing with infinite value */
    205 SCIP_Real lastglbminactivity; /**< last global minimal activity which was computed by complete summation
    206 * over all contributing values */
    207 SCIP_Real lastglbmaxactivity; /**< last global maximal activity which was computed by complete summation
    208 * over all contributing values */
    209 SCIP_Real maxactdelta; /**< maximal activity contribution of a single variable, or SCIP_INVALID if invalid */
    210 SCIP_VAR* maxactdeltavar; /**< variable with maximal activity contribution, or NULL if invalid */
    211 uint64_t possignature; /**< bit signature of coefficients that may take a positive value */
    212 uint64_t negsignature; /**< bit signature of coefficients that may take a negative value */
    213 SCIP_ROW* row; /**< LP row, if constraint is already stored in LP row format */
    214 SCIP_NLROW* nlrow; /**< NLP row, if constraint has been added to NLP relaxation */
    215 SCIP_VAR** vars; /**< variables of constraint entries */
    216 SCIP_Real* vals; /**< coefficients of constraint entries */
    217 SCIP_EVENTDATA** eventdata; /**< event data for bound change events of the variables */
    218 int minactivityneginf; /**< number of coefficients contributing with neg. infinite value to minactivity */
    219 int minactivityposinf; /**< number of coefficients contributing with pos. infinite value to minactivity */
    220 int maxactivityneginf; /**< number of coefficients contributing with neg. infinite value to maxactivity */
    221 int maxactivityposinf; /**< number of coefficients contributing with pos. infinite value to maxactivity */
    222 int minactivityneghuge; /**< number of coefficients contributing with huge neg. value to minactivity */
    223 int minactivityposhuge; /**< number of coefficients contributing with huge pos. value to minactivity */
    224 int maxactivityneghuge; /**< number of coefficients contributing with huge neg. value to maxactivity */
    225 int maxactivityposhuge; /**< number of coefficients contributing with huge pos. value to maxactivity */
    226 int glbminactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbminactivity */
    227 int glbminactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbminactivity */
    228 int glbmaxactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbmaxactivity */
    229 int glbmaxactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbmaxactivity */
    230 int glbminactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbminactivity */
    231 int glbminactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbminactivity */
    232 int glbmaxactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbmaxactivity */
    233 int glbmaxactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbmaxactivity */
    234 int varssize; /**< size of the vars- and vals-arrays */
    235 int nvars; /**< number of nonzeros in constraint */
    236 int nbinvars; /**< the number of binary variables in the constraint, only valid after
    237 * sorting in stage >= SCIP_STAGE_INITSOLVE
    238 */
    239 unsigned int boundstightened:2; /**< is constraint already propagated with bound tightening? */
    240 unsigned int rangedrowpropagated:2; /**< did we perform ranged row propagation on this constraint?
    241 * (0: no, 1: yes, 2: with potentially adding artificial constraint */
    242 unsigned int validmaxabsval:1; /**< is the maximum absolute value valid? */
    243 unsigned int validminabsval:1; /**< is the minimum absolute value valid? */
    244 unsigned int validactivities:1; /**< are the activity bounds (local and global) valid? */
    245 unsigned int validminact:1; /**< is the local minactivity valid? */
    246 unsigned int validmaxact:1; /**< is the local maxactivity valid? */
    247 unsigned int validglbminact:1; /**< is the global minactivity valid? */
    248 unsigned int validglbmaxact:1; /**< is the global maxactivity valid? */
    249 unsigned int presolved:1; /**< is constraint already presolved? */
    250 unsigned int removedfixings:1; /**< are all fixed variables removed from the constraint? */
    251 unsigned int validsignature:1; /**< is the bit signature valid? */
    252 unsigned int changed:1; /**< was constraint changed since last aggregation round in preprocessing? */
    253 unsigned int normalized:1; /**< is the constraint in normalized form? */
    254 unsigned int upgradetried:1; /**< was the constraint already tried to be upgraded? */
    255 unsigned int upgraded:1; /**< is the constraint upgraded and will it be removed after preprocessing? */
    256 unsigned int indexsorted:1; /**< are the constraint's variables sorted by type and index? */
    257 unsigned int merged:1; /**< are the constraint's equal variables already merged? */
    258 unsigned int cliquesadded:1; /**< were the cliques of the constraint already extracted? */
    259 unsigned int implsadded:1; /**< were the implications of the constraint already extracted? */
    260 unsigned int coefsorted:1; /**< are variables sorted by type and their absolute activity delta? */
    261 unsigned int varsdeleted:1; /**< were variables deleted after last cleanup? */
    262 unsigned int hascontvar:1; /**< does the constraint contain at least one continuous variable? */
    263 unsigned int hasnonbinvar:1; /**< does the constraint contain at least one non-binary variable? */
    264 unsigned int hasnonbinvalid:1; /**< is the information stored in hasnonbinvar and hascontvar valid? */
    265 unsigned int checkabsolute:1; /**< should the constraint be checked w.r.t. an absolute feasibilty tolerance? */
    266};
    267
    268/** event data for bound change event */
    269struct SCIP_EventData
    270{
    271 SCIP_CONS* cons; /**< linear constraint to process the bound change for */
    272 int varpos; /**< position of variable in vars array */
    273 int filterpos; /**< position of event in variable's event filter */
    274};
    275
    276/** constraint handler data */
    277struct SCIP_ConshdlrData
    278{
    279 SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events */
    280 SCIP_LINCONSUPGRADE** linconsupgrades; /**< linear constraint upgrade methods for specializing linear constraints */
    281 SCIP_Real maxaggrnormscale; /**< maximal allowed relative gain in maximum norm for constraint aggregation
    282 * (0.0: disable constraint aggregation) */
    283 SCIP_Real maxcardbounddist; /**< maximal relative distance from current node's dual bound to primal bound compared
    284 * to best node's dual bound for separating knapsack cardinality cuts */
    285 SCIP_Real mingainpernmincomp; /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise comparison round */
    286 SCIP_Real maxeasyactivitydelta;/**< maximum activity delta to run easy propagation on linear constraint
    287 * (faster, but numerically less stable) */
    288 int linconsupgradessize;/**< size of linconsupgrade array */
    289 int nlinconsupgrades; /**< number of linear constraint upgrade methods */
    290 int tightenboundsfreq; /**< multiplier on propagation frequency, how often the bounds are tightened */
    291 int maxrounds; /**< maximal number of separation rounds per node (-1: unlimited) */
    292 int maxroundsroot; /**< maximal number of separation rounds in the root node (-1: unlimited) */
    293 int maxsepacuts; /**< maximal number of cuts separated per separation round */
    294 int maxsepacutsroot; /**< maximal number of cuts separated per separation round in root node */
    295 int nmincomparisons; /**< number for minimal pairwise presolving comparisons */
    296 int naddconss; /**< number of added constraints */
    297 SCIP_Bool presolpairwise; /**< should pairwise constraint comparison be performed in presolving? */
    298 SCIP_Bool presolusehashing; /**< should hash table be used for detecting redundant constraints in advance */
    299 SCIP_Bool separateall; /**< should all constraints be subject to cardinality cut generation instead of only
    300 * the ones with non-zero dual value? */
    301 SCIP_Bool aggregatevariables; /**< should presolving search for redundant variables in equations */
    302 SCIP_Bool simplifyinequalities;/**< should presolving try to cancel down or delete coefficients in inequalities */
    303 SCIP_Bool dualpresolving; /**< should dual presolving steps be performed? */
    304 SCIP_Bool singletonstuffing; /**< should stuffing of singleton continuous variables be performed? */
    305 SCIP_Bool singlevarstuffing; /**< should single variable stuffing be performed, which tries to fulfill
    306 * constraints using the cheapest variable? */
    307 SCIP_Bool sortvars; /**< should binary variables be sorted for faster propagation? */
    308 SCIP_Bool checkrelmaxabs; /**< should the violation for a constraint with side 0.0 be checked relative
    309 * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
    310 SCIP_Bool detectcutoffbound; /**< should presolving try to detect constraints parallel to the objective
    311 * function defining an upper bound and prevent these constraints from
    312 * entering the LP */
    313 SCIP_Bool detectlowerbound; /**< should presolving try to detect constraints parallel to the objective
    314 * function defining a lower bound and prevent these constraints from
    315 * entering the LP */
    316 SCIP_Bool detectpartialobjective;/**< should presolving try to detect subsets of constraints parallel to
    317 * the objective function */
    318 SCIP_Bool rangedrowpropagation;/**< should presolving and propagation try to improve bounds, detect
    319 * infeasibility, and extract sub-constraints from ranged rows and
    320 * equations */
    321 SCIP_Bool rangedrowartcons; /**< should presolving and propagation extract sub-constraints from ranged rows and equations?*/
    322 int rangedrowmaxdepth; /**< maximum depth to apply ranged row propagation */
    323 int rangedrowfreq; /**< frequency for applying ranged row propagation */
    324 SCIP_Bool multaggrremove; /**< should multi-aggregations only be performed if the constraint can be
    325 * removed afterwards? */
    326 SCIP_Real maxmultaggrquot; /**< maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation */
    327 SCIP_Real maxdualmultaggrquot;/**< maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation */
    328 SCIP_Bool extractcliques; /**< should cliques be extracted? */
    329};
    330
    331/** linear constraint update method */
    333{
    334 SCIP_DECL_LINCONSUPGD((*linconsupgd)); /**< method to call for upgrading linear constraint */
    335 int priority; /**< priority of upgrading method */
    336 SCIP_Bool active; /**< is upgrading enabled */
    337};
    338
    339
    340/*
    341 * Propagation rules
    342 */
    343
    345{
    346 PROPRULE_1_RHS = 1, /**< activity residuals of all other variables tighten bounds of single
    347 * variable due to the right hand side of the inequality */
    348 PROPRULE_1_LHS = 2, /**< activity residuals of all other variables tighten bounds of single
    349 * variable due to the left hand side of the inequality */
    350 PROPRULE_1_RANGEDROW = 3, /**< fixed variables and gcd of all left variables tighten bounds of a
    351 * single variable in this reanged row */
    352 PROPRULE_INVALID = 0 /**< propagation was applied without a specific propagation rule */
    354typedef enum Proprule PROPRULE;
    355
    356/** inference information */
    357struct InferInfo
    358{
    359 union
    360 {
    361 struct
    362 {
    363 unsigned int proprule:8; /**< propagation rule that was applied */
    364 unsigned int pos:24; /**< variable position, the propagation rule was applied at */
    365 } asbits;
    366 int asint; /**< inference information as a single int value */
    367 } val;
    368};
    369typedef struct InferInfo INFERINFO;
    370
    371/** converts an integer into an inference information */
    372static
    374 int i /**< integer to convert */
    375 )
    376{
    377 INFERINFO inferinfo;
    378
    379 inferinfo.val.asint = i;
    380
    381 return inferinfo;
    382}
    383
    384/** converts an inference information into an int */
    385static
    387 INFERINFO inferinfo /**< inference information to convert */
    388 )
    389{
    390 return inferinfo.val.asint;
    391}
    392
    393/** returns the propagation rule stored in the inference information */
    394static
    396 INFERINFO inferinfo /**< inference information to convert */
    397 )
    398{
    399 return (int) inferinfo.val.asbits.proprule;
    400}
    401
    402/** returns the position stored in the inference information */
    403static
    405 INFERINFO inferinfo /**< inference information to convert */
    406 )
    407{
    408 return (int) inferinfo.val.asbits.pos;
    409}
    410
    411/** constructs an inference information out of a propagation rule and a position number */
    412static
    414 PROPRULE proprule, /**< propagation rule that deduced the value */
    415 int pos /**< variable position, the propagation rule was applied at */
    416 )
    417{
    418 INFERINFO inferinfo;
    419
    420 assert(pos >= 0);
    421 /* in the inferinfo struct only 24 bits for 'pos' are reserved */
    422 assert(pos < (1<<24));
    423
    424 inferinfo.val.asbits.proprule = (unsigned int) proprule; /*lint !e641*/
    425 inferinfo.val.asbits.pos = (unsigned int) pos; /*lint !e732*/
    426
    427 return inferinfo;
    428}
    429
    430/** constructs an inference information out of a propagation rule and a position number, returns info as int */
    431static
    433 PROPRULE proprule, /**< propagation rule that deduced the value */
    434 int pos /**< variable position, the propagation rule was applied at */
    435 )
    436{
    437 return inferInfoToInt(getInferInfo(proprule, pos));
    438}
    439
    440
    441/*
    442 * memory growing methods for dynamically allocated arrays
    443 */
    444
    445/** ensures, that linconsupgrades array can store at least num entries */
    446static
    448 SCIP* scip, /**< SCIP data structure */
    449 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
    450 int num /**< minimum number of entries to store */
    451 )
    452{
    453 assert(scip != NULL);
    454 assert(conshdlrdata != NULL);
    455 assert(conshdlrdata->nlinconsupgrades <= conshdlrdata->linconsupgradessize);
    456
    457 if( num > conshdlrdata->linconsupgradessize )
    458 {
    459 int newsize;
    460
    461 newsize = SCIPcalcMemGrowSize(scip, num);
    462 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &conshdlrdata->linconsupgrades, conshdlrdata->linconsupgradessize, newsize) );
    463 conshdlrdata->linconsupgradessize = newsize;
    464 }
    465 assert(num <= conshdlrdata->linconsupgradessize);
    466
    467 return SCIP_OKAY;
    468}
    469
    470/** ensures, that vars and vals arrays can store at least num entries */
    471static
    473 SCIP* scip, /**< SCIP data structure */
    474 SCIP_CONSDATA* consdata, /**< linear constraint data */
    475 int num /**< minimum number of entries to store */
    476 )
    477{
    478 assert(scip != NULL);
    479 assert(consdata != NULL);
    480 assert(consdata->nvars <= consdata->varssize);
    481
    482 if( num > consdata->varssize )
    483 {
    484 int newsize;
    485
    486 newsize = SCIPcalcMemGrowSize(scip, num);
    487 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
    488 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vals, consdata->varssize, newsize) );
    489 if( consdata->eventdata != NULL )
    490 {
    491 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize, newsize) );
    492 }
    493 consdata->varssize = newsize;
    494 }
    495 assert(num <= consdata->varssize);
    496
    497 return SCIP_OKAY;
    498}
    499
    500
    501/*
    502 * local methods for managing linear constraint update methods
    503 */
    504
    505/** creates a linear constraint upgrade data object */
    506static
    508 SCIP* scip, /**< SCIP data structure */
    509 SCIP_LINCONSUPGRADE** linconsupgrade, /**< pointer to store the linear constraint upgrade */
    510 SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
    511 int priority /**< priority of upgrading method */
    512 )
    513{
    514 assert(scip != NULL);
    515 assert(linconsupgrade != NULL);
    516 assert(linconsupgd != NULL);
    517
    518 SCIP_CALL( SCIPallocBlockMemory(scip, linconsupgrade) );
    519 (*linconsupgrade)->linconsupgd = linconsupgd;
    520 (*linconsupgrade)->priority = priority;
    521 (*linconsupgrade)->active = TRUE;
    522
    523 return SCIP_OKAY;
    524}
    525
    526/** frees a linear constraint upgrade data object */
    527static
    529 SCIP* scip, /**< SCIP data structure */
    530 SCIP_LINCONSUPGRADE** linconsupgrade /**< pointer to the linear constraint upgrade */
    531 )
    532{
    533 assert(scip != NULL);
    534 assert(linconsupgrade != NULL);
    535 assert(*linconsupgrade != NULL);
    536
    537 SCIPfreeBlockMemory(scip, linconsupgrade);
    538}
    539
    540/** creates constraint handler data for linear constraint handler */
    541static
    543 SCIP* scip, /**< SCIP data structure */
    544 SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
    545 SCIP_EVENTHDLR* eventhdlr /**< event handler */
    546 )
    547{
    548 assert(scip != NULL);
    549 assert(conshdlrdata != NULL);
    550 assert(eventhdlr != NULL);
    551
    552 SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
    553 (*conshdlrdata)->linconsupgrades = NULL;
    554 (*conshdlrdata)->linconsupgradessize = 0;
    555 (*conshdlrdata)->nlinconsupgrades = 0;
    556 (*conshdlrdata)->naddconss = 0;
    557
    558 /* set event handler for updating linear constraint activity bounds */
    559 (*conshdlrdata)->eventhdlr = eventhdlr;
    560
    561 return SCIP_OKAY;
    562}
    563
    564/** frees constraint handler data for linear constraint handler */
    565static
    567 SCIP* scip, /**< SCIP data structure */
    568 SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
    569 )
    570{
    571 int i;
    572
    573 assert(scip != NULL);
    574 assert(conshdlrdata != NULL);
    575 assert(*conshdlrdata != NULL);
    576
    577 for( i = 0; i < (*conshdlrdata)->nlinconsupgrades; ++i )
    578 {
    579 linconsupgradeFree(scip, &(*conshdlrdata)->linconsupgrades[i]);
    580 }
    581 SCIPfreeBlockMemoryArrayNull(scip, &(*conshdlrdata)->linconsupgrades, (*conshdlrdata)->linconsupgradessize);
    582
    583 SCIPfreeBlockMemory(scip, conshdlrdata);
    584}
    585
    586/** creates a linear constraint upgrade data object */
    587static
    589 SCIP* scip, /**< SCIP data structure */
    590 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
    591 SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
    592 const char* conshdlrname /**< name of the constraint handler */
    593 )
    594{
    595 int i;
    596
    597 assert(scip != NULL);
    598 assert(conshdlrdata != NULL);
    599 assert(linconsupgd != NULL);
    600 assert(conshdlrname != NULL);
    601
    602 for( i = conshdlrdata->nlinconsupgrades - 1; i >= 0; --i )
    603 {
    604 if( conshdlrdata->linconsupgrades[i]->linconsupgd == linconsupgd )
    605 {
    606#ifdef SCIP_DEBUG
    607 SCIPwarningMessage(scip, "Try to add already known upgrade message for constraint handler %s.\n", conshdlrname);
    608#endif
    609 return TRUE;
    610 }
    611 }
    612
    613 return FALSE;
    614}
    615
    616/** adds a linear constraint update method to the constraint handler's data */
    617static
    619 SCIP* scip, /**< SCIP data structure */
    620 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
    621 SCIP_LINCONSUPGRADE* linconsupgrade /**< linear constraint upgrade method */
    622 )
    623{
    624 int i;
    625
    626 assert(scip != NULL);
    627 assert(conshdlrdata != NULL);
    628 assert(linconsupgrade != NULL);
    629
    630 SCIP_CALL( conshdlrdataEnsureLinconsupgradesSize(scip, conshdlrdata, conshdlrdata->nlinconsupgrades+1) );
    631
    632 for( i = conshdlrdata->nlinconsupgrades;
    633 i > 0 && conshdlrdata->linconsupgrades[i-1]->priority < linconsupgrade->priority; --i )
    634 {
    635 conshdlrdata->linconsupgrades[i] = conshdlrdata->linconsupgrades[i-1];
    636 }
    637 assert(0 <= i && i <= conshdlrdata->nlinconsupgrades);
    638 conshdlrdata->linconsupgrades[i] = linconsupgrade;
    639 conshdlrdata->nlinconsupgrades++;
    640
    641 return SCIP_OKAY;
    642}
    643
    644/*
    645 * local methods
    646 */
    647
    648/** installs rounding locks for the given variable associated to the given coefficient in the linear constraint */
    649static
    651 SCIP* scip, /**< SCIP data structure */
    652 SCIP_CONS* cons, /**< linear constraint */
    653 SCIP_VAR* var, /**< variable of constraint entry */
    654 SCIP_Real val /**< coefficient of constraint entry */
    655 )
    656{
    657 SCIP_CONSDATA* consdata;
    658
    659 assert(scip != NULL);
    660 assert(cons != NULL);
    661 assert(var != NULL);
    662
    663 consdata = SCIPconsGetData(cons);
    664 assert(consdata != NULL);
    665 assert(!SCIPisZero(scip, val));
    666
    667 if( val < 0.0 )
    668 {
    669 SCIP_CALL( SCIPlockVarCons(scip, var, cons,
    670 !SCIPisInfinity(scip, consdata->rhs), !SCIPisInfinity(scip, -consdata->lhs)) );
    671 }
    672 else
    673 {
    674 SCIP_CALL( SCIPlockVarCons(scip, var, cons,
    675 !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
    676 }
    677
    678 return SCIP_OKAY;
    679}
    680
    681/** removes rounding locks for the given variable associated to the given coefficient in the linear constraint */
    682static
    684 SCIP* scip, /**< SCIP data structure */
    685 SCIP_CONS* cons, /**< linear constraint */
    686 SCIP_VAR* var, /**< variable of constraint entry */
    687 SCIP_Real val /**< coefficient of constraint entry */
    688 )
    689{
    690 SCIP_CONSDATA* consdata;
    691
    692 assert(scip != NULL);
    693 assert(cons != NULL);
    694 assert(var != NULL);
    695
    696 consdata = SCIPconsGetData(cons);
    697 assert(consdata != NULL);
    698 assert(!SCIPisZero(scip, val));
    699
    700 if( val < 0.0 )
    701 {
    702 SCIP_CALL( SCIPunlockVarCons(scip, var, cons,
    703 !SCIPisInfinity(scip, consdata->rhs), !SCIPisInfinity(scip, -consdata->lhs)) );
    704 }
    705 else
    706 {
    707 SCIP_CALL( SCIPunlockVarCons(scip, var, cons,
    708 !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
    709 }
    710
    711 return SCIP_OKAY;
    712}
    713
    714/** creates event data for variable at given position, and catches events */
    715/**! [SnippetDebugAssertions] */
    716static
    718 SCIP* scip, /**< SCIP data structure */
    719 SCIP_CONS* cons, /**< linear constraint */
    720 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    721 int pos /**< array position of variable to catch bound change events for */
    722 )
    723{
    724 SCIP_CONSDATA* consdata;
    725 assert(scip != NULL);
    726 assert(cons != NULL);
    727 assert(eventhdlr != NULL);
    728
    729 consdata = SCIPconsGetData(cons);
    730 assert(consdata != NULL);
    731
    732 assert(0 <= pos && pos < consdata->nvars);
    733 assert(consdata->vars != NULL);
    734 assert(consdata->vars[pos] != NULL);
    735 assert(SCIPvarIsTransformed(consdata->vars[pos]));
    736 assert(consdata->eventdata != NULL);
    737 assert(consdata->eventdata[pos] == NULL);
    738
    739 SCIP_CALL( SCIPallocBlockMemory(scip, &(consdata->eventdata[pos])) ); /*lint !e866*/
    740 consdata->eventdata[pos]->cons = cons;
    741 consdata->eventdata[pos]->varpos = pos;
    742
    743 SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[pos],
    747 eventhdlr, consdata->eventdata[pos], &consdata->eventdata[pos]->filterpos) );
    748
    749 consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(consdata->vars[pos]);
    750
    751 return SCIP_OKAY;
    752}
    753/**! [SnippetDebugAssertions] */
    754
    755/** deletes event data for variable at given position, and drops events */
    756static
    758 SCIP* scip, /**< SCIP data structure */
    759 SCIP_CONS* cons, /**< linear constraint */
    760 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    761 int pos /**< array position of variable to catch bound change events for */
    762 )
    763{
    764 SCIP_CONSDATA* consdata;
    765 assert(scip != NULL);
    766 assert(cons != NULL);
    767 assert(eventhdlr != NULL);
    768
    769 consdata = SCIPconsGetData(cons);
    770 assert(consdata != NULL);
    771
    772 assert(0 <= pos && pos < consdata->nvars);
    773 assert(consdata->vars[pos] != NULL);
    774 assert(consdata->eventdata != NULL);
    775 assert(consdata->eventdata[pos] != NULL);
    776 assert(consdata->eventdata[pos]->cons == cons);
    777 assert(consdata->eventdata[pos]->varpos == pos);
    778
    779 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[pos],
    783 eventhdlr, consdata->eventdata[pos], consdata->eventdata[pos]->filterpos) );
    784
    785 SCIPfreeBlockMemory(scip, &consdata->eventdata[pos]); /*lint !e866*/
    786
    787 return SCIP_OKAY;
    788}
    789
    790/** catches bound change events for all variables in transformed linear constraint */
    791static
    793 SCIP* scip, /**< SCIP data structure */
    794 SCIP_CONS* cons, /**< linear constraint */
    795 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
    796 )
    797{
    798 SCIP_CONSDATA* consdata;
    799 int i;
    800
    801 assert(scip != NULL);
    802 assert(cons != NULL);
    803
    804 consdata = SCIPconsGetData(cons);
    805 assert(consdata != NULL);
    806 assert(consdata->eventdata == NULL);
    807
    808 /* allocate eventdata array */
    809 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize) );
    810 assert(consdata->eventdata != NULL);
    811 BMSclearMemoryArray(consdata->eventdata, consdata->nvars);
    812
    813 /* catch event for every single variable */
    814 for( i = 0; i < consdata->nvars; ++i )
    815 {
    816 SCIP_CALL( consCatchEvent(scip, cons, eventhdlr, i) );
    817 }
    818
    819 return SCIP_OKAY;
    820}
    821
    822/** drops bound change events for all variables in transformed linear constraint */
    823static
    825 SCIP* scip, /**< SCIP data structure */
    826 SCIP_CONS* cons, /**< linear constraint */
    827 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
    828 )
    829{
    830 SCIP_CONSDATA* consdata;
    831 int i;
    832
    833 assert(scip != NULL);
    834 assert(cons != NULL);
    835
    836 consdata = SCIPconsGetData(cons);
    837 assert(consdata != NULL);
    838 assert(consdata->eventdata != NULL);
    839
    840 /* drop event of every single variable */
    841 for( i = consdata->nvars - 1; i >= 0; --i )
    842 {
    843 SCIP_CALL( consDropEvent(scip, cons, eventhdlr, i) );
    844 }
    845
    846 /* free eventdata array */
    847 SCIPfreeBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize);
    848 assert(consdata->eventdata == NULL);
    849
    850 return SCIP_OKAY;
    851}
    852
    853/** creates a linear constraint data */
    854static
    856 SCIP* scip, /**< SCIP data structure */
    857 SCIP_CONSDATA** consdata, /**< pointer to linear constraint data */
    858 int nvars, /**< number of nonzeros in the constraint */
    859 SCIP_VAR** vars, /**< array with variables of constraint entries */
    860 SCIP_Real* vals, /**< array with coefficients of constraint entries */
    861 SCIP_Real lhs, /**< left hand side of row */
    862 SCIP_Real rhs /**< right hand side of row */
    863 )
    864{
    865 int v;
    866 SCIP_Real constant;
    867
    868 assert(scip != NULL);
    869 assert(consdata != NULL);
    870 assert(nvars == 0 || vars != NULL);
    871 assert(nvars == 0 || vals != NULL);
    872
    873 if( SCIPisInfinity(scip, rhs) )
    874 rhs = SCIPinfinity(scip);
    875 else if( SCIPisInfinity(scip, -rhs) )
    876 rhs = -SCIPinfinity(scip);
    877
    878 if( SCIPisInfinity(scip, -lhs) )
    879 lhs = -SCIPinfinity(scip);
    880 else if( SCIPisInfinity(scip, lhs) )
    881 lhs = SCIPinfinity(scip);
    882
    883 if( SCIPisGT(scip, lhs, rhs) )
    884 {
    885 SCIPwarningMessage(scip, "left hand side of linear constraint greater than right hand side\n");
    886 SCIPwarningMessage(scip, " -> lhs=%g, rhs=%g\n", lhs, rhs);
    887 }
    888
    889 SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
    890
    891 (*consdata)->varssize = 0;
    892 (*consdata)->nvars = nvars;
    893 (*consdata)->hascontvar = FALSE;
    894 (*consdata)->hasnonbinvar = FALSE;
    895 (*consdata)->hasnonbinvalid = TRUE;
    896 (*consdata)->vars = NULL;
    897 (*consdata)->vals = NULL;
    898
    899 constant = 0.0;
    900 if( nvars > 0 )
    901 {
    902 SCIP_VAR** varsbuffer;
    903 SCIP_Real* valsbuffer;
    904
    905 /* copy variables into temporary buffer */
    906 SCIP_CALL( SCIPallocBufferArray(scip, &varsbuffer, nvars) );
    907 SCIP_CALL( SCIPallocBufferArray(scip, &valsbuffer, nvars) );
    908 nvars = 0;
    909
    910 /* loop over variables and sort out fixed ones */
    911 for( v = 0; v < (*consdata)->nvars; ++v )
    912 {
    913 SCIP_VAR* var;
    914 SCIP_Real val;
    915
    916 var = vars[v];
    917 assert(var != NULL);
    918 val = vals[v];
    919 assert(!SCIPisInfinity(scip, val));
    920
    921 if( !SCIPisZero(scip, val) )
    922 {
    923 /* treat fixed variable as a constant if problem compression is enabled */
    925 {
    926 constant += SCIPvarGetLbGlobal(var) * val;
    927 }
    928 else
    929 {
    930 varsbuffer[nvars] = var;
    931 valsbuffer[nvars] = val;
    932 ++nvars;
    933
    934 if( !(*consdata)->hascontvar && !SCIPvarIsBinary(var) )
    935 {
    936 (*consdata)->hasnonbinvar = TRUE;
    937
    938 if( !SCIPvarIsIntegral(var) )
    939 (*consdata)->hascontvar = TRUE;
    940 }
    941 }
    942 }
    943 }
    944 (*consdata)->nvars = nvars;
    945
    946 if( nvars > 0 )
    947 {
    948 /* copy the possibly reduced buffer arrays into block */
    949 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, varsbuffer, nvars) );
    950 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vals, valsbuffer, nvars) );
    951 (*consdata)->varssize = nvars;
    952 }
    953 /* free temporary buffer */
    954 SCIPfreeBufferArray(scip, &valsbuffer);
    955 SCIPfreeBufferArray(scip, &varsbuffer);
    956 }
    957
    958 (*consdata)->eventdata = NULL;
    959
    960 /* due to compressed copying, we may have fixed variables contributing to the left and right hand side */
    961 if( !SCIPisZero(scip, constant) )
    962 {
    963 if( !SCIPisInfinity(scip, REALABS(lhs)) )
    964 lhs -= constant;
    965
    966 if( !SCIPisInfinity(scip, REALABS(rhs)) )
    967 rhs -= constant;
    968 }
    969
    970 (*consdata)->row = NULL;
    971 (*consdata)->nlrow = NULL;
    972 (*consdata)->lhs = lhs;
    973 (*consdata)->rhs = rhs;
    974 (*consdata)->maxabsval = SCIP_INVALID;
    975 (*consdata)->minabsval = SCIP_INVALID;
    976 QUAD_ASSIGN((*consdata)->minactivity, SCIP_INVALID);
    977 QUAD_ASSIGN((*consdata)->maxactivity, SCIP_INVALID);
    978 (*consdata)->lastminactivity = SCIP_INVALID;
    979 (*consdata)->lastmaxactivity = SCIP_INVALID;
    980 (*consdata)->maxactdelta = SCIP_INVALID;
    981 (*consdata)->maxactdeltavar = NULL;
    982 (*consdata)->minactivityneginf = -1;
    983 (*consdata)->minactivityposinf = -1;
    984 (*consdata)->maxactivityneginf = -1;
    985 (*consdata)->maxactivityposinf = -1;
    986 (*consdata)->minactivityneghuge = -1;
    987 (*consdata)->minactivityposhuge = -1;
    988 (*consdata)->maxactivityneghuge = -1;
    989 (*consdata)->maxactivityposhuge = -1;
    990 QUAD_ASSIGN((*consdata)->glbminactivity, SCIP_INVALID);
    991 QUAD_ASSIGN((*consdata)->glbmaxactivity, SCIP_INVALID);
    992 (*consdata)->lastglbminactivity = SCIP_INVALID;
    993 (*consdata)->lastglbmaxactivity = SCIP_INVALID;
    994 (*consdata)->glbminactivityneginf = -1;
    995 (*consdata)->glbminactivityposinf = -1;
    996 (*consdata)->glbmaxactivityneginf = -1;
    997 (*consdata)->glbmaxactivityposinf = -1;
    998 (*consdata)->glbminactivityneghuge = -1;
    999 (*consdata)->glbminactivityposhuge = -1;
    1000 (*consdata)->glbmaxactivityneghuge = -1;
    1001 (*consdata)->glbmaxactivityposhuge = -1;
    1002 (*consdata)->possignature = 0;
    1003 (*consdata)->negsignature = 0;
    1004 (*consdata)->validmaxabsval = FALSE;
    1005 (*consdata)->validminabsval = FALSE;
    1006 (*consdata)->validactivities = FALSE;
    1007 (*consdata)->validminact = FALSE;
    1008 (*consdata)->validmaxact = FALSE;
    1009 (*consdata)->validglbminact = FALSE;
    1010 (*consdata)->validglbmaxact = FALSE;
    1011 (*consdata)->boundstightened = 0;
    1012 (*consdata)->presolved = FALSE;
    1013 (*consdata)->removedfixings = FALSE;
    1014 (*consdata)->validsignature = FALSE;
    1015 (*consdata)->changed = TRUE;
    1016 (*consdata)->normalized = FALSE;
    1017 (*consdata)->upgradetried = FALSE;
    1018 (*consdata)->upgraded = FALSE;
    1019 (*consdata)->indexsorted = (nvars <= 1);
    1020 (*consdata)->merged = (nvars <= 1);
    1021 (*consdata)->cliquesadded = FALSE;
    1022 (*consdata)->implsadded = FALSE;
    1023 (*consdata)->coefsorted = FALSE;
    1024 (*consdata)->nbinvars = -1;
    1025 (*consdata)->varsdeleted = FALSE;
    1026 (*consdata)->rangedrowpropagated = 0;
    1027 (*consdata)->checkabsolute = FALSE;
    1028
    1029 if( SCIPisTransformed(scip) )
    1030 {
    1031 /* get transformed variables */
    1032 SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
    1033 }
    1034
    1035 /* capture variables */
    1036 for( v = 0; v < (*consdata)->nvars; v++ )
    1037 {
    1038 /* likely implies a deleted variable */
    1039 if( (*consdata)->vars[v] == NULL )
    1040 {
    1041 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
    1042 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize);
    1043 SCIPfreeBlockMemory(scip, consdata);
    1044 return SCIP_INVALIDDATA;
    1045 }
    1046
    1047 assert(!SCIPisZero(scip, (*consdata)->vals[v]));
    1048 SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
    1049 }
    1050
    1051 return SCIP_OKAY;
    1052}
    1053
    1054/** frees a linear constraint data */
    1055static
    1057 SCIP* scip, /**< SCIP data structure */
    1058 SCIP_CONSDATA** consdata /**< pointer to linear constraint data */
    1059 )
    1060{
    1061 int v;
    1062
    1063 assert(scip != NULL);
    1064 assert(consdata != NULL);
    1065 assert(*consdata != NULL);
    1066 assert((*consdata)->varssize >= 0);
    1067
    1068 /* release the row */
    1069 if( (*consdata)->row != NULL )
    1070 {
    1071 SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) );
    1072 }
    1073
    1074 /* release the nlrow */
    1075 if( (*consdata)->nlrow != NULL )
    1076 {
    1077 SCIP_CALL( SCIPreleaseNlRow(scip, &(*consdata)->nlrow) );
    1078 }
    1079
    1080 /* release variables */
    1081 for( v = 0; v < (*consdata)->nvars; v++ )
    1082 {
    1083 assert((*consdata)->vars[v] != NULL);
    1084 assert(!SCIPisZero(scip, (*consdata)->vals[v]));
    1085 SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->vars[v])) );
    1086 }
    1087
    1088 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
    1089 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize);
    1090 SCIPfreeBlockMemory(scip, consdata);
    1091
    1092 return SCIP_OKAY;
    1093}
    1094
    1095/** prints linear constraint in CIP format to file stream */
    1096static
    1098 SCIP* scip, /**< SCIP data structure */
    1099 SCIP_CONSDATA* consdata, /**< linear constraint data */
    1100 FILE* file /**< output file (or NULL for standard output) */
    1101 )
    1102{
    1103 assert(scip != NULL);
    1104 assert(consdata != NULL);
    1105
    1106 /* print left hand side for ranged rows */
    1107 if( !SCIPisInfinity(scip, -consdata->lhs)
    1108 && !SCIPisInfinity(scip, consdata->rhs)
    1109 && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
    1110 SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
    1111
    1112 /* print coefficients and variables */
    1113 if( consdata->nvars == 0 )
    1114 SCIPinfoMessage(scip, file, "0");
    1115 else
    1116 {
    1117 /* post linear sum of the linear constraint */
    1118 SCIP_CALL( SCIPwriteVarsLinearsum(scip, file, consdata->vars, consdata->vals, consdata->nvars, TRUE) );
    1119 }
    1120
    1121 /* print right hand side */
    1122 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
    1123 SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
    1124 else if( !SCIPisInfinity(scip, consdata->rhs) )
    1125 SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
    1126 else if( !SCIPisInfinity(scip, -consdata->lhs) )
    1127 SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
    1128 else
    1129 SCIPinfoMessage(scip, file, " [free]");
    1130
    1131 return SCIP_OKAY;
    1132}
    1133
    1134/** prints linear constraint and contained solution values of variables to file stream */
    1135static
    1137 SCIP* scip, /**< SCIP data structure */
    1138 SCIP_CONS* cons, /**< linear constraint */
    1139 SCIP_SOL* sol, /**< solution to print */
    1140 FILE* file /**< output file (or NULL for standard output) */
    1141 )
    1142{
    1143 SCIP_CONSDATA* consdata;
    1144
    1145 assert(scip != NULL);
    1146 assert(cons != NULL);
    1147
    1148 consdata = SCIPconsGetData(cons);
    1149 assert(consdata != NULL);
    1150
    1152
    1153 /* print left hand side for ranged rows */
    1154 if( !SCIPisInfinity(scip, -consdata->lhs)
    1155 && !SCIPisInfinity(scip, consdata->rhs)
    1156 && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
    1157 SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
    1158
    1159 /* print coefficients and variables */
    1160 if( consdata->nvars == 0 )
    1161 SCIPinfoMessage(scip, file, "0");
    1162 else
    1163 {
    1164 int v;
    1165
    1166 /* post linear sum of the linear constraint */
    1167 for( v = 0; v < consdata->nvars; ++v )
    1168 {
    1169 if( consdata->vals != NULL )
    1170 {
    1171 if( consdata->vals[v] == 1.0 )
    1172 {
    1173 if( v > 0 )
    1174 SCIPinfoMessage(scip, file, " +");
    1175 }
    1176 else if( consdata->vals[v] == -1.0 )
    1177 SCIPinfoMessage(scip, file, " -");
    1178 else
    1179 SCIPinfoMessage(scip, file, " %+.9g", consdata->vals[v]);
    1180 }
    1181 else if( consdata->nvars > 0 )
    1182 SCIPinfoMessage(scip, file, " +");
    1183
    1184 /* print variable name */
    1185 SCIP_CALL( SCIPwriteVarName(scip, file, consdata->vars[v], TRUE) );
    1186
    1187 SCIPinfoMessage(scip, file, " (%+.9g)", SCIPgetSolVal(scip, sol, consdata->vars[v]));
    1188 }
    1189 }
    1190
    1191 /* print right hand side */
    1192 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
    1193 SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
    1194 else if( !SCIPisInfinity(scip, consdata->rhs) )
    1195 SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
    1196 else if( !SCIPisInfinity(scip, -consdata->lhs) )
    1197 SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
    1198 else
    1199 SCIPinfoMessage(scip, file, " [free]");
    1200
    1201 SCIPinfoMessage(scip, file, ";\n");
    1202
    1203 return SCIP_OKAY;
    1204}
    1205
    1206/** invalidates activity bounds, such that they are recalculated in next get */
    1207static
    1209 SCIP_CONSDATA* consdata /**< linear constraint */
    1210 )
    1211{
    1212 assert(consdata != NULL);
    1213
    1214 consdata->validactivities = FALSE;
    1215 consdata->validminact = FALSE;
    1216 consdata->validmaxact = FALSE;
    1217 consdata->validglbminact = FALSE;
    1218 consdata->validglbmaxact = FALSE;
    1219 consdata->validmaxabsval = FALSE;
    1220 consdata->validminabsval = FALSE;
    1221 consdata->hasnonbinvalid = FALSE;
    1222 QUAD_ASSIGN(consdata->minactivity, SCIP_INVALID);
    1223 QUAD_ASSIGN(consdata->maxactivity, SCIP_INVALID);
    1224 consdata->lastminactivity = SCIP_INVALID;
    1225 consdata->lastmaxactivity = SCIP_INVALID;
    1226 consdata->maxabsval = SCIP_INVALID;
    1227 consdata->minabsval = SCIP_INVALID;
    1228 consdata->maxactdelta = SCIP_INVALID;
    1229 consdata->maxactdeltavar = NULL;
    1230 consdata->minactivityneginf = -1;
    1231 consdata->minactivityposinf = -1;
    1232 consdata->maxactivityneginf = -1;
    1233 consdata->maxactivityposinf = -1;
    1234 consdata->minactivityneghuge = -1;
    1235 consdata->minactivityposhuge = -1;
    1236 consdata->maxactivityneghuge = -1;
    1237 consdata->maxactivityposhuge = -1;
    1238 QUAD_ASSIGN(consdata->glbminactivity, SCIP_INVALID);
    1239 QUAD_ASSIGN(consdata->glbmaxactivity, SCIP_INVALID);
    1240 consdata->lastglbminactivity = SCIP_INVALID;
    1241 consdata->lastglbmaxactivity = SCIP_INVALID;
    1242 consdata->glbminactivityneginf = -1;
    1243 consdata->glbminactivityposinf = -1;
    1244 consdata->glbmaxactivityneginf = -1;
    1245 consdata->glbmaxactivityposinf = -1;
    1246 consdata->glbminactivityneghuge = -1;
    1247 consdata->glbminactivityposhuge = -1;
    1248 consdata->glbmaxactivityneghuge = -1;
    1249 consdata->glbmaxactivityposhuge = -1;
    1250}
    1251
    1252/** compute the pseudo activity of a constraint */
    1253static
    1255 SCIP* scip, /**< SCIP data structure */
    1256 SCIP_CONSDATA* consdata /**< linear constraint data */
    1257 )
    1258{
    1259 int i;
    1260 int pseudoactivityposinf;
    1261 int pseudoactivityneginf;
    1262 SCIP_Real pseudoactivity;
    1264 SCIP_Real val;
    1265
    1266 pseudoactivity = 0;
    1267 pseudoactivityposinf = 0;
    1268 pseudoactivityneginf = 0;
    1269
    1270 for( i = consdata->nvars - 1; i >= 0; --i )
    1271 {
    1272 bound = SCIPvarGetBestBoundLocal(consdata->vars[i]);
    1273 val = consdata->vals[i];
    1274 assert(!SCIPisZero(scip, val));
    1275
    1276 if( SCIPisInfinity(scip, -bound) )
    1277 {
    1278 if( val < 0.0 )
    1279 ++pseudoactivityposinf;
    1280 else
    1281 ++pseudoactivityneginf;
    1282 }
    1283 else if( SCIPisInfinity(scip, bound) )
    1284 {
    1285 if( val < 0.0 )
    1286 ++pseudoactivityneginf;
    1287 else
    1288 ++pseudoactivityposinf;
    1289 }
    1290 else
    1291 pseudoactivity += val * bound;
    1292 }
    1293
    1294 /* invalidate pseudo activity for contradicting contributions */
    1295 if( pseudoactivityneginf > 0 && pseudoactivityposinf > 0 )
    1296 return SCIP_INVALID;
    1297 else if( pseudoactivityneginf > 0 )
    1298 return -SCIPinfinity(scip);
    1299 else if( pseudoactivityposinf > 0 )
    1300 return SCIPinfinity(scip);
    1301
    1302 return pseudoactivity;
    1303}
    1304
    1305/** recompute the minactivity of a constraint */
    1306static
    1308 SCIP* scip, /**< SCIP data structure */
    1309 SCIP_CONSDATA* consdata /**< linear constraint data */
    1310 )
    1311{
    1312 int i;
    1314
    1315 QUAD_ASSIGN(consdata->minactivity, 0.0);
    1316
    1317 for( i = consdata->nvars - 1; i >= 0; --i )
    1318 {
    1319 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
    1321 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
    1322 SCIPquadprecSumQD(consdata->minactivity, consdata->minactivity, consdata->vals[i] * bound);
    1323 }
    1324
    1325 /* the activity was just computed from scratch and is valid now */
    1326 consdata->validminact = TRUE;
    1327
    1328 /* the activity was just computed from scratch, mark it to be reliable */
    1329 consdata->lastminactivity = QUAD_TO_DBL(consdata->minactivity);
    1330}
    1331
    1332/** recompute the maxactivity of a constraint */
    1333static
    1335 SCIP* scip, /**< SCIP data structure */
    1336 SCIP_CONSDATA* consdata /**< linear constraint data */
    1337 )
    1338{
    1339 int i;
    1341
    1342 QUAD_ASSIGN(consdata->maxactivity, 0.0);
    1343
    1344 for( i = consdata->nvars - 1; i >= 0; --i )
    1345 {
    1346 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbLocal(consdata->vars[i]) : SCIPvarGetLbLocal(consdata->vars[i]);
    1348 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
    1349 SCIPquadprecSumQD(consdata->maxactivity, consdata->maxactivity, consdata->vals[i] * bound);
    1350 }
    1351
    1352 /* the activity was just computed from scratch and is valid now */
    1353 consdata->validmaxact = TRUE;
    1354
    1355 /* the activity was just computed from scratch, mark it to be reliable */
    1356 consdata->lastmaxactivity = QUAD_TO_DBL(consdata->maxactivity);
    1357}
    1358
    1359/** recompute the global minactivity of a constraint */
    1360static
    1362 SCIP* scip, /**< SCIP data structure */
    1363 SCIP_CONSDATA* consdata /**< linear constraint data */
    1364 )
    1365{
    1366 int i;
    1368
    1369 QUAD_ASSIGN(consdata->glbminactivity, 0.0);
    1370
    1371 for( i = consdata->nvars - 1; i >= 0; --i )
    1372 {
    1373 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbGlobal(consdata->vars[i]) : SCIPvarGetUbGlobal(consdata->vars[i]);
    1375 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
    1376 SCIPquadprecSumQD(consdata->glbminactivity, consdata->glbminactivity, consdata->vals[i] * bound);
    1377 }
    1378
    1379 /* the activity was just computed from scratch and is valid now */
    1380 consdata->validglbminact = TRUE;
    1381
    1382 /* the activity was just computed from scratch, mark it to be reliable */
    1383 consdata->lastglbminactivity = QUAD_TO_DBL(consdata->glbminactivity);
    1384}
    1385
    1386/** recompute the global maxactivity of a constraint */
    1387static
    1389 SCIP* scip, /**< SCIP data structure */
    1390 SCIP_CONSDATA* consdata /**< linear constraint data */
    1391 )
    1392{
    1393 int i;
    1395
    1396 QUAD_ASSIGN(consdata->glbmaxactivity, 0.0);
    1397
    1398 for( i = consdata->nvars - 1; i >= 0; --i )
    1399 {
    1400 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbGlobal(consdata->vars[i]) : SCIPvarGetLbGlobal(consdata->vars[i]);
    1402 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
    1403 SCIPquadprecSumQD(consdata->glbmaxactivity, consdata->glbmaxactivity, consdata->vals[i] * bound);
    1404 }
    1405
    1406 /* the activity was just computed from scratch and is valid now */
    1407 consdata->validglbmaxact = TRUE;
    1408
    1409 /* the activity was just computed from scratch, mark it to be reliable */
    1410 consdata->lastglbmaxactivity = QUAD_TO_DBL(consdata->glbmaxactivity);
    1411}
    1412
    1413/** calculates maximum absolute value of coefficients */
    1414static
    1416 SCIP_CONSDATA* consdata /**< linear constraint data */
    1417 )
    1418{
    1419 SCIP_Real absval;
    1420 int i;
    1421
    1422 assert(consdata != NULL);
    1423 assert(!consdata->validmaxabsval);
    1424 assert(consdata->maxabsval >= SCIP_INVALID);
    1425
    1426 consdata->validmaxabsval = TRUE;
    1427 consdata->maxabsval = 0.0;
    1428 for( i = 0; i < consdata->nvars; ++i )
    1429 {
    1430 absval = consdata->vals[i];
    1431 absval = REALABS(absval);
    1432 if( absval > consdata->maxabsval )
    1433 consdata->maxabsval = absval;
    1434 }
    1435}
    1436
    1437/** calculates minimum absolute value of coefficients */
    1438static
    1440 SCIP_CONSDATA* consdata /**< linear constraint data */
    1441 )
    1442{
    1443 SCIP_Real absval;
    1444 int i;
    1445
    1446 assert(consdata != NULL);
    1447 assert(!consdata->validminabsval);
    1448 assert(consdata->minabsval >= SCIP_INVALID);
    1449
    1450 consdata->validminabsval = TRUE;
    1451
    1452 if( consdata->nvars > 0 )
    1453 consdata->minabsval = REALABS(consdata->vals[0]);
    1454 else
    1455 consdata->minabsval = 0.0;
    1456
    1457 for( i = 1; i < consdata->nvars; ++i )
    1458 {
    1459 absval = consdata->vals[i];
    1460 absval = REALABS(absval);
    1461 if( absval < consdata->minabsval )
    1462 consdata->minabsval = absval;
    1463 }
    1464}
    1465
    1466/** checks the type of all variables of the constraint and sets hasnonbinvar and hascontvar flags accordingly */
    1467static
    1469 SCIP_CONSDATA* consdata /**< linear constraint data */
    1470 )
    1471{
    1472 int v;
    1473
    1474 assert(!consdata->hasnonbinvalid);
    1475 consdata->hasnonbinvar = FALSE;
    1476 consdata->hascontvar = FALSE;
    1477
    1478 for( v = consdata->nvars - 1; v >= 0; --v )
    1479 {
    1480 if( !SCIPvarIsBinary(consdata->vars[v]) )
    1481 {
    1482 consdata->hasnonbinvar = TRUE;
    1483
    1484 if( !SCIPvarIsIntegral(consdata->vars[v]) )
    1485 {
    1486 consdata->hascontvar = TRUE;
    1487 break;
    1488 }
    1489 }
    1490 }
    1491 assert(consdata->hascontvar || v < 0);
    1492
    1493 consdata->hasnonbinvalid = TRUE;
    1494}
    1495
    1496
    1497#ifdef CHECKMAXACTDELTA
    1498/** checks that the stored maximal activity delta (if not invalid) is correct */
    1499static
    1501 SCIP* scip, /**< SCIP data structure */
    1502 SCIP_CONSDATA* consdata /**< linear constraint data */
    1503 )
    1504{
    1505 if( consdata->maxactdelta != SCIP_INVALID )
    1506 {
    1507 SCIP_Real maxactdelta = 0.0;
    1508 SCIP_Real domain;
    1509 SCIP_Real delta;
    1510 SCIP_Real lb;
    1511 SCIP_Real ub;
    1512 int v;
    1513
    1514 for( v = consdata->nvars - 1; v >= 0; --v )
    1515 {
    1516 lb = SCIPvarGetLbLocal(consdata->vars[v]);
    1517 ub = SCIPvarGetUbLocal(consdata->vars[v]);
    1518
    1519 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
    1520 {
    1521 maxactdelta = SCIPinfinity(scip);
    1522 break;
    1523 }
    1524
    1525 domain = ub - lb;
    1526 delta = REALABS(consdata->vals[v]) * domain;
    1527
    1528 if( delta > maxactdelta )
    1529 {
    1530 maxactdelta = delta;
    1531 }
    1532 }
    1533 assert(SCIPisFeasEQ(scip, maxactdelta, consdata->maxactdelta));
    1534 }
    1535}
    1536#else
    1537#define checkMaxActivityDelta(scip, consdata) /**/
    1538#endif
    1539
    1540/** recompute maximal activity contribution for a single variable */
    1541static
    1543 SCIP* scip, /**< SCIP data structure */
    1544 SCIP_CONSDATA* consdata /**< linear constraint data */
    1545 )
    1546{
    1547 SCIP_Real delta;
    1548 int v;
    1549
    1550 consdata->maxactdelta = 0.0;
    1551
    1552 if( !consdata->hasnonbinvalid )
    1553 consdataCheckNonbinvar(consdata);
    1554
    1555 /* easy case, the problem consists only of binary variables */
    1556 if( !consdata->hasnonbinvar )
    1557 {
    1558 for( v = consdata->nvars - 1; v >= 0; --v )
    1559 {
    1560 if( SCIPvarGetLbLocal(consdata->vars[v]) < 0.5 && SCIPvarGetUbLocal(consdata->vars[v]) > 0.5 )
    1561 {
    1562 delta = REALABS(consdata->vals[v]);
    1563
    1564 if( delta > consdata->maxactdelta )
    1565 {
    1566 consdata->maxactdelta = delta;
    1567 consdata->maxactdeltavar = consdata->vars[v];
    1568 }
    1569 }
    1570 }
    1571 return;
    1572 }
    1573
    1574 for( v = consdata->nvars - 1; v >= 0; --v )
    1575 {
    1576 SCIP_Real domain;
    1577 SCIP_Real lb;
    1578 SCIP_Real ub;
    1579
    1580 lb = SCIPvarGetLbLocal(consdata->vars[v]);
    1581 ub = SCIPvarGetUbLocal(consdata->vars[v]);
    1582
    1583 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
    1584 {
    1585 consdata->maxactdelta = SCIPinfinity(scip);
    1586 consdata->maxactdeltavar = consdata->vars[v];
    1587 break;
    1588 }
    1589
    1590 domain = ub - lb;
    1591 delta = REALABS(consdata->vals[v]) * domain;
    1592
    1593 if( delta > consdata->maxactdelta )
    1594 {
    1595 consdata->maxactdelta = delta;
    1596 consdata->maxactdeltavar = consdata->vars[v];
    1597 }
    1598 }
    1599}
    1600
    1601
    1602/** updates activities for a change in a bound */
    1603static
    1605 SCIP* scip, /**< SCIP data structure */
    1606 SCIP_CONSDATA* consdata, /**< linear constraint data */
    1607 SCIP_VAR* var, /**< variable that has been changed; can be NULL for global bound changes */
    1608 SCIP_Real oldbound, /**< old bound of variable */
    1609 SCIP_Real newbound, /**< new bound of variable */
    1610 SCIP_Real val, /**< coefficient of constraint entry */
    1611 SCIP_BOUNDTYPE boundtype, /**< type of the bound change */
    1612 SCIP_Bool global, /**< is it a global or a local bound change? */
    1613 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
    1614 )
    1615{
    1616 QUAD_MEMBER(SCIP_Real* activity);
    1617 QUAD_MEMBER(SCIP_Real delta);
    1618 SCIP_Real* lastactivity;
    1619 int* activityposinf;
    1620 int* activityneginf;
    1621 int* activityposhuge;
    1622 int* activityneghuge;
    1623 SCIP_Real oldcontribution;
    1624 SCIP_Real newcontribution;
    1625 SCIP_Bool validact;
    1626 SCIP_Bool finitenewbound;
    1627 SCIP_Bool hugevalnewcont;
    1628
    1629 assert(scip != NULL);
    1630 assert(consdata != NULL);
    1631 assert(global || (var != NULL));
    1632 assert(consdata->validactivities);
    1633 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
    1634 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
    1635 assert(consdata->lastminactivity < SCIP_INVALID);
    1636 assert(consdata->lastmaxactivity < SCIP_INVALID);
    1637 assert(consdata->minactivityneginf >= 0);
    1638 assert(consdata->minactivityposinf >= 0);
    1639 assert(consdata->maxactivityneginf >= 0);
    1640 assert(consdata->maxactivityposinf >= 0);
    1641 assert(consdata->minactivityneghuge >= 0);
    1642 assert(consdata->minactivityposhuge >= 0);
    1643 assert(consdata->maxactivityneghuge >= 0);
    1644 assert(consdata->maxactivityposhuge >= 0);
    1645 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
    1646 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
    1647 assert(consdata->lastglbminactivity < SCIP_INVALID);
    1648 assert(consdata->lastglbmaxactivity < SCIP_INVALID);
    1649 assert(consdata->glbminactivityneginf >= 0);
    1650 assert(consdata->glbminactivityposinf >= 0);
    1651 assert(consdata->glbmaxactivityneginf >= 0);
    1652 assert(consdata->glbmaxactivityposinf >= 0);
    1653 assert(consdata->glbminactivityneghuge >= 0);
    1654 assert(consdata->glbminactivityposhuge >= 0);
    1655 assert(consdata->glbmaxactivityneghuge >= 0);
    1656 assert(consdata->glbmaxactivityposhuge >= 0);
    1657
    1658 QUAD_ASSIGN(delta, 0.0);
    1659
    1660 /* we are updating global activities */
    1661 if( global )
    1662 {
    1663 /* depending on the boundtype and the coefficient, we choose the activity to be updated:
    1664 * lower bound + pos. coef: update minactivity
    1665 * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
    1666 * upper bound + pos. coef: update maxactivity
    1667 * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
    1668 */
    1669 if( boundtype == SCIP_BOUNDTYPE_LOWER )
    1670 {
    1671 if( val > 0.0 )
    1672 {
    1673 QUAD_ASSIGN_Q(activity, &consdata->glbminactivity);
    1674 lastactivity = &(consdata->lastglbminactivity);
    1675 activityposinf = &(consdata->glbminactivityposinf);
    1676 activityneginf = &(consdata->glbminactivityneginf);
    1677 activityposhuge = &(consdata->glbminactivityposhuge);
    1678 activityneghuge = &(consdata->glbminactivityneghuge);
    1679 validact = consdata->validglbminact;
    1680 }
    1681 else
    1682 {
    1683 QUAD_ASSIGN_Q(activity, &consdata->glbmaxactivity);
    1684 lastactivity = &(consdata->lastglbmaxactivity);
    1685 activityposinf = &(consdata->glbmaxactivityneginf);
    1686 activityneginf = &(consdata->glbmaxactivityposinf);
    1687 activityposhuge = &(consdata->glbmaxactivityposhuge);
    1688 activityneghuge = &(consdata->glbmaxactivityneghuge);
    1689 validact = consdata->validglbmaxact;
    1690 }
    1691 }
    1692 else
    1693 {
    1694 if( val > 0.0 )
    1695 {
    1696 QUAD_ASSIGN_Q(activity, &consdata->glbmaxactivity);
    1697 lastactivity = &(consdata->lastglbmaxactivity);
    1698 activityposinf = &(consdata->glbmaxactivityposinf);
    1699 activityneginf = &(consdata->glbmaxactivityneginf);
    1700 activityposhuge = &(consdata->glbmaxactivityposhuge);
    1701 activityneghuge = &(consdata->glbmaxactivityneghuge);
    1702 validact = consdata->validglbmaxact;
    1703 }
    1704 else
    1705 {
    1706 QUAD_ASSIGN_Q(activity, &consdata->glbminactivity);
    1707 lastactivity = &(consdata->lastglbminactivity);
    1708 activityposinf = &(consdata->glbminactivityneginf);
    1709 activityneginf = &(consdata->glbminactivityposinf);
    1710 activityposhuge = &(consdata->glbminactivityposhuge);
    1711 activityneghuge = &(consdata->glbminactivityneghuge);
    1712 validact = consdata->validglbminact;
    1713 }
    1714 }
    1715 }
    1716 /* we are updating local activities */
    1717 else
    1718 {
    1719 /* depending on the boundtype and the coefficient, we choose the activity to be updated:
    1720 * lower bound + pos. coef: update minactivity
    1721 * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
    1722 * upper bound + pos. coef: update maxactivity
    1723 * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
    1724 */
    1725 if( boundtype == SCIP_BOUNDTYPE_LOWER )
    1726 {
    1727 if( val > 0.0 )
    1728 {
    1729 QUAD_ASSIGN_Q(activity, &consdata->minactivity);
    1730 lastactivity = &(consdata->lastminactivity);
    1731 activityposinf = &(consdata->minactivityposinf);
    1732 activityneginf = &(consdata->minactivityneginf);
    1733 activityposhuge = &(consdata->minactivityposhuge);
    1734 activityneghuge = &(consdata->minactivityneghuge);
    1735 validact = consdata->validminact;
    1736 }
    1737 else
    1738 {
    1739 QUAD_ASSIGN_Q(activity, &consdata->maxactivity);
    1740 lastactivity = &(consdata->lastmaxactivity);
    1741 activityposinf = &(consdata->maxactivityneginf);
    1742 activityneginf = &(consdata->maxactivityposinf);
    1743 activityposhuge = &(consdata->maxactivityposhuge);
    1744 activityneghuge = &(consdata->maxactivityneghuge);
    1745 validact = consdata->validmaxact;
    1746 }
    1747 }
    1748 else
    1749 {
    1750 if( val > 0.0 )
    1751 {
    1752 QUAD_ASSIGN_Q(activity, &consdata->maxactivity);
    1753 lastactivity = &(consdata->lastmaxactivity);
    1754 activityposinf = &(consdata->maxactivityposinf);
    1755 activityneginf = &(consdata->maxactivityneginf);
    1756 activityposhuge = &(consdata->maxactivityposhuge);
    1757 activityneghuge = &(consdata->maxactivityneghuge);
    1758 validact = consdata->validmaxact;
    1759 }
    1760 else
    1761 {
    1762 QUAD_ASSIGN_Q(activity, &consdata->minactivity);
    1763 lastactivity = &(consdata->lastminactivity);
    1764 activityposinf = &(consdata->minactivityneginf);
    1765 activityneginf = &(consdata->minactivityposinf);
    1766 activityposhuge = &(consdata->minactivityposhuge);
    1767 activityneghuge = &(consdata->minactivityneghuge);
    1768 validact = consdata->validminact;
    1769 }
    1770 }
    1771 }
    1772
    1773 oldcontribution = val * oldbound;
    1774 newcontribution = val * newbound;
    1775 hugevalnewcont = SCIPisHugeValue(scip, REALABS(newcontribution));
    1776 finitenewbound = !SCIPisInfinity(scip, REALABS(newbound));
    1777
    1778 if( SCIPisInfinity(scip, REALABS(oldbound)) )
    1779 {
    1780 /* old bound was +infinity */
    1781 if( oldbound > 0.0 )
    1782 {
    1783 assert((*activityposinf) >= 1);
    1784
    1785 /* we only have to do something if the new bound is not again +infinity */
    1786 if( finitenewbound || newbound < 0.0 )
    1787 {
    1788 /* decrease the counter for positive infinite contributions */
    1789 (*activityposinf)--;
    1790
    1791 /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
    1792 if( !finitenewbound && newbound < 0.0 )
    1793 (*activityneginf)++;
    1794 else if( hugevalnewcont )
    1795 {
    1796 /* if the contribution of this variable is too large, increase the counter for huge values */
    1797 if( newcontribution > 0.0 )
    1798 (*activityposhuge)++;
    1799 else
    1800 (*activityneghuge)++;
    1801 }
    1802 /* "normal case": just add the contribution to the activity */
    1803 else
    1804 QUAD_ASSIGN(delta, newcontribution);
    1805 }
    1806 }
    1807 /* old bound was -infinity */
    1808 else
    1809 {
    1810 assert(oldbound < 0.0);
    1811 assert((*activityneginf) >= 1);
    1812
    1813 /* we only have to do something ig the new bound is not again -infinity */
    1814 if( finitenewbound || newbound > 0.0 )
    1815 {
    1816 /* decrease the counter for negative infinite contributions */
    1817 (*activityneginf)--;
    1818
    1819 /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
    1820 if( !finitenewbound && newbound > 0.0 )
    1821 (*activityposinf)++;
    1822 else if( hugevalnewcont )
    1823 {
    1824 /* if the contribution of this variable is too large, increase the counter for huge values */
    1825 if( newcontribution > 0.0 )
    1826 (*activityposhuge)++;
    1827 else
    1828 (*activityneghuge)++;
    1829 }
    1830 /* "normal case": just add the contribution to the activity */
    1831 else
    1832 QUAD_ASSIGN(delta, newcontribution);
    1833 }
    1834 }
    1835 }
    1836 else if( SCIPisHugeValue(scip, REALABS(oldcontribution)) )
    1837 {
    1838 /* old contribution was too large and positive */
    1839 if( oldcontribution > 0.0 )
    1840 {
    1841 assert((*activityposhuge) >= 1);
    1842
    1843 /* decrease the counter for huge positive contributions; it might be increased again later,
    1844 * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
    1845 */
    1846 (*activityposhuge)--;
    1847
    1848 if( !finitenewbound )
    1849 {
    1850 /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
    1851 if( newbound > 0.0 )
    1852 (*activityposinf)++;
    1853 /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
    1854 else
    1855 (*activityneginf)++;
    1856 }
    1857 else if( hugevalnewcont )
    1858 {
    1859 /* if the contribution of this variable is too large and positive, increase the corresponding counter */
    1860 if( newcontribution > 0.0 )
    1861 (*activityposhuge)++;
    1862 /* if the contribution of this variable is too large and negative, increase the corresponding counter */
    1863 else
    1864 (*activityneghuge)++;
    1865 }
    1866 /* "normal case": just add the contribution to the activity */
    1867 else
    1868 QUAD_ASSIGN(delta, newcontribution);
    1869 }
    1870 /* old contribution was too large and negative */
    1871 else
    1872 {
    1873 assert(oldcontribution < 0.0);
    1874 assert((*activityneghuge) >= 1);
    1875
    1876 /* decrease the counter for huge negative contributions; it might be increased again later,
    1877 * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
    1878 */
    1879 (*activityneghuge)--;
    1880
    1881 if( !finitenewbound )
    1882 {
    1883 /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
    1884 if( newbound > 0.0 )
    1885 (*activityposinf)++;
    1886 /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
    1887 else
    1888 (*activityneginf)++;
    1889 }
    1890 else if( hugevalnewcont )
    1891 {
    1892 /* if the contribution of this variable is too large and positive, increase the corresponding counter */
    1893 if( newcontribution > 0.0 )
    1894 (*activityposhuge)++;
    1895 /* if the contribution of this variable is too large and negative, increase the corresponding counter */
    1896 else
    1897 (*activityneghuge)++;
    1898 }
    1899 /* "normal case": just add the contribution to the activity */
    1900 else
    1901 QUAD_ASSIGN(delta, newcontribution);
    1902 }
    1903 }
    1904 /* old bound was finite and not too large */
    1905 else
    1906 {
    1907 if( !finitenewbound )
    1908 {
    1909 /* if the new bound is +infinity, the old contribution has to be subtracted
    1910 * and the counter for positive infinite contributions has to be increased
    1911 */
    1912 if( newbound > 0.0 )
    1913 {
    1914 (*activityposinf)++;
    1915 QUAD_ASSIGN(delta, -oldcontribution);
    1916 }
    1917 /* if the new bound is -infinity, the old contribution has to be subtracted
    1918 * and the counter for negative infinite contributions has to be increased
    1919 */
    1920 else
    1921 {
    1922 assert(newbound < 0.0 );
    1923
    1924 (*activityneginf)++;
    1925 QUAD_ASSIGN(delta, -oldcontribution);
    1926 }
    1927 }
    1928 /* if the contribution of this variable is too large, increase the counter for huge values */
    1929 else if( hugevalnewcont )
    1930 {
    1931 if( newcontribution > 0.0 )
    1932 {
    1933 (*activityposhuge)++;
    1934 QUAD_ASSIGN(delta, -oldcontribution);
    1935 }
    1936 else
    1937 {
    1938 (*activityneghuge)++;
    1939 QUAD_ASSIGN(delta, -oldcontribution);
    1940 }
    1941 }
    1942 /* "normal case": just update the activity */
    1943 else
    1944 {
    1945 QUAD_ASSIGN(delta, newcontribution);
    1946 SCIPquadprecSumQD(delta, delta, -oldcontribution);
    1947 }
    1948 }
    1949
    1950 /* update the activity, if the current value is valid and there was a change in the finite part */
    1951 if( validact && (QUAD_TO_DBL(delta) != 0.0) )
    1952 {
    1953 SCIP_Real curractivity;
    1954
    1955 /* if the absolute value of the activity is increased, this is regarded as reliable,
    1956 * otherwise, we check whether we can still trust the updated value
    1957 */
    1958 SCIPquadprecSumQD(*activity, *activity, QUAD_TO_DBL(delta));
    1959
    1960 curractivity = QUAD_TO_DBL(*activity);
    1961 assert(!SCIPisInfinity(scip, -curractivity) && !SCIPisInfinity(scip, curractivity));
    1962
    1963 if( REALABS((*lastactivity)) < REALABS(curractivity) )
    1964 {
    1965 (*lastactivity) = curractivity;
    1966 }
    1967 else
    1968 {
    1969 if( checkreliability && SCIPisUpdateUnreliable(scip, curractivity, (*lastactivity)) )
    1970 {
    1971 SCIPdebugMsg(scip, "%s activity of linear constraint unreliable after update: %16.9g\n",
    1972 (global ? "global " : ""), curractivity);
    1973
    1974 /* mark the activity that was just changed and is not reliable anymore to be invalid */
    1975 if( global )
    1976 {
    1977 if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
    1978 consdata->validglbminact = FALSE;
    1979 else
    1980 consdata->validglbmaxact = FALSE;
    1981 }
    1982 else
    1983 {
    1984 if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
    1985 consdata->validminact = FALSE;
    1986 else
    1987 consdata->validmaxact = FALSE;
    1988 }
    1989 }
    1990 }
    1991 }
    1992}
    1993
    1994/** updates minimum and maximum activity for a change in lower bound */
    1995static
    1997 SCIP* scip, /**< SCIP data structure */
    1998 SCIP_CONSDATA* consdata, /**< linear constraint data */
    1999 SCIP_VAR* var, /**< variable that has been changed */
    2000 SCIP_Real oldlb, /**< old lower bound of variable */
    2001 SCIP_Real newlb, /**< new lower bound of variable */
    2002 SCIP_Real val, /**< coefficient of constraint entry */
    2003 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
    2004 )
    2005{
    2006 assert(scip != NULL);
    2007 assert(consdata != NULL);
    2008 assert(var != NULL);
    2009
    2010 if( consdata->validactivities )
    2011 {
    2012 consdataUpdateActivities(scip, consdata, var, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, FALSE, checkreliability);
    2013
    2014 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->minactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->minactivity)));
    2015 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->maxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->maxactivity)));
    2016 }
    2017}
    2018
    2019/** updates minimum and maximum activity for a change in upper bound */
    2020static
    2022 SCIP* scip, /**< SCIP data structure */
    2023 SCIP_CONSDATA* consdata, /**< linear constraint data */
    2024 SCIP_VAR* var, /**< variable that has been changed */
    2025 SCIP_Real oldub, /**< old upper bound of variable */
    2026 SCIP_Real newub, /**< new upper bound of variable */
    2027 SCIP_Real val, /**< coefficient of constraint entry */
    2028 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
    2029 )
    2030{
    2031 assert(scip != NULL);
    2032 assert(consdata != NULL);
    2033 assert(var != NULL);
    2034
    2035 if( consdata->validactivities )
    2036 {
    2037 consdataUpdateActivities(scip, consdata, var, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, FALSE, checkreliability);
    2038
    2039 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->minactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->minactivity)));
    2040 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->maxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->maxactivity)));
    2041 }
    2042}
    2043
    2044/** updates minimum and maximum global activity for a change in the global lower bound */
    2045static
    2047 SCIP* scip, /**< SCIP data structure */
    2048 SCIP_CONSDATA* consdata, /**< linear constraint data */
    2049 SCIP_Real oldlb, /**< old lower bound of variable */
    2050 SCIP_Real newlb, /**< new lower bound of variable */
    2051 SCIP_Real val, /**< coefficient of constraint entry */
    2052 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
    2053 )
    2054{
    2055 assert(scip != NULL);
    2056 assert(consdata != NULL);
    2057
    2058 if( consdata->validactivities )
    2059 {
    2060 consdataUpdateActivities(scip, consdata, NULL, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, TRUE, checkreliability);
    2061
    2062 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbminactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbminactivity)));
    2063 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbmaxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbmaxactivity)));
    2064 }
    2065}
    2066
    2067/** updates minimum and maximum global activity for a change in global upper bound */
    2068static
    2070 SCIP* scip, /**< SCIP data structure */
    2071 SCIP_CONSDATA* consdata, /**< linear constraint data */
    2072 SCIP_Real oldub, /**< old upper bound of variable */
    2073 SCIP_Real newub, /**< new upper bound of variable */
    2074 SCIP_Real val, /**< coefficient of constraint entry */
    2075 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
    2076 )
    2077{
    2078 assert(scip != NULL);
    2079 assert(consdata != NULL);
    2080
    2081 if( consdata->validactivities )
    2082 {
    2083 consdataUpdateActivities(scip, consdata, NULL, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, TRUE, checkreliability);
    2084
    2085 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbminactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbminactivity)));
    2086 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbmaxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbmaxactivity)));
    2087 }
    2088}
    2089
    2090/** updates minimum and maximum activity and maximum absolute value for coefficient addition */
    2091static
    2093 SCIP* scip, /**< SCIP data structure */
    2094 SCIP_CONSDATA* consdata, /**< linear constraint data */
    2095 SCIP_VAR* var, /**< variable of constraint entry */
    2096 SCIP_Real val, /**< coefficient of constraint entry */
    2097 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
    2098 )
    2099{
    2100 assert(scip != NULL);
    2101 assert(consdata != NULL);
    2102 assert(var != NULL);
    2103 assert(!SCIPisZero(scip, val));
    2104
    2105 /* update maximum absolute value */
    2106 if( consdata->validmaxabsval )
    2107 {
    2108 SCIP_Real absval;
    2109
    2110 assert(consdata->maxabsval < SCIP_INVALID);
    2111
    2112 absval = REALABS(val);
    2113 consdata->maxabsval = MAX(consdata->maxabsval, absval);
    2114 }
    2115
    2116 /* update minimum absolute value */
    2117 if( consdata->validminabsval )
    2118 {
    2119 SCIP_Real absval;
    2120
    2121 assert(consdata->minabsval < SCIP_INVALID);
    2122
    2123 absval = REALABS(val);
    2124 consdata->minabsval = MIN(consdata->minabsval, absval);
    2125 }
    2126
    2127 /* update minimum and maximum activity */
    2128 if( consdata->validactivities )
    2129 {
    2130 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
    2131 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
    2132 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
    2133 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
    2134
    2135 consdataUpdateActivitiesLb(scip, consdata, var, 0.0, SCIPvarGetLbLocal(var), val, checkreliability);
    2136 consdataUpdateActivitiesUb(scip, consdata, var, 0.0, SCIPvarGetUbLocal(var), val, checkreliability);
    2137 consdataUpdateActivitiesGlbLb(scip, consdata, 0.0, SCIPvarGetLbGlobal(var), val, checkreliability);
    2138 consdataUpdateActivitiesGlbUb(scip, consdata, 0.0, SCIPvarGetUbGlobal(var), val, checkreliability);
    2139 }
    2140
    2141 /* update maximum activity delta */
    2142 if( consdata->maxactdeltavar == NULL || !SCIPisInfinity(scip, consdata->maxactdelta) )
    2143 {
    2144 SCIP_Real lb = SCIPvarGetLbLocal(var);
    2145 SCIP_Real ub = SCIPvarGetUbLocal(var);
    2146
    2147 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
    2148 {
    2149 consdata->maxactdelta = SCIPinfinity(scip);
    2150 consdata->maxactdeltavar = var;
    2151 }
    2152 else if( consdata->maxactdeltavar != NULL )
    2153 {
    2154 SCIP_Real domain = ub - lb;
    2155 SCIP_Real delta = REALABS(val) * domain;
    2156
    2157 if( delta > consdata->maxactdelta )
    2158 {
    2159 consdata->maxactdelta = delta;
    2160 consdata->maxactdeltavar = var;
    2161 }
    2162 }
    2163 }
    2164}
    2165
    2166/** updates minimum and maximum activity for coefficient deletion, invalidates maximum absolute value if necessary */
    2167static
    2169 SCIP* scip, /**< SCIP data structure */
    2170 SCIP_CONSDATA* consdata, /**< linear constraint data */
    2171 SCIP_VAR* var, /**< variable of constraint entry */
    2172 SCIP_Real val, /**< coefficient of constraint entry */
    2173 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
    2174 )
    2175{
    2176 assert(scip != NULL);
    2177 assert(consdata != NULL);
    2178 assert(var != NULL);
    2179 assert(!SCIPisZero(scip, val));
    2180
    2181 /* invalidate maximum absolute value, if this coefficient was the maximum */
    2182 if( consdata->validmaxabsval )
    2183 {
    2184 SCIP_Real absval;
    2185
    2186 absval = REALABS(val);
    2187
    2188 if( SCIPisEQ(scip, absval, consdata->maxabsval) )
    2189 {
    2190 consdata->validmaxabsval = FALSE;
    2191 consdata->maxabsval = SCIP_INVALID;
    2192 }
    2193 }
    2194
    2195 /* invalidate minimum absolute value, if this coefficient was the minimum */
    2196 if( consdata->validminabsval )
    2197 {
    2198 SCIP_Real absval;
    2199
    2200 absval = REALABS(val);
    2201
    2202 if( SCIPisEQ(scip, absval, consdata->minabsval) )
    2203 {
    2204 consdata->validminabsval = FALSE;
    2205 consdata->minabsval = SCIP_INVALID;
    2206 }
    2207 }
    2208
    2209 /* update minimum and maximum activity */
    2210 if( consdata->validactivities )
    2211 {
    2212 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
    2213 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
    2214 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
    2215 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
    2216
    2217 consdataUpdateActivitiesLb(scip, consdata, var, SCIPvarGetLbLocal(var), 0.0, val, checkreliability);
    2218 consdataUpdateActivitiesUb(scip, consdata, var, SCIPvarGetUbLocal(var), 0.0, val, checkreliability);
    2219 consdataUpdateActivitiesGlbLb(scip, consdata, SCIPvarGetLbGlobal(var), 0.0, val, checkreliability);
    2220 consdataUpdateActivitiesGlbUb(scip, consdata, SCIPvarGetUbGlobal(var), 0.0, val, checkreliability);
    2221 }
    2222
    2223 /* reset maximum activity delta so that it will be recalculated on the next real propagation */
    2224 if( consdata->maxactdeltavar == var )
    2225 {
    2226 consdata->maxactdelta = SCIP_INVALID;
    2227 consdata->maxactdeltavar = NULL;
    2228 }
    2229}
    2230
    2231/** updates minimum and maximum activity for coefficient change, invalidates maximum absolute value if necessary */
    2232static
    2234 SCIP* scip, /**< SCIP data structure */
    2235 SCIP_CONSDATA* consdata, /**< linear constraint data */
    2236 SCIP_VAR* var, /**< variable of constraint entry */
    2237 SCIP_Real oldval, /**< old coefficient of constraint entry */
    2238 SCIP_Real newval, /**< new coefficient of constraint entry */
    2239 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
    2240 )
    2241{
    2242 /* @todo do something more clever here, e.g. if oldval * newval >= 0, do the update directly */
    2243 consdataUpdateDelCoef(scip, consdata, var, oldval, checkreliability);
    2244 consdataUpdateAddCoef(scip, consdata, var, newval, checkreliability);
    2245}
    2246
    2247/** returns the maximum absolute value of all coefficients in the constraint */
    2248static
    2250 SCIP_CONSDATA* consdata /**< linear constraint data */
    2251 )
    2252{
    2253 assert(consdata != NULL);
    2254
    2255 if( !consdata->validmaxabsval )
    2256 consdataCalcMaxAbsval(consdata);
    2257 assert(consdata->validmaxabsval);
    2258 assert(consdata->maxabsval < SCIP_INVALID);
    2259
    2260 return consdata->maxabsval;
    2261}
    2262
    2263/** returns the minimum absolute value of all coefficients in the constraint */
    2264static
    2266 SCIP_CONSDATA* consdata /**< linear constraint data */
    2267 )
    2268{
    2269 assert(consdata != NULL);
    2270
    2271 if( !consdata->validminabsval )
    2272 consdataCalcMinAbsval(consdata);
    2273 assert(consdata->validminabsval);
    2274 assert(consdata->minabsval < SCIP_INVALID);
    2275
    2276 return consdata->minabsval;
    2277}
    2278
    2279/** calculates minimum and maximum local and global activity for constraint from scratch;
    2280 * additionally recalculates maximum absolute value of coefficients
    2281 */
    2282static
    2284 SCIP* scip, /**< SCIP data structure */
    2285 SCIP_CONSDATA* consdata /**< linear constraint data */
    2286 )
    2287{
    2288 int i;
    2289
    2290 assert(scip != NULL);
    2291 assert(consdata != NULL);
    2292 assert(!consdata->validactivities);
    2293 assert(QUAD_TO_DBL(consdata->minactivity) >= SCIP_INVALID || consdata->validminact);
    2294 assert(QUAD_TO_DBL(consdata->maxactivity) >= SCIP_INVALID || consdata->validmaxact);
    2295 assert(QUAD_TO_DBL(consdata->glbminactivity) >= SCIP_INVALID || consdata->validglbminact);
    2296 assert(QUAD_TO_DBL(consdata->glbmaxactivity) >= SCIP_INVALID || consdata->validglbmaxact);
    2297
    2298 consdata->validmaxabsval = TRUE;
    2299 consdata->validminabsval = TRUE;
    2300 consdata->validactivities = TRUE;
    2301 consdata->validminact = TRUE;
    2302 consdata->validmaxact = TRUE;
    2303 consdata->validglbminact = TRUE;
    2304 consdata->validglbmaxact = TRUE;
    2305 consdata->maxabsval = 0.0;
    2306 consdata->minabsval = (consdata->nvars == 0 ? 0.0 : REALABS(consdata->vals[0]));
    2307 QUAD_ASSIGN(consdata->minactivity, 0.0);
    2308 QUAD_ASSIGN(consdata->maxactivity, 0.0);
    2309 consdata->lastminactivity = 0.0;
    2310 consdata->lastmaxactivity = 0.0;
    2311 consdata->minactivityneginf = 0;
    2312 consdata->minactivityposinf = 0;
    2313 consdata->maxactivityneginf = 0;
    2314 consdata->maxactivityposinf = 0;
    2315 consdata->minactivityneghuge = 0;
    2316 consdata->minactivityposhuge = 0;
    2317 consdata->maxactivityneghuge = 0;
    2318 consdata->maxactivityposhuge = 0;
    2319 QUAD_ASSIGN(consdata->glbminactivity, 0.0);
    2320 QUAD_ASSIGN(consdata->glbmaxactivity, 0.0);
    2321 consdata->lastglbminactivity = 0.0;
    2322 consdata->lastglbmaxactivity = 0.0;
    2323 consdata->glbminactivityneginf = 0;
    2324 consdata->glbminactivityposinf = 0;
    2325 consdata->glbmaxactivityneginf = 0;
    2326 consdata->glbmaxactivityposinf = 0;
    2327 consdata->glbminactivityneghuge = 0;
    2328 consdata->glbminactivityposhuge = 0;
    2329 consdata->glbmaxactivityneghuge = 0;
    2330 consdata->glbmaxactivityposhuge = 0;
    2331
    2332 for( i = 0; i < consdata->nvars; ++i )
    2333 consdataUpdateAddCoef(scip, consdata, consdata->vars[i], consdata->vals[i], FALSE);
    2334
    2335 consdata->lastminactivity = QUAD_TO_DBL(consdata->minactivity);
    2336 consdata->lastmaxactivity = QUAD_TO_DBL(consdata->maxactivity);
    2337 consdata->lastglbminactivity = QUAD_TO_DBL(consdata->glbminactivity);
    2338 consdata->lastglbmaxactivity = QUAD_TO_DBL(consdata->glbmaxactivity);
    2339}
    2340
    2341/** gets minimal activity for constraint and given values of counters for infinite and huge contributions
    2342 * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
    2343 */
    2344static
    2346 SCIP* scip, /**< SCIP data structure */
    2347 SCIP_CONSDATA* consdata, /**< linear constraint */
    2348 int posinf, /**< number of coefficients contributing pos. infinite value */
    2349 int neginf, /**< number of coefficients contributing neg. infinite value */
    2350 int poshuge, /**< number of coefficients contributing huge pos. value */
    2351 int neghuge, /**< number of coefficients contributing huge neg. value */
    2352 SCIP_Real delta, /**< value to subtract from stored minactivity
    2353 * (contribution of the variable set to zero when getting residual activity) */
    2354 SCIP_Bool global, /**< should the global or local minimal activity be returned? */
    2355 SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
    2356 SCIP_Real* minactivity, /**< pointer to store the minimal activity */
    2357 SCIP_Bool* istight, /**< pointer to store whether activity bound is tight to variable bounds
    2358 * i.e. is the actual minactivity (otherwise a lower bound is provided) */
    2359 SCIP_Bool* issettoinfinity /**< pointer to store whether minactivity was set to infinity or calculated */
    2360 )
    2361{
    2362 assert(scip != NULL);
    2363 assert(consdata != NULL);
    2364 assert(posinf >= 0);
    2365 assert(neginf >= 0);
    2366 assert(poshuge >= 0);
    2367 assert(neghuge >= 0);
    2368 assert(minactivity != NULL);
    2369 assert(istight != NULL);
    2370 assert(issettoinfinity != NULL);
    2371
    2372 /* if we have neg. infinite contributions, the minactivity is -infty */
    2373 if( neginf > 0 )
    2374 {
    2375 *minactivity = -SCIPinfinity(scip);
    2376 *issettoinfinity = TRUE;
    2377 *istight = posinf == 0;
    2378 }
    2379 /* if we have pos. (and no neg.) infinite contributions, the minactivity is +infty */
    2380 else if( posinf > 0 )
    2381 {
    2382 *minactivity = SCIPinfinity(scip);
    2383 *issettoinfinity = TRUE;
    2384 *istight = TRUE;
    2385 }
    2386 /* if we have neg. huge contributions or do not need a good relaxation, we just return -infty as minactivity */
    2387 else if( neghuge > 0 || ( poshuge > 0 && !goodrelax ) )
    2388 {
    2389 *minactivity = -SCIPinfinity(scip);
    2390 *issettoinfinity = TRUE;
    2391 *istight = FALSE;
    2392 }
    2393 else
    2394 {
    2395 SCIP_Real QUAD(tmpactivity);
    2396
    2397 /* recompute minactivity if it is not valid */
    2398 if( global )
    2399 {
    2400 if( !consdata->validglbminact )
    2402 assert(consdata->validglbminact);
    2403
    2404 QUAD_ASSIGN_Q(tmpactivity, consdata->glbminactivity);
    2405 }
    2406 else
    2407 {
    2408 if( !consdata->validminact )
    2410 assert(consdata->validminact);
    2411
    2412 QUAD_ASSIGN_Q(tmpactivity, consdata->minactivity);
    2413 }
    2414
    2415 /* calculate residual minactivity */
    2416 SCIPquadprecSumQD(tmpactivity, tmpactivity, -delta);
    2417
    2418 /* we have no infinite and no neg. huge contributions, but pos. huge contributions; a feasible relaxation of the
    2419 * minactivity is given by adding the number of positive huge contributions times the huge value
    2420 */
    2421 if( poshuge > 0 )
    2422 {
    2423 SCIPquadprecSumQD(tmpactivity, tmpactivity, poshuge * SCIPgetHugeValue(scip));
    2424 *istight = FALSE;
    2425 }
    2426 /* all counters are zero, so the minactivity is tight */
    2427 else
    2428 *istight = TRUE;
    2429
    2430 /* round residual minactivity */
    2431 *minactivity = QUAD_TO_DBL(tmpactivity);
    2432 *issettoinfinity = FALSE;
    2433 }
    2434}
    2435
    2436/** gets maximal activity for constraint and given values of counters for infinite and huge contributions
    2437 * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
    2438 */
    2439static
    2441 SCIP* scip, /**< SCIP data structure */
    2442 SCIP_CONSDATA* consdata, /**< linear constraint */
    2443 int posinf, /**< number of coefficients contributing pos. infinite value */
    2444 int neginf, /**< number of coefficients contributing neg. infinite value */
    2445 int poshuge, /**< number of coefficients contributing huge pos. value */
    2446 int neghuge, /**< number of coefficients contributing huge neg. value */
    2447 SCIP_Real delta, /**< value to subtract from stored maxactivity
    2448 * (contribution of the variable set to zero when getting residual activity) */
    2449 SCIP_Bool global, /**< should the global or local maximal activity be returned? */
    2450 SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
    2451 SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
    2452 SCIP_Bool* istight, /**< pointer to store whether activity bound is tight to variable bounds
    2453 * i.e. is the actual maxactivity (otherwise an upper bound is provided) */
    2454 SCIP_Bool* issettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
    2455 )
    2456{
    2457 assert(scip != NULL);
    2458 assert(consdata != NULL);
    2459 assert(posinf >= 0);
    2460 assert(neginf >= 0);
    2461 assert(poshuge >= 0);
    2462 assert(neghuge >= 0);
    2463 assert(maxactivity != NULL);
    2464 assert(istight != NULL);
    2465 assert(issettoinfinity != NULL);
    2466
    2467 /* if we have pos. infinite contributions, the maxactivity is +infty */
    2468 if( posinf > 0 )
    2469 {
    2470 *maxactivity = SCIPinfinity(scip);
    2471 *issettoinfinity = TRUE;
    2472 *istight = neginf == 0;
    2473 }
    2474 /* if we have neg. (and no pos.) infinite contributions, the maxactivity is -infty */
    2475 else if( neginf > 0 )
    2476 {
    2477 *maxactivity = -SCIPinfinity(scip);
    2478 *issettoinfinity = TRUE;
    2479 *istight = TRUE;
    2480 }
    2481 /* if we have pos. huge contributions or do not need a good relaxation, we just return +infty as maxactivity */
    2482 else if( poshuge > 0 || ( neghuge > 0 && !goodrelax ) )
    2483 {
    2484 *maxactivity = SCIPinfinity(scip);
    2485 *issettoinfinity = TRUE;
    2486 *istight = FALSE;
    2487 }
    2488 else
    2489 {
    2490 SCIP_Real QUAD(tmpactivity);
    2491
    2492 /* recompute maxactivity if it is not valid */
    2493 if( global )
    2494 {
    2495 if( !consdata->validglbmaxact )
    2497 assert(consdata->validglbmaxact);
    2498
    2499 QUAD_ASSIGN_Q(tmpactivity, consdata->glbmaxactivity);
    2500 }
    2501 else
    2502 {
    2503 if( !consdata->validmaxact )
    2505 assert(consdata->validmaxact);
    2506
    2507 QUAD_ASSIGN_Q(tmpactivity, consdata->maxactivity);
    2508 }
    2509
    2510 /* calculate residual maxactivity */
    2511 SCIPquadprecSumQD(tmpactivity, tmpactivity, -delta);
    2512
    2513 /* we have no infinite and no pos. huge contributions, but neg. huge contributions; a feasible relaxation of the
    2514 * maxactivity is given by subtracting the number of negative huge contributions times the huge value
    2515 */
    2516 if( neghuge > 0 )
    2517 {
    2518 SCIPquadprecSumQD(tmpactivity, tmpactivity, -neghuge * SCIPgetHugeValue(scip));
    2519 *istight = FALSE;
    2520 }
    2521 /* all counters are zero, so the maxactivity is tight */
    2522 else
    2523 *istight = TRUE;
    2524
    2525 /* round residual maxactivity */
    2526 *maxactivity = QUAD_TO_DBL(tmpactivity);
    2527 *issettoinfinity = FALSE;
    2528 }
    2529}
    2530
    2531/** gets activity bounds for constraint */
    2532static
    2534 SCIP* scip, /**< SCIP data structure */
    2535 SCIP_CONSDATA* consdata, /**< linear constraint */
    2536 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
    2537 * relaxed activities ignored, anyway? */
    2538 SCIP_Real* minactivity, /**< pointer to store the minimal activity */
    2539 SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
    2540 SCIP_Bool* ismintight, /**< pointer to store whether the minactivity bound is tight
    2541 * i.e. is the actual minactivity (otherwise a lower bound is provided) */
    2542 SCIP_Bool* ismaxtight, /**< pointer to store whether the maxactivity bound is tight
    2543 * i.e. is the actual maxactivity (otherwise an upper bound is provided) */
    2544 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minactivity was set to infinity or calculated */
    2545 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
    2546
    2547 )
    2548{
    2549 assert(scip != NULL);
    2550 assert(consdata != NULL);
    2551 assert(minactivity != NULL);
    2552 assert(maxactivity != NULL);
    2553 assert(isminsettoinfinity != NULL);
    2554 assert(ismaxsettoinfinity != NULL);
    2555
    2556 if( !consdata->validactivities )
    2557 {
    2558 consdataCalcActivities(scip, consdata);
    2559 assert(consdata->validminact);
    2560 assert(consdata->validmaxact);
    2561 }
    2562 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
    2563 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
    2564 assert(consdata->minactivityneginf >= 0);
    2565 assert(consdata->minactivityposinf >= 0);
    2566 assert(consdata->maxactivityneginf >= 0);
    2567 assert(consdata->maxactivityposinf >= 0);
    2568
    2569 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
    2570 consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
    2571 minactivity, ismintight, isminsettoinfinity);
    2572
    2573 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
    2574 consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
    2575 maxactivity, ismaxtight, ismaxsettoinfinity);
    2576}
    2577
    2578/** calculates activity bounds for constraint after setting variable to zero */
    2579static
    2581 SCIP* scip, /**< SCIP data structure */
    2582 SCIP_CONSDATA* consdata, /**< linear constraint */
    2583 SCIP_VAR* cancelvar, /**< variable to calculate activity residual for */
    2584 SCIP_Real* resactivity, /**< pointer to store the residual activity */
    2585 SCIP_Bool isminresact, /**< should minimal or maximal residual activity be calculated? */
    2586 SCIP_Bool useglobalbounds /**< should global or local bounds be used? */
    2587 )
    2588{
    2589 SCIP_VAR* var;
    2590 SCIP_Real val;
    2591 SCIP_Real lb;
    2592 SCIP_Real ub;
    2593 int v;
    2594
    2595 assert(scip != NULL);
    2596 assert(consdata != NULL);
    2597 assert(cancelvar != NULL);
    2598 assert(resactivity != NULL);
    2599
    2600 *resactivity = 0.0;
    2601
    2602 for( v = 0; v < consdata->nvars; ++v )
    2603 {
    2604 var = consdata->vars[v];
    2605 assert(var != NULL);
    2606 if( var == cancelvar )
    2607 continue;
    2608
    2609 val = consdata->vals[v];
    2610
    2611 if( useglobalbounds )
    2612 {
    2613 lb = SCIPvarGetLbGlobal(var);
    2614 ub = SCIPvarGetUbGlobal(var);
    2615 }
    2616 else
    2617 {
    2618 lb = SCIPvarGetLbLocal(var);
    2619 ub = SCIPvarGetUbLocal(var);
    2620 }
    2621
    2622 assert(!SCIPisZero(scip, val));
    2623 assert(SCIPisLE(scip, lb, ub));
    2624
    2625 if( val > 0.0 )
    2626 {
    2627 if( isminresact )
    2628 {
    2629 assert(!SCIPisInfinity(scip, -lb));
    2630 assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
    2631 *resactivity += val*lb;
    2632 }
    2633 else
    2634 {
    2635 assert(!SCIPisInfinity(scip, ub));
    2636 assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
    2637 *resactivity += val*ub;
    2638 }
    2639 }
    2640 else
    2641 {
    2642 if( isminresact)
    2643 {
    2644 assert(!SCIPisInfinity(scip, ub));
    2645 assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
    2646 *resactivity += val*ub;
    2647 }
    2648 else
    2649 {
    2650 assert(!SCIPisInfinity(scip, -lb));
    2651 assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
    2652 *resactivity += val*lb;
    2653 }
    2654 }
    2655 }
    2656 assert(!SCIPisInfinity(scip, *resactivity) && !SCIPisInfinity(scip, -(*resactivity)));
    2657}
    2658
    2659/** gets activity bounds for constraint after setting variable to zero */
    2660static
    2662 SCIP* scip, /**< SCIP data structure */
    2663 SCIP_CONSDATA* consdata, /**< linear constraint */
    2664 SCIP_VAR* var, /**< variable to calculate activity residual for */
    2665 SCIP_Real val, /**< coefficient value of variable in linear constraint */
    2666 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
    2667 * relaxed acticities ignored, anyway? */
    2668 SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity */
    2669 SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity */
    2670 SCIP_Bool* ismintight, /**< pointer to store whether the residual minactivity bound is tight
    2671 * i.e. is the actual residual minactivity (otherwise a lower bound is provided) */
    2672 SCIP_Bool* ismaxtight, /**< pointer to store whether the residual maxactivity bound is tight
    2673 * i.e. is the actual residual maxactivity (otherwise an upper bound is provided) */
    2674 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
    2675 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
    2676 )
    2677{
    2678 SCIP_Real minactbound;
    2679 SCIP_Real maxactbound;
    2680 SCIP_Real absval;
    2681
    2682 assert(scip != NULL);
    2683 assert(consdata != NULL);
    2684 assert(var != NULL);
    2685 assert(minresactivity != NULL);
    2686 assert(maxresactivity != NULL);
    2687 assert(ismintight != NULL);
    2688 assert(ismaxtight != NULL);
    2689 assert(isminsettoinfinity != NULL);
    2690 assert(ismaxsettoinfinity != NULL);
    2691
    2692 /* get activity bounds of linear constraint */
    2693 if( !consdata->validactivities )
    2694 {
    2695 consdataCalcActivities(scip, consdata);
    2696 assert(consdata->validminact);
    2697 assert(consdata->validmaxact);
    2698 }
    2699 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
    2700 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
    2701 assert(consdata->minactivityneginf >= 0);
    2702 assert(consdata->minactivityposinf >= 0);
    2703 assert(consdata->maxactivityneginf >= 0);
    2704 assert(consdata->maxactivityposinf >= 0);
    2705 assert(consdata->minactivityneghuge >= 0);
    2706 assert(consdata->minactivityposhuge >= 0);
    2707 assert(consdata->maxactivityneghuge >= 0);
    2708 assert(consdata->maxactivityposhuge >= 0);
    2709
    2710 if( val > 0.0 )
    2711 {
    2712 minactbound = SCIPvarGetLbLocal(var);
    2713 maxactbound = SCIPvarGetUbLocal(var);
    2714 absval = val;
    2715 }
    2716 else
    2717 {
    2718 minactbound = -SCIPvarGetUbLocal(var);
    2719 maxactbound = -SCIPvarGetLbLocal(var);
    2720 absval = -val;
    2721 }
    2722
    2723 /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
    2724 * and contribution of variable set to zero that has to be subtracted from finite part of activity
    2725 */
    2726 if( SCIPisInfinity(scip, minactbound) )
    2727 {
    2728 assert(consdata->minactivityposinf >= 1);
    2729
    2730 getMinActivity(scip, consdata, consdata->minactivityposinf - 1, consdata->minactivityneginf,
    2731 consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
    2732 minresactivity, ismintight, isminsettoinfinity);
    2733 }
    2734 else if( SCIPisInfinity(scip, -minactbound) )
    2735 {
    2736 assert(consdata->minactivityneginf >= 1);
    2737
    2738 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf - 1,
    2739 consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
    2740 minresactivity, ismintight, isminsettoinfinity);
    2741 }
    2742 else if( SCIPisHugeValue(scip, minactbound * absval) )
    2743 {
    2744 assert(consdata->minactivityposhuge >= 1);
    2745
    2746 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
    2747 consdata->minactivityposhuge - 1, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
    2748 minresactivity, ismintight, isminsettoinfinity);
    2749 }
    2750 else if( SCIPisHugeValue(scip, -minactbound * absval) )
    2751 {
    2752 assert(consdata->minactivityneghuge >= 1);
    2753
    2754 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
    2755 consdata->minactivityposhuge, consdata->minactivityneghuge - 1, 0.0, FALSE, goodrelax,
    2756 minresactivity, ismintight, isminsettoinfinity);
    2757 }
    2758 else
    2759 {
    2760 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
    2761 consdata->minactivityposhuge, consdata->minactivityneghuge, absval * minactbound, FALSE, goodrelax,
    2762 minresactivity, ismintight, isminsettoinfinity);
    2763 }
    2764
    2765 /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
    2766 * and contribution of variable set to zero that has to be subtracted from finite part of activity
    2767 */
    2768 if( SCIPisInfinity(scip, -maxactbound) )
    2769 {
    2770 assert(consdata->maxactivityneginf >= 1);
    2771
    2772 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf - 1,
    2773 consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
    2774 maxresactivity, ismaxtight, ismaxsettoinfinity);
    2775 }
    2776 else if( SCIPisInfinity(scip, maxactbound) )
    2777 {
    2778 assert(consdata->maxactivityposinf >= 1);
    2779
    2780 getMaxActivity(scip, consdata, consdata->maxactivityposinf - 1, consdata->maxactivityneginf,
    2781 consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
    2782 maxresactivity, ismaxtight, ismaxsettoinfinity);
    2783 }
    2784 else if( SCIPisHugeValue(scip, absval * maxactbound) )
    2785 {
    2786 assert(consdata->maxactivityposhuge >= 1);
    2787
    2788 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
    2789 consdata->maxactivityposhuge - 1, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
    2790 maxresactivity, ismaxtight, ismaxsettoinfinity);
    2791 }
    2792 else if( SCIPisHugeValue(scip, -absval * maxactbound) )
    2793 {
    2794 assert(consdata->maxactivityneghuge >= 1);
    2795
    2796 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
    2797 consdata->maxactivityposhuge, consdata->maxactivityneghuge - 1, 0.0, FALSE, goodrelax,
    2798 maxresactivity, ismaxtight, ismaxsettoinfinity);
    2799 }
    2800 else
    2801 {
    2802 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
    2803 consdata->maxactivityposhuge, consdata->maxactivityneghuge, absval * maxactbound, FALSE, goodrelax,
    2804 maxresactivity, ismaxtight, ismaxsettoinfinity);
    2805 }
    2806}
    2807
    2808/** gets global activity bounds for constraint */
    2809static
    2811 SCIP* scip, /**< SCIP data structure */
    2812 SCIP_CONSDATA* consdata, /**< linear constraint */
    2813 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
    2814 * relaxed acticities ignored, anyway? */
    2815 SCIP_Real* glbminactivity, /**< pointer to store the minimal activity, or NULL, if not needed */
    2816 SCIP_Real* glbmaxactivity, /**< pointer to store the maximal activity, or NULL, if not needed */
    2817 SCIP_Bool* ismintight, /**< pointer to store whether the minactivity bound is tight
    2818 * i.e. is the actual minactivity (otherwise a lower bound is provided) */
    2819 SCIP_Bool* ismaxtight, /**< pointer to store whether the maxactivity bound is tight
    2820 * i.e. is the actual maxactivity (otherwise an upper bound is provided) */
    2821 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
    2822 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
    2823 )
    2824{
    2825 assert(scip != NULL);
    2826 assert(consdata != NULL);
    2827 assert((glbminactivity != NULL && ismintight != NULL && isminsettoinfinity != NULL)
    2828 || (glbmaxactivity != NULL && ismaxtight != NULL && ismaxsettoinfinity != NULL));
    2829
    2830 if( !consdata->validactivities )
    2831 {
    2832 consdataCalcActivities(scip, consdata);
    2833 assert(consdata->validglbminact);
    2834 assert(consdata->validglbmaxact);
    2835 }
    2836 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
    2837 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
    2838 assert(consdata->glbminactivityneginf >= 0);
    2839 assert(consdata->glbminactivityposinf >= 0);
    2840 assert(consdata->glbmaxactivityneginf >= 0);
    2841 assert(consdata->glbmaxactivityposinf >= 0);
    2842 assert(consdata->glbminactivityneghuge >= 0);
    2843 assert(consdata->glbminactivityposhuge >= 0);
    2844 assert(consdata->glbmaxactivityneghuge >= 0);
    2845 assert(consdata->glbmaxactivityposhuge >= 0);
    2846
    2847 if( glbminactivity != NULL )
    2848 {
    2849 assert(isminsettoinfinity != NULL);
    2850 assert(ismintight != NULL);
    2851
    2852 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
    2853 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
    2854 glbminactivity, ismintight, isminsettoinfinity);
    2855 }
    2856
    2857 if( glbmaxactivity != NULL )
    2858 {
    2859 assert(ismaxsettoinfinity != NULL);
    2860 assert(ismaxtight != NULL);
    2861
    2862 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
    2863 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
    2864 glbmaxactivity, ismaxtight, ismaxsettoinfinity);
    2865 }
    2866}
    2867
    2868/** gets global activity bounds for constraint after setting variable to zero */
    2869static
    2871 SCIP* scip, /**< SCIP data structure */
    2872 SCIP_CONSDATA* consdata, /**< linear constraint */
    2873 SCIP_VAR* var, /**< variable to calculate activity residual for */
    2874 SCIP_Real val, /**< coefficient value of variable in linear constraint */
    2875 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
    2876 * relaxed acticities ignored, anyway? */
    2877 SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity, or NULL, if not needed */
    2878 SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity, or NULL, if not needed */
    2879 SCIP_Bool* ismintight, /**< pointer to store whether the residual minactivity bound is tight
    2880 * i.e. is the actual residual minactivity (otherwise a lower bound is provided) */
    2881 SCIP_Bool* ismaxtight, /**< pointer to store whether the residual maxactivity bound is tight
    2882 * i.e. is the actual residual maxactivity (otherwise an upper bound is provided) */
    2883 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
    2884 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
    2885 )
    2886{
    2887 SCIP_Real minactbound;
    2888 SCIP_Real maxactbound;
    2889 SCIP_Real absval;
    2890
    2891 assert(scip != NULL);
    2892 assert(consdata != NULL);
    2893 assert(var != NULL);
    2894 assert((minresactivity != NULL && ismintight != NULL && isminsettoinfinity != NULL )
    2895 || (maxresactivity != NULL && ismaxtight != NULL && ismaxsettoinfinity != NULL));
    2896
    2897 /* get activity bounds of linear constraint */
    2898 if( !consdata->validactivities )
    2899 consdataCalcActivities(scip, consdata);
    2900
    2901 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
    2902 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
    2903 assert(consdata->glbminactivityneginf >= 0);
    2904 assert(consdata->glbminactivityposinf >= 0);
    2905 assert(consdata->glbmaxactivityneginf >= 0);
    2906 assert(consdata->glbmaxactivityposinf >= 0);
    2907
    2908 if( val > 0.0 )
    2909 {
    2910 minactbound = SCIPvarGetLbGlobal(var);
    2911 maxactbound = SCIPvarGetUbGlobal(var);
    2912 absval = val;
    2913 }
    2914 else
    2915 {
    2916 minactbound = -SCIPvarGetUbGlobal(var);
    2917 maxactbound = -SCIPvarGetLbGlobal(var);
    2918 absval = -val;
    2919 }
    2920
    2921 if( minresactivity != NULL )
    2922 {
    2923 assert(isminsettoinfinity != NULL);
    2924 assert(ismintight != NULL);
    2925
    2926 /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
    2927 * and contribution of variable set to zero that has to be subtracted from finite part of activity
    2928 */
    2929 if( SCIPisInfinity(scip, minactbound) )
    2930 {
    2931 assert(consdata->glbminactivityposinf >= 1);
    2932
    2933 getMinActivity(scip, consdata, consdata->glbminactivityposinf - 1, consdata->glbminactivityneginf,
    2934 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
    2935 minresactivity, ismintight, isminsettoinfinity);
    2936 }
    2937 else if( SCIPisInfinity(scip, -minactbound) )
    2938 {
    2939 assert(consdata->glbminactivityneginf >= 1);
    2940
    2941 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf - 1,
    2942 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
    2943 minresactivity, ismintight, isminsettoinfinity);
    2944 }
    2945 else if( SCIPisHugeValue(scip, minactbound * absval) )
    2946 {
    2947 assert(consdata->glbminactivityposhuge >= 1);
    2948
    2949 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
    2950 consdata->glbminactivityposhuge - 1, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
    2951 minresactivity, ismintight, isminsettoinfinity);
    2952 }
    2953 else if( SCIPisHugeValue(scip, -minactbound * absval) )
    2954 {
    2955 assert(consdata->glbminactivityneghuge >= 1);
    2956
    2957 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
    2958 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge - 1, 0.0, TRUE, goodrelax,
    2959 minresactivity, ismintight, isminsettoinfinity);
    2960 }
    2961 else
    2962 {
    2963 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
    2964 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, absval * minactbound, TRUE,
    2965 goodrelax, minresactivity, ismintight, isminsettoinfinity);
    2966 }
    2967 }
    2968
    2969 if( maxresactivity != NULL )
    2970 {
    2971 assert(ismaxsettoinfinity != NULL);
    2972 assert(ismaxtight != NULL);
    2973
    2974 /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
    2975 * and contribution of variable set to zero that has to be subtracted from finite part of activity
    2976 */
    2977 if( SCIPisInfinity(scip, -maxactbound) )
    2978 {
    2979 assert(consdata->glbmaxactivityneginf >= 1);
    2980
    2981 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf - 1,
    2982 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
    2983 maxresactivity, ismaxtight, ismaxsettoinfinity);
    2984 }
    2985 else if( SCIPisInfinity(scip, maxactbound) )
    2986 {
    2987 assert(consdata->glbmaxactivityposinf >= 1);
    2988
    2989 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf - 1, consdata->glbmaxactivityneginf,
    2990 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
    2991 maxresactivity, ismaxtight, ismaxsettoinfinity);
    2992 }
    2993 else if( SCIPisHugeValue(scip, absval * maxactbound) )
    2994 {
    2995 assert(consdata->glbmaxactivityposhuge >= 1);
    2996
    2997 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
    2998 consdata->glbmaxactivityposhuge - 1, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
    2999 maxresactivity, ismaxtight, ismaxsettoinfinity);
    3000 }
    3001 else if( SCIPisHugeValue(scip, -absval * maxactbound) )
    3002 {
    3003 assert(consdata->glbmaxactivityneghuge >= 1);
    3004
    3005 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
    3006 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge - 1, 0.0, TRUE, goodrelax,
    3007 maxresactivity, ismaxtight, ismaxsettoinfinity);
    3008 }
    3009 else
    3010 {
    3011 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
    3012 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, absval * maxactbound, TRUE,
    3013 goodrelax, maxresactivity, ismaxtight, ismaxsettoinfinity);
    3014 }
    3015 }
    3016}
    3017
    3018/** calculates the activity of the linear constraint for given solution */
    3019static
    3021 SCIP* scip, /**< SCIP data structure */
    3022 SCIP_CONSDATA* consdata, /**< linear constraint data */
    3023 SCIP_SOL* sol /**< solution to get activity for, NULL to current solution */
    3024 )
    3025{
    3026 SCIP_Real activity;
    3027
    3028 assert(scip != NULL);
    3029 assert(consdata != NULL);
    3030
    3031 if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
    3032 activity = consdataComputePseudoActivity(scip, consdata);
    3033 else
    3034 {
    3035 SCIP_Real solval;
    3036 int nposinf;
    3037 int nneginf;
    3038 SCIP_Bool negsign;
    3039 int v;
    3040
    3041 activity = 0.0;
    3042 nposinf = 0;
    3043 nneginf = 0;
    3044
    3045 for( v = 0; v < consdata->nvars; ++v )
    3046 {
    3047 solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
    3048
    3049 assert(!SCIPisZero(scip, consdata->vals[v]));
    3050 negsign = consdata->vals[v] < 0.0;
    3051
    3052 if( (SCIPisInfinity(scip, solval) && !negsign) || (SCIPisInfinity(scip, -solval) && negsign) )
    3053 ++nposinf;
    3054 else if( (SCIPisInfinity(scip, solval) && negsign) || (SCIPisInfinity(scip, -solval) && !negsign) )
    3055 ++nneginf;
    3056 else
    3057 activity += consdata->vals[v] * solval;
    3058 }
    3059 assert(nneginf >= 0 && nposinf >= 0);
    3060
    3061 SCIPdebugMsg(scip, "activity of linear constraint: %.15g, %d positive infinity values, %d negative infinity values \n", activity, nposinf, nneginf);
    3062
    3063 /* invalidate activity for contradicting contributions */
    3064 if( nposinf > 0 && nneginf > 0 )
    3065 activity = SCIP_INVALID;
    3066 else if( nneginf > 0 )
    3067 activity = -SCIPinfinity(scip);
    3068 else if( nposinf > 0 )
    3069 activity = SCIPinfinity(scip);
    3070
    3071 SCIPdebugMsg(scip, "corrected activity of linear constraint: %.15g\n", activity);
    3072 }
    3073
    3074 if( activity == SCIP_INVALID ) /*lint !e777*/
    3075 return activity;
    3076 else if( activity < 0 )
    3077 activity = MAX(activity, -SCIPinfinity(scip)); /*lint !e666*/
    3078 else
    3079 activity = MIN(activity, SCIPinfinity(scip)); /*lint !e666*/
    3080
    3081 return activity;
    3082}
    3083
    3084/** calculates the feasibility of the linear constraint for given solution */
    3085static
    3087 SCIP* scip, /**< SCIP data structure */
    3088 SCIP_CONSDATA* consdata, /**< linear constraint data */
    3089 SCIP_SOL* sol /**< solution to get feasibility for, NULL to current solution */
    3090 )
    3091{
    3092 SCIP_Real activity;
    3093
    3094 assert(scip != NULL);
    3095 assert(consdata != NULL);
    3096
    3097 activity = consdataGetActivity(scip, consdata, sol);
    3098
    3099 if( activity == SCIP_INVALID ) /*lint !e777*/
    3100 return -SCIPinfinity(scip);
    3101
    3102 return MIN(consdata->rhs - activity, activity - consdata->lhs);
    3103}
    3104
    3105/** updates bit signatures after adding a single coefficient */
    3106static
    3108 SCIP_CONSDATA* consdata, /**< linear constraint data */
    3109 int pos /**< position of coefficient to update signatures for */
    3110 )
    3111{
    3112 uint64_t varsignature;
    3113 SCIP_Real lb;
    3114 SCIP_Real ub;
    3115 SCIP_Real val;
    3116
    3117 assert(consdata != NULL);
    3118 assert(consdata->validsignature);
    3119
    3120 varsignature = SCIPhashSignature64(SCIPvarGetIndex(consdata->vars[pos]));
    3121 lb = SCIPvarGetLbGlobal(consdata->vars[pos]);
    3122 ub = SCIPvarGetUbGlobal(consdata->vars[pos]);
    3123 val = consdata->vals[pos];
    3124 if( (val > 0.0 && ub > 0.0) || (val < 0.0 && lb < 0.0) )
    3125 consdata->possignature |= varsignature;
    3126 if( (val > 0.0 && lb < 0.0) || (val < 0.0 && ub > 0.0) )
    3127 consdata->negsignature |= varsignature;
    3128}
    3129
    3130/** calculates the bit signatures of the given constraint data */
    3131static
    3133 SCIP_CONSDATA* consdata /**< linear constraint data */
    3134 )
    3135{
    3136 assert(consdata != NULL);
    3137
    3138 if( !consdata->validsignature )
    3139 {
    3140 int i;
    3141
    3142 consdata->validsignature = TRUE;
    3143 consdata->possignature = 0;
    3144 consdata->negsignature = 0;
    3145 for( i = 0; i < consdata->nvars; ++i )
    3146 consdataUpdateSignatures(consdata, i);
    3147 }
    3148}
    3149
    3150/** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
    3151static
    3153{ /*lint --e{715}*/
    3154 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
    3155 SCIP_VAR* var1;
    3156 SCIP_VAR* var2;
    3157
    3158 assert(consdata != NULL);
    3159 assert(0 <= ind1 && ind1 < consdata->nvars);
    3160 assert(0 <= ind2 && ind2 < consdata->nvars);
    3161
    3162 var1 = consdata->vars[ind1];
    3163 var2 = consdata->vars[ind2];
    3164
    3165 /* exactly one variable is binary */
    3166 if( SCIPvarIsBinary(var1) != SCIPvarIsBinary(var2) )
    3167 {
    3168 return (SCIPvarIsBinary(var1) ? -1 : +1);
    3169 }
    3170 /* both variables are binary */
    3171 else if( SCIPvarIsBinary(var1) )
    3172 {
    3173 return SCIPvarCompare(var1, var2);
    3174 }
    3175 else
    3176 {
    3179
    3180 if( vartype1 < vartype2 )
    3181 return -1;
    3182 else if( vartype1 > vartype2 )
    3183 return +1;
    3184 else
    3185 return SCIPvarCompare(var1, var2);
    3186 }
    3187}
    3188
    3189/** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
    3190static
    3191SCIP_DECL_SORTINDCOMP(consdataCompVarProp)
    3192{ /*lint --e{715}*/
    3193 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
    3194 SCIP_VAR* var1;
    3195 SCIP_VAR* var2;
    3196
    3197 assert(consdata != NULL);
    3198 assert(0 <= ind1 && ind1 < consdata->nvars);
    3199 assert(0 <= ind2 && ind2 < consdata->nvars);
    3200
    3201 var1 = consdata->vars[ind1];
    3202 var2 = consdata->vars[ind2];
    3203
    3204 /* exactly one variable is binary */
    3205 if( SCIPvarIsBinary(var1) != SCIPvarIsBinary(var2) )
    3206 {
    3207 return (SCIPvarIsBinary(var1) ? -1 : +1);
    3208 }
    3209 /* both variables are binary */
    3210 else if( SCIPvarIsBinary(var1) )
    3211 {
    3212 SCIP_Real abscoef1 = REALABS(consdata->vals[ind1]);
    3213 SCIP_Real abscoef2 = REALABS(consdata->vals[ind2]);
    3214
    3215 if( EPSGT(abscoef1, abscoef2, 1e-9) )
    3216 return -1;
    3217 else if( EPSGT(abscoef2, abscoef1, 1e-9) )
    3218 return +1;
    3219 else
    3220 return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
    3221 }
    3222 else
    3223 {
    3226
    3227 if( vartype1 < vartype2 )
    3228 {
    3229 return -1;
    3230 }
    3231 else if( vartype1 > vartype2 )
    3232 {
    3233 return +1;
    3234 }
    3235 else
    3236 {
    3237 /* both variables are continuous */
    3238 if( !SCIPvarIsIntegral(var1) )
    3239 {
    3240 assert(!SCIPvarIsIntegral(var2));
    3241 return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
    3242 }
    3243 else
    3244 {
    3245 SCIP_Real abscont1 = REALABS(consdata->vals[ind1] * (SCIPvarGetUbGlobal(var1) - SCIPvarGetLbGlobal(var1)));
    3246 SCIP_Real abscont2 = REALABS(consdata->vals[ind2] * (SCIPvarGetUbGlobal(var2) - SCIPvarGetLbGlobal(var2)));
    3247
    3248 if( EPSGT(abscont1, abscont2, 1e-9) )
    3249 return -1;
    3250 else if( EPSGT(abscont2, abscont1, 1e-9) )
    3251 return +1;
    3252 else
    3253 return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
    3254 }
    3255 }
    3256 }
    3257}
    3258
    3259/** permutes the constraint's variables according to a given permutation. */
    3260static
    3262 SCIP_CONSDATA* consdata, /**< the constraint data */
    3263 int* perm, /**< the target permutation */
    3264 int nvars /**< the number of variables */
    3265 )
    3266{ /*lint --e{715}*/
    3267 SCIP_VAR* varv;
    3268 SCIP_EVENTDATA* eventdatav;
    3269 SCIP_Real valv;
    3270 int v;
    3271 int i;
    3272 int nexti;
    3273
    3274 assert(perm != NULL);
    3275 assert(consdata != NULL);
    3276
    3277 /* permute the variables in the linear constraint according to the target permutation */
    3278 eventdatav = NULL;
    3279 for( v = 0; v < nvars; ++v )
    3280 {
    3281 if( perm[v] != v )
    3282 {
    3283 varv = consdata->vars[v];
    3284 valv = consdata->vals[v];
    3285 if( consdata->eventdata != NULL )
    3286 eventdatav = consdata->eventdata[v];
    3287 i = v;
    3288 do
    3289 {
    3290 assert(0 <= perm[i] && perm[i] < nvars);
    3291 assert(perm[i] != i);
    3292 consdata->vars[i] = consdata->vars[perm[i]];
    3293 consdata->vals[i] = consdata->vals[perm[i]];
    3294 if( consdata->eventdata != NULL )
    3295 {
    3296 consdata->eventdata[i] = consdata->eventdata[perm[i]];
    3297 consdata->eventdata[i]->varpos = i;
    3298 }
    3299 nexti = perm[i];
    3300 perm[i] = i;
    3301 i = nexti;
    3302 }
    3303 while( perm[i] != v );
    3304 consdata->vars[i] = varv;
    3305 consdata->vals[i] = valv;
    3306 if( consdata->eventdata != NULL )
    3307 {
    3308 consdata->eventdata[i] = eventdatav;
    3309 consdata->eventdata[i]->varpos = i;
    3310 }
    3311 perm[i] = i;
    3312 }
    3313 }
    3314#ifdef SCIP_DEBUG
    3315 /* check sorting */
    3316 for( v = 0; v < nvars; ++v )
    3317 {
    3318 assert(perm[v] == v);
    3319 assert(consdata->eventdata == NULL || consdata->eventdata[v]->varpos == v);
    3320 }
    3321#endif
    3322}
    3323
    3324/** sorts linear constraint's variables depending on the stage of the solving process:
    3325 * - during PRESOLVING
    3326 * sorts variables by binary, integer, implied integral, and continuous variables,
    3327 * and the variables of the same type by non-decreasing variable index
    3328 *
    3329 * - during SOLVING
    3330 * sorts variables of the remaining problem by binary, integer, implied integral, and continuous variables,
    3331 * and binary and integer variables by their global max activity delta (within each group),
    3332 * ties within a group are broken by problem index of the variable.
    3333 *
    3334 * This fastens the propagation time of the constraint handler.
    3335 */
    3336static
    3338 SCIP* scip, /**< SCIP data structure */
    3339 SCIP_CONSDATA* consdata /**< linear constraint data */
    3340 )
    3341{
    3342 assert(scip != NULL);
    3343 assert(consdata != NULL);
    3344
    3345 /* check if there are variables for sorting */
    3346 if( consdata->nvars <= 1 )
    3347 {
    3348 consdata->indexsorted = TRUE;
    3349 consdata->coefsorted = TRUE;
    3350 consdata->nbinvars = (consdata->nvars == 1 ? (int)SCIPvarIsBinary(consdata->vars[0]) : 0);
    3351 }
    3352 else if( (!consdata->indexsorted && SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE)
    3353 || (!consdata->coefsorted && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE) )
    3354 {
    3355 int* perm;
    3356 int v;
    3357
    3358 /* get temporary memory to store the sorted permutation */
    3359 SCIP_CALL( SCIPallocBufferArray(scip, &perm, consdata->nvars) );
    3360
    3361 /* call sorting method */
    3363 SCIPsort(perm, consdataCompVar, (void*)consdata, consdata->nvars);
    3364 else
    3365 SCIPsort(perm, consdataCompVarProp, (void*)consdata, consdata->nvars);
    3366
    3367 permSortConsdata(consdata, perm, consdata->nvars);
    3368
    3369 /* free temporary memory */
    3370 SCIPfreeBufferArray(scip, &perm);
    3371
    3373 {
    3374 consdata->indexsorted = FALSE;
    3375 consdata->coefsorted = TRUE;
    3376
    3377 /* count binary variables in the sorted vars array */
    3378 consdata->nbinvars = 0;
    3379 for( v = 0; v < consdata->nvars; ++v )
    3380 {
    3381 if( SCIPvarIsBinary(consdata->vars[v]) )
    3382 ++consdata->nbinvars;
    3383 else
    3384 break;
    3385 }
    3386 }
    3387 else
    3388 {
    3389 consdata->indexsorted = TRUE;
    3390 consdata->coefsorted = FALSE;
    3391 }
    3392 }
    3393
    3394 return SCIP_OKAY;
    3395}
    3396
    3397
    3398/*
    3399 * local linear constraint handler methods
    3400 */
    3401
    3402/** sets left hand side of linear constraint */
    3403static
    3405 SCIP* scip, /**< SCIP data structure */
    3406 SCIP_CONS* cons, /**< linear constraint */
    3407 SCIP_Real lhs /**< new left hand side */
    3408 )
    3409{
    3410 SCIP_CONSDATA* consdata;
    3411 SCIP_Bool locked;
    3412 int i;
    3413
    3414 assert(scip != NULL);
    3415 assert(cons != NULL);
    3416
    3417 /* adjust value to be not beyond infinity */
    3418 if( SCIPisInfinity(scip, -lhs) )
    3419 lhs = -SCIPinfinity(scip);
    3420 else if( SCIPisInfinity(scip, lhs) )
    3421 lhs = SCIPinfinity(scip);
    3422
    3423 consdata = SCIPconsGetData(cons);
    3424 assert(consdata != NULL);
    3425 assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
    3426
    3427 /* check whether the side is not changed */
    3428 if( SCIPisEQ(scip, consdata->lhs, lhs) )
    3429 return SCIP_OKAY;
    3430
    3431 assert(!SCIPisInfinity(scip, ABS(consdata->lhs)) || !SCIPisInfinity(scip, ABS(lhs)));
    3432
    3433 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
    3434 if( SCIPisEQ(scip, lhs, consdata->rhs) )
    3435 {
    3436 consdata->rhs = lhs;
    3437 assert(consdata->row == NULL);
    3438 }
    3439
    3440 locked = FALSE;
    3441 for( i = 0; i < NLOCKTYPES && !locked; i++ )
    3442 locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
    3443
    3444 /* if necessary, update the rounding locks of variables */
    3445 if( locked )
    3446 {
    3447 if( SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, -lhs) )
    3448 {
    3449 SCIP_VAR** vars;
    3450 SCIP_Real* vals;
    3451 int v;
    3452
    3453 /* the left hand side switched from -infinity to a non-infinite value -> install rounding locks */
    3454 vars = consdata->vars;
    3455 vals = consdata->vals;
    3456
    3457 for( v = 0; v < consdata->nvars; ++v )
    3458 {
    3459 assert(vars[v] != NULL);
    3460 assert(!SCIPisZero(scip, vals[v]));
    3461
    3462 if( SCIPisPositive(scip, vals[v]) )
    3463 {
    3464 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
    3465 }
    3466 else
    3467 {
    3468 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
    3469 }
    3470 }
    3471 }
    3472 else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -lhs) )
    3473 {
    3474 SCIP_VAR** vars;
    3475 SCIP_Real* vals;
    3476 int v;
    3477
    3478 /* the left hand side switched from a non-infinite value to -infinity -> remove rounding locks */
    3479 vars = consdata->vars;
    3480 vals = consdata->vals;
    3481
    3482 for( v = 0; v < consdata->nvars; ++v )
    3483 {
    3484 assert(vars[v] != NULL);
    3485 assert(!SCIPisZero(scip, vals[v]));
    3486
    3487 if( SCIPisPositive(scip, vals[v]) )
    3488 {
    3489 SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
    3490 }
    3491 else
    3492 {
    3493 SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
    3494 }
    3495 }
    3496 }
    3497 }
    3498
    3499 /* check whether the left hand side is increased, if and only if that's the case we maybe can propagate, tighten and add more cliques */
    3500 if( !SCIPisInfinity(scip, ABS(lhs)) && SCIPisGT(scip, lhs, consdata->lhs) )
    3501 {
    3502 consdata->boundstightened = 0;
    3503 consdata->presolved = FALSE;
    3504 consdata->cliquesadded = FALSE;
    3505 consdata->implsadded = FALSE;
    3506
    3507 /* mark the constraint for propagation */
    3508 if( SCIPconsIsTransformed(cons) )
    3509 {
    3511 }
    3512 }
    3513
    3514 /* set new left hand side and update constraint data */
    3515 consdata->lhs = lhs;
    3516 consdata->changed = TRUE;
    3517 consdata->normalized = FALSE;
    3518 consdata->upgradetried = FALSE;
    3519 consdata->rangedrowpropagated = 0;
    3520
    3521 /* update the lhs of the LP row */
    3522 if( consdata->row != NULL )
    3523 {
    3524 SCIP_CALL( SCIPchgRowLhs(scip, consdata->row, lhs) );
    3525 }
    3526
    3527 return SCIP_OKAY;
    3528}
    3529
    3530/** sets right hand side of linear constraint */
    3531static
    3533 SCIP* scip, /**< SCIP data structure */
    3534 SCIP_CONS* cons, /**< linear constraint */
    3535 SCIP_Real rhs /**< new right hand side */
    3536 )
    3537{
    3538 SCIP_CONSDATA* consdata;
    3539 SCIP_Bool locked;
    3540 int i;
    3541
    3542 assert(scip != NULL);
    3543 assert(cons != NULL);
    3544
    3545 /* adjust value to be not beyond infinity */
    3546 if( SCIPisInfinity(scip, rhs) )
    3547 rhs = SCIPinfinity(scip);
    3548 else if( SCIPisInfinity(scip, -rhs) )
    3549 rhs = -SCIPinfinity(scip);
    3550
    3551 consdata = SCIPconsGetData(cons);
    3552 assert(consdata != NULL);
    3553 assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
    3554
    3555 /* check whether the side is not changed */
    3556 if( SCIPisEQ(scip, consdata->rhs, rhs) )
    3557 return SCIP_OKAY;
    3558
    3559 assert(!SCIPisInfinity(scip, ABS(consdata->rhs)) || !SCIPisInfinity(scip, ABS(rhs)));
    3560
    3561 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
    3562 if( SCIPisEQ(scip, rhs, consdata->lhs) )
    3563 {
    3564 consdata->lhs = rhs;
    3565 assert(consdata->row == NULL);
    3566 }
    3567
    3568 locked = FALSE;
    3569 for( i = 0; i < NLOCKTYPES && !locked; i++ )
    3570 locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
    3571
    3572 /* if necessary, update the rounding locks of variables */
    3573 if( locked )
    3574 {
    3575 assert(SCIPconsIsTransformed(cons));
    3576
    3577 if( SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, rhs) )
    3578 {
    3579 SCIP_VAR** vars;
    3580 SCIP_Real* vals;
    3581 int v;
    3582
    3583 /* the right hand side switched from infinity to a non-infinite value -> install rounding locks */
    3584 vars = consdata->vars;
    3585 vals = consdata->vals;
    3586
    3587 for( v = 0; v < consdata->nvars; ++v )
    3588 {
    3589 assert(vars[v] != NULL);
    3590 assert(!SCIPisZero(scip, vals[v]));
    3591
    3592 if( SCIPisPositive(scip, vals[v]) )
    3593 {
    3594 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
    3595 }
    3596 else
    3597 {
    3598 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
    3599 }
    3600 }
    3601 }
    3602 else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, rhs) )
    3603 {
    3604 SCIP_VAR** vars;
    3605 SCIP_Real* vals;
    3606 int v;
    3607
    3608 /* the right hand side switched from a non-infinite value to infinity -> remove rounding locks */
    3609 vars = consdata->vars;
    3610 vals = consdata->vals;
    3611
    3612 for( v = 0; v < consdata->nvars; ++v )
    3613 {
    3614 assert(vars[v] != NULL);
    3615 assert(!SCIPisZero(scip, vals[v]));
    3616
    3617 if( SCIPisPositive(scip, vals[v]) )
    3618 {
    3619 SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
    3620 }
    3621 else
    3622 {
    3623 SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
    3624 }
    3625 }
    3626 }
    3627 }
    3628
    3629 /* check whether the right hand side is decreased, if and only if that's the case we maybe can propagate, tighten and add more cliques */
    3630 if( !SCIPisInfinity(scip, ABS(rhs)) && SCIPisLT(scip, rhs, consdata->rhs) )
    3631 {
    3632 consdata->boundstightened = 0;
    3633 consdata->presolved = FALSE;
    3634 consdata->cliquesadded = FALSE;
    3635 consdata->implsadded = FALSE;
    3636
    3637 /* mark the constraint for propagation */
    3638 if( SCIPconsIsTransformed(cons) )
    3639 {
    3641 }
    3642 }
    3643
    3644 /* set new right hand side and update constraint data */
    3645 consdata->rhs = rhs;
    3646 consdata->changed = TRUE;
    3647 consdata->normalized = FALSE;
    3648 consdata->upgradetried = FALSE;
    3649 consdata->rangedrowpropagated = 0;
    3650
    3651 /* update the rhs of the LP row */
    3652 if( consdata->row != NULL )
    3653 {
    3654 SCIP_CALL( SCIPchgRowRhs(scip, consdata->row, rhs) );
    3655 }
    3656
    3657 return SCIP_OKAY;
    3658}
    3659
    3660/** adds coefficient in linear constraint */
    3661static
    3663 SCIP* scip, /**< SCIP data structure */
    3664 SCIP_CONS* cons, /**< linear constraint */
    3665 SCIP_VAR* var, /**< variable of constraint entry */
    3666 SCIP_Real val /**< coefficient of constraint entry */
    3667 )
    3668{
    3669 SCIP_CONSDATA* consdata;
    3670 SCIP_Bool transformed;
    3671
    3672 assert(scip != NULL);
    3673 assert(cons != NULL);
    3674 assert(var != NULL);
    3675
    3676 /* relaxation-only variables must not be used in checked or enforced constraints */
    3677 assert(!SCIPvarIsRelaxationOnly(var) || (!SCIPconsIsChecked(cons) && !SCIPconsIsEnforced(cons)));
    3678 consdata = SCIPconsGetData(cons);
    3679 assert(consdata != NULL);
    3680
    3681 /* are we in the transformed problem? */
    3682 transformed = SCIPconsIsTransformed(cons);
    3683
    3684 /* always use transformed variables in transformed constraints */
    3685 if( transformed )
    3686 {
    3687 SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
    3688 }
    3689 assert(var != NULL);
    3690 assert(transformed == SCIPvarIsTransformed(var));
    3691
    3692 SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
    3693 consdata->vars[consdata->nvars] = var;
    3694 consdata->vals[consdata->nvars] = val;
    3695 consdata->nvars++;
    3696
    3697 /* capture variable */
    3698 SCIP_CALL( SCIPcaptureVar(scip, var) );
    3699
    3700 /* if we are in transformed problem, the variable needs an additional event data */
    3701 if( transformed )
    3702 {
    3703 if( consdata->eventdata != NULL )
    3704 {
    3705 SCIP_CONSHDLR* conshdlr;
    3706 SCIP_CONSHDLRDATA* conshdlrdata;
    3707
    3708 /* check for event handler */
    3709 conshdlr = SCIPconsGetHdlr(cons);
    3710 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    3711 assert(conshdlrdata != NULL);
    3712 assert(conshdlrdata->eventhdlr != NULL);
    3713
    3714 /* initialize eventdata array */
    3715 consdata->eventdata[consdata->nvars-1] = NULL;
    3716
    3717 /* catch bound change events of variable */
    3718 SCIP_CALL( consCatchEvent(scip, cons, conshdlrdata->eventhdlr, consdata->nvars-1) );
    3719 }
    3720
    3721 /* update minimum and maximum activities */
    3722 if( !SCIPisZero(scip, val) )
    3723 consdataUpdateAddCoef(scip, consdata, var, val, FALSE);
    3724 }
    3725
    3726 /* install rounding locks for new variable with non-zero coefficient */
    3727 if( !SCIPisZero(scip, val) )
    3728 {
    3729 SCIP_CALL( lockRounding(scip, cons, var, val) );
    3730 }
    3731
    3732 /* mark the constraint for propagation */
    3733 if( transformed )
    3734 {
    3736 }
    3737
    3738 consdata->boundstightened = 0;
    3739 consdata->presolved = FALSE;
    3740 consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(var);
    3741
    3742 if( consdata->validsignature )
    3743 consdataUpdateSignatures(consdata, consdata->nvars-1);
    3744
    3745 consdata->changed = TRUE;
    3746 consdata->normalized = FALSE;
    3747 consdata->upgradetried = FALSE;
    3748 consdata->cliquesadded = FALSE;
    3749 consdata->implsadded = FALSE;
    3750 consdata->rangedrowpropagated = 0;
    3751 consdata->merged = FALSE;
    3752
    3753 if( consdata->nvars == 1 )
    3754 {
    3755 consdata->indexsorted = TRUE;
    3756 consdata->coefsorted = TRUE;
    3757 }
    3758 else
    3759 {
    3761 {
    3762 consdata->indexsorted = consdata->indexsorted && (consdataCompVar((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0);
    3763 consdata->coefsorted = FALSE;
    3764 }
    3765 else
    3766 {
    3767 consdata->indexsorted = FALSE;
    3768 consdata->coefsorted = consdata->coefsorted && (consdataCompVarProp((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0);
    3769 }
    3770 }
    3771
    3772 /* update hascontvar and hasnonbinvar flags */
    3773 if( consdata->hasnonbinvalid && !consdata->hascontvar )
    3774 {
    3775 if( !SCIPvarIsBinary(var) )
    3776 {
    3777 consdata->hasnonbinvar = TRUE;
    3778
    3779 if( !SCIPvarIsIntegral(var) )
    3780 consdata->hascontvar = TRUE;
    3781 }
    3782 }
    3783
    3784 /* add the new coefficient to the LP row */
    3785 if( consdata->row != NULL )
    3786 {
    3787 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, val) );
    3788 }
    3789
    3790 return SCIP_OKAY;
    3791}
    3792
    3793/** deletes coefficient at given position from linear constraint data */
    3794static
    3796 SCIP* scip, /**< SCIP data structure */
    3797 SCIP_CONS* cons, /**< linear constraint */
    3798 int pos /**< position of coefficient to delete */
    3799 )
    3800{
    3801 SCIP_CONSDATA* consdata;
    3802 SCIP_VAR* var;
    3803 SCIP_Real val;
    3804
    3805 assert(scip != NULL);
    3806 assert(cons != NULL);
    3807
    3808 consdata = SCIPconsGetData(cons);
    3809 assert(consdata != NULL);
    3810 assert(0 <= pos && pos < consdata->nvars);
    3811
    3812 var = consdata->vars[pos];
    3813 val = consdata->vals[pos];
    3814 assert(var != NULL);
    3815
    3816 /* remove rounding locks for deleted variable with non-zero coefficient */
    3817 if( !SCIPisZero(scip, val) )
    3818 {
    3819 SCIP_CALL( unlockRounding(scip, cons, var, val) );
    3820 }
    3821
    3822 /* if we are in transformed problem, delete the event data of the variable */
    3823 if( SCIPconsIsTransformed(cons) )
    3824 {
    3825 SCIP_CONSHDLR* conshdlr;
    3826 SCIP_CONSHDLRDATA* conshdlrdata;
    3827
    3828 /* check for event handler */
    3829 conshdlr = SCIPconsGetHdlr(cons);
    3830 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    3831 assert(conshdlrdata != NULL);
    3832 assert(conshdlrdata->eventhdlr != NULL);
    3833
    3834 /* drop bound change events of variable */
    3835 if( consdata->eventdata != NULL )
    3836 {
    3837 SCIP_CALL( consDropEvent(scip, cons, conshdlrdata->eventhdlr, pos) );
    3838 assert(consdata->eventdata[pos] == NULL);
    3839 }
    3840 }
    3841
    3842 /* move the last variable to the free slot */
    3843 if( pos != consdata->nvars - 1 )
    3844 {
    3845 consdata->vars[pos] = consdata->vars[consdata->nvars-1];
    3846 consdata->vals[pos] = consdata->vals[consdata->nvars-1];
    3847
    3848 if( consdata->eventdata != NULL )
    3849 {
    3850 consdata->eventdata[pos] = consdata->eventdata[consdata->nvars-1];
    3851 assert(consdata->eventdata[pos] != NULL);
    3852 consdata->eventdata[pos]->varpos = pos;
    3853 }
    3854
    3855 consdata->indexsorted = consdata->indexsorted && (pos + 2 >= consdata->nvars);
    3856 consdata->coefsorted = consdata->coefsorted && (pos + 2 >= consdata->nvars);
    3857 }
    3858 consdata->nvars--;
    3859
    3860 /* if at most one variable is left, the activities should be recalculated (to correspond exactly to the bounds
    3861 * of the remaining variable, or give exactly 0.0)
    3862 */
    3863 if( consdata->nvars <= 1 )
    3865 else
    3866 {
    3867 /* if we are in transformed problem, update minimum and maximum activities */
    3868 if( SCIPconsIsTransformed(cons) && !SCIPisZero(scip, val) )
    3869 consdataUpdateDelCoef(scip, consdata, var, val, TRUE);
    3870 }
    3871
    3872 /* mark the constraint for propagation */
    3873 if( SCIPconsIsTransformed(cons) )
    3874 {
    3876 }
    3877
    3878 consdata->boundstightened = 0;
    3879 consdata->presolved = FALSE;
    3880 consdata->validsignature = FALSE;
    3881 consdata->changed = TRUE;
    3882 consdata->normalized = FALSE;
    3883 consdata->upgradetried = FALSE;
    3884 consdata->cliquesadded = FALSE;
    3885 consdata->implsadded = FALSE;
    3886 consdata->rangedrowpropagated = 0;
    3887
    3888 /* check if hasnonbinvar flag might be incorrect now */
    3889 if( consdata->hasnonbinvar && !SCIPvarIsBinary(var) )
    3890 {
    3891 consdata->hasnonbinvalid = FALSE;
    3892 }
    3893
    3894 /* delete coefficient from the LP row */
    3895 if( consdata->row != NULL )
    3896 {
    3897 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, -val) );
    3898 }
    3899
    3900 /* release variable */
    3901 SCIP_CALL( SCIPreleaseVar(scip, &var) );
    3902
    3903 return SCIP_OKAY;
    3904}
    3905
    3906/** changes coefficient value at given position of linear constraint data */
    3907static
    3909 SCIP* scip, /**< SCIP data structure */
    3910 SCIP_CONS* cons, /**< linear constraint */
    3911 int pos, /**< position of coefficient to delete */
    3912 SCIP_Real newval /**< new value of coefficient */
    3913 )
    3914{
    3915 SCIP_CONSDATA* consdata;
    3916 SCIP_VAR* var;
    3917 SCIP_Real val;
    3918 SCIP_Bool locked;
    3919 int i;
    3920
    3921 assert(scip != NULL);
    3922 assert(cons != NULL);
    3923 consdata = SCIPconsGetData(cons);
    3924 assert(consdata != NULL);
    3925 assert(0 <= pos && pos < consdata->nvars);
    3926 var = consdata->vars[pos];
    3927 assert(var != NULL);
    3928 assert(SCIPvarIsTransformed(var) == SCIPconsIsTransformed(cons));
    3929 val = consdata->vals[pos];
    3930 assert(!SCIPisZero(scip, val) || !SCIPisZero(scip, newval));
    3931
    3932 locked = FALSE;
    3933 for( i = 0; i < NLOCKTYPES && !locked; i++ )
    3934 locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
    3935
    3936 /* if necessary, update the rounding locks of the variable */
    3937 if( locked && ( !SCIPisNegative(scip, val) || !SCIPisNegative(scip, newval) )
    3938 && ( !SCIPisPositive(scip, val) || !SCIPisPositive(scip, newval) ) )
    3939 {
    3940 assert(SCIPconsIsTransformed(cons));
    3941
    3942 /* remove rounding locks for variable with old non-zero coefficient */
    3943 if( !SCIPisZero(scip, val) )
    3944 {
    3945 SCIP_CALL( unlockRounding(scip, cons, var, val) );
    3946 }
    3947
    3948 /* install rounding locks for variable with new non-zero coefficient */
    3949 if( !SCIPisZero(scip, newval) )
    3950 {
    3951 SCIP_CALL( lockRounding(scip, cons, var, newval) );
    3952 }
    3953 }
    3954
    3955 /* change the value */
    3956 consdata->vals[pos] = newval;
    3957
    3958 if( consdata->coefsorted )
    3959 {
    3960 if( pos > 0 )
    3961 consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos - 1, pos) <= 0);
    3962 if( consdata->coefsorted && pos < consdata->nvars - 1 )
    3963 consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos, pos + 1) <= 0);
    3964 }
    3965
    3966 /* update minimum and maximum activities */
    3967 if( SCIPconsIsTransformed(cons) )
    3968 {
    3969 if( SCIPisZero(scip, val) )
    3970 consdataUpdateAddCoef(scip, consdata, var, newval, TRUE);
    3971 else if( SCIPisZero(scip, newval) )
    3972 consdataUpdateDelCoef(scip, consdata, var, val, TRUE);
    3973 else
    3974 consdataUpdateChgCoef(scip, consdata, var, val, newval, TRUE);
    3975 }
    3976
    3977 /* mark the constraint for propagation */
    3978 if( SCIPconsIsTransformed(cons) )
    3979 {
    3981 }
    3982
    3983 consdata->boundstightened = 0;
    3984 consdata->presolved = FALSE;
    3985 consdata->validsignature = consdata->validsignature && (newval * val > 0.0);
    3986 consdata->changed = TRUE;
    3987 consdata->normalized = FALSE;
    3988 consdata->upgradetried = FALSE;
    3989 consdata->cliquesadded = FALSE;
    3990 consdata->implsadded = FALSE;
    3991 consdata->rangedrowpropagated = 0;
    3992
    3993 return SCIP_OKAY;
    3994}
    3995
    3996/** scales a linear constraint with a constant scalar */
    3997static
    3999 SCIP* scip, /**< SCIP data structure */
    4000 SCIP_CONS* cons, /**< linear constraint to scale */
    4001 SCIP_Real scalar /**< value to scale constraint with */
    4002 )
    4003{
    4004 SCIP_CONSDATA* consdata;
    4005 SCIP_Real newval;
    4006 SCIP_Real absscalar;
    4007 int i;
    4008
    4009 assert(scip != NULL);
    4010 assert(cons != NULL);
    4011
    4012 consdata = SCIPconsGetData(cons);
    4013 assert(consdata != NULL);
    4014 assert(consdata->row == NULL);
    4015 assert(scalar != 1.0);
    4016
    4017 if( (!SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -consdata->lhs * scalar))
    4018 || (!SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, consdata->rhs * scalar)) )
    4019 {
    4020 SCIPwarningMessage(scip, "skipped scaling for linear constraint <%s> to avoid numerical troubles (scalar: %.15g)\n",
    4021 SCIPconsGetName(cons), scalar);
    4022
    4023 return SCIP_OKAY;
    4024 }
    4025
    4026 /* scale the coefficients */
    4027 for( i = consdata->nvars - 1; i >= 0; --i )
    4028 {
    4029 newval = scalar * consdata->vals[i];
    4030
    4031 /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
    4032 * flooring down our new value
    4033 */
    4034 if( SCIPisScalingIntegral(scip, consdata->vals[i], scalar) )
    4035 newval = SCIPfeasFloor(scip, newval + 0.5);
    4036
    4037 if( SCIPisZero(scip, newval) )
    4038 {
    4039 SCIPwarningMessage(scip, "coefficient %.15g of variable <%s> in linear constraint <%s> scaled to zero (scalar: %.15g)\n",
    4040 consdata->vals[i], SCIPvarGetName(consdata->vars[i]), SCIPconsGetName(cons), scalar);
    4041 SCIP_CALL( delCoefPos(scip, cons, i) );
    4042 }
    4043 else
    4044 consdata->vals[i] = newval;
    4045 }
    4046
    4047 /* scale the sides */
    4048 if( scalar < 0.0 )
    4049 {
    4050 SCIP_Real lhs;
    4051
    4052 lhs = consdata->lhs;
    4053 consdata->lhs = -consdata->rhs;
    4054 consdata->rhs = -lhs;
    4055 }
    4056 absscalar = REALABS(scalar);
    4057 if( !SCIPisInfinity(scip, -consdata->lhs) )
    4058 {
    4059 newval = absscalar * consdata->lhs;
    4060
    4061 /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
    4062 * flooring down our new value
    4063 */
    4064 if( SCIPisScalingIntegral(scip, consdata->lhs, absscalar) )
    4065 consdata->lhs = SCIPfeasFloor(scip, newval + 0.5);
    4066 else
    4067 consdata->lhs = newval;
    4068 }
    4069 if( !SCIPisInfinity(scip, consdata->rhs) )
    4070 {
    4071 newval = absscalar * consdata->rhs;
    4072
    4073 /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasCeil, we subtract 0.5 before ceiling up
    4074 * our new value
    4075 */
    4076 if( SCIPisScalingIntegral(scip, consdata->rhs, absscalar) )
    4077 consdata->rhs = SCIPfeasCeil(scip, newval - 0.5);
    4078 else
    4079 consdata->rhs = newval;
    4080 }
    4081
    4083 consdata->cliquesadded = FALSE;
    4084 consdata->implsadded = FALSE;
    4085
    4086 return SCIP_OKAY;
    4087}
    4088
    4089/** perform deletion of variables in all constraints of the constraint handler */
    4090static
    4092 SCIP* scip, /**< SCIP data structure */
    4093 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
    4094 SCIP_CONS** conss, /**< array of constraints */
    4095 int nconss /**< number of constraints */
    4096 )
    4097{
    4098 SCIP_CONSDATA* consdata;
    4099 int i;
    4100 int v;
    4101
    4102 assert(scip != NULL);
    4103 assert(conshdlr != NULL);
    4104 assert(conss != NULL);
    4105 assert(nconss >= 0);
    4106
    4108
    4109 /* iterate over all constraints */
    4110 for( i = 0; i < nconss; i++ )
    4111 {
    4112 consdata = SCIPconsGetData(conss[i]);
    4113
    4114 /* constraint is marked, that some of its variables were deleted */
    4115 if( consdata->varsdeleted )
    4116 {
    4117 /* iterate over all variables of the constraint and delete them from the constraint */
    4118 for( v = consdata->nvars - 1; v >= 0; --v )
    4119 {
    4120 if( SCIPvarIsDeleted(consdata->vars[v]) )
    4121 {
    4122 SCIP_CALL( delCoefPos(scip, conss[i], v) );
    4123 }
    4124 }
    4125 consdata->varsdeleted = FALSE;
    4126 }
    4127 }
    4128
    4129 return SCIP_OKAY;
    4130}
    4131
    4132
    4133/** normalizes a linear constraint with the following rules:
    4134 * - if all coefficients have them same absolute value, change them to (-)1.0
    4135 * - multiplication with +1 or -1:
    4136 * Apply the following rules in the given order, until the sign of the factor is determined. Later rules only apply,
    4137 * if the current rule doesn't determine the sign):
    4138 * 1. the right hand side must not be negative
    4139 * 2. the right hand side must not be infinite
    4140 * 3. the absolute value of the right hand side must be greater than that of the left hand side
    4141 * 4. the number of positive coefficients must not be smaller than the number of negative coefficients
    4142 * 5. multiply with +1
    4143 * - rationals to integrals
    4144 * Try to identify a rational representation of the fractional coefficients, and multiply all coefficients
    4145 * by the smallest common multiple of all denominators to get integral coefficients.
    4146 * Forbid large denominators due to numerical stability.
    4147 * - division by greatest common divisor
    4148 * If all coefficients are integral, divide them by the greatest common divisor.
    4149 */
    4150static
    4152 SCIP* scip, /**< SCIP data structure */
    4153 SCIP_CONS* cons, /**< linear constraint to normalize */
    4154 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
    4155 )
    4156{
    4157 SCIP_CONSDATA* consdata;
    4158 SCIP_Real* vals;
    4159 SCIP_Longint scm;
    4162 SCIP_Longint gcd;
    4163 SCIP_Longint maxmult;
    4164 SCIP_Real epsilon;
    4165 SCIP_Real feastol;
    4166 SCIP_Real maxabsval;
    4167 SCIP_Real minabsval;
    4168 SCIP_Bool success;
    4169 SCIP_Bool onlyintegral;
    4170 int nvars;
    4171 int mult;
    4172 int nposcoeffs;
    4173 int nnegcoeffs;
    4174 int i;
    4175
    4176 assert(scip != NULL);
    4177 assert(cons != NULL);
    4178 assert(infeasible != NULL);
    4179
    4180 *infeasible = FALSE;
    4181
    4182 /* we must not change a modifiable constraint in any way */
    4183 if( SCIPconsIsModifiable(cons) )
    4184 return SCIP_OKAY;
    4185
    4186 /* get constraint data */
    4187 consdata = SCIPconsGetData(cons);
    4188 assert(consdata != NULL);
    4189
    4190 /* check, if the constraint is already normalized */
    4191 if( consdata->normalized )
    4192 return SCIP_OKAY;
    4193
    4194 /* get coefficient arrays */
    4195 vals = consdata->vals;
    4196 nvars = consdata->nvars;
    4197 assert(nvars == 0 || vals != NULL);
    4198
    4199 if( nvars == 0 )
    4200 {
    4201 consdata->normalized = TRUE;
    4202 return SCIP_OKAY;
    4203 }
    4204
    4205 assert(vals != NULL);
    4206
    4207 /* get maximum and minimum absolute coefficient */
    4208 maxabsval = consdataGetMaxAbsval(consdata);
    4209 minabsval = consdataGetMinAbsval(consdata);
    4210
    4211 /* return if scaling by maxval will eliminate coefficients */
    4212 if( SCIPisZero(scip, minabsval/maxabsval) )
    4213 return SCIP_OKAY;
    4214
    4215 /* return if scaling by maxval will eliminate or generate non-zero sides */
    4216 if( !SCIPisInfinity(scip, consdata->lhs) && SCIPisFeasZero(scip, consdata->lhs) != SCIPisFeasZero(scip, consdata->lhs/maxabsval) )
    4217 return SCIP_OKAY;
    4218 if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisFeasZero(scip, consdata->rhs) != SCIPisFeasZero(scip, consdata->rhs/maxabsval) )
    4219 return SCIP_OKAY;
    4220
    4221 /* check if not all absolute coefficients are near 1.0 but scaling could do */
    4222 if( SCIPisLT(scip, minabsval, 1.0) != SCIPisGT(scip, maxabsval, 1.0) )
    4223 {
    4224 SCIP_Real scalar;
    4225
    4226 /* calculate scale of the average minimum and maximum absolute coefficient to 1.0 */
    4227 scalar = 2.0 / (minabsval + maxabsval);
    4228
    4229 /* check if all scaled absolute coefficients are near 1.0
    4230 * we can relax EQ(x,1.0) to LE(x,1.0), as LT(x,1.0) is not possible
    4231 */
    4232 if( SCIPisLE(scip, scalar * maxabsval, 1.0) )
    4233 {
    4234 SCIPdebugMsg(scip, "divide linear constraint with %g, because all coefficients are in absolute value the same\n", maxabsval);
    4236 SCIP_CALL( scaleCons(scip, cons, scalar) );
    4237
    4238 /* get new consdata information, because scaleCons() might have deleted variables */
    4239 vals = consdata->vals;
    4240 nvars = consdata->nvars;
    4241
    4242 assert(nvars == 0 || vals != NULL);
    4243 }
    4244 }
    4245
    4246 /* nvars might have changed */
    4247 if( nvars == 0 )
    4248 {
    4249 consdata->normalized = TRUE;
    4250 return SCIP_OKAY;
    4251 }
    4252
    4253 assert(vals != NULL);
    4254
    4255 /* calculate the maximal multiplier for common divisor calculation:
    4256 * |p/q - val| < epsilon and q < feastol/epsilon => |p - q*val| < feastol
    4257 * which means, a value of feastol/epsilon should be used as maximal multiplier;
    4258 * additionally, we don't want to scale the constraint if this would lead to too
    4259 * large coefficients
    4260 */
    4261 epsilon = SCIPepsilon(scip) * 0.9; /* slightly decrease epsilon to be safe in rational conversion below */
    4262 feastol = SCIPfeastol(scip);
    4263 maxmult = (SCIP_Longint)(feastol/epsilon + feastol);
    4264
    4265 if( !consdata->hasnonbinvalid )
    4266 consdataCheckNonbinvar(consdata);
    4267
    4268 /* get maximum absolute coefficient */
    4269 maxabsval = consdataGetMaxAbsval(consdata);
    4270
    4271 /* if all variables are of integral type we will allow a greater multiplier */
    4272 if( !consdata->hascontvar )
    4273 maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEFINTEGER / MAX(maxabsval, 1.0))); /*lint !e835*/
    4274 else
    4275 maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEF / MAX(maxabsval, 1.0))); /*lint !e835*/
    4276
    4277 /*
    4278 * multiplication with +1 or -1
    4279 */
    4280 mult = 0;
    4281
    4282 /* 1. the right hand side must not be negative */
    4283 if( SCIPisPositive(scip, consdata->lhs) )
    4284 mult = +1;
    4285 else if( SCIPisNegative(scip, consdata->rhs) )
    4286 mult = -1;
    4287
    4288 if( mult == 0 )
    4289 {
    4290 /* 2. the right hand side must not be infinite */
    4291 if( SCIPisInfinity(scip, -consdata->lhs) )
    4292 mult = +1;
    4293 else if( SCIPisInfinity(scip, consdata->rhs) )
    4294 mult = -1;
    4295 }
    4296
    4297 if( mult == 0 )
    4298 {
    4299 /* 3. the absolute value of the right hand side must be greater than that of the left hand side */
    4300 if( SCIPisGT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
    4301 mult = +1;
    4302 else if( SCIPisLT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
    4303 mult = -1;
    4304 }
    4305
    4306 if( mult == 0 )
    4307 {
    4308 /* 4. the number of positive coefficients must not be smaller than the number of negative coefficients */
    4309 nposcoeffs = 0;
    4310 nnegcoeffs = 0;
    4311 for( i = 0; i < nvars; ++i )
    4312 {
    4313 if( vals[i] > 0.0 )
    4314 nposcoeffs++;
    4315 else
    4316 nnegcoeffs++;
    4317 }
    4318 if( nposcoeffs > nnegcoeffs )
    4319 mult = +1;
    4320 else if( nposcoeffs < nnegcoeffs )
    4321 mult = -1;
    4322 }
    4323
    4324 if( mult == 0 )
    4325 {
    4326 /* 5. multiply with +1 */
    4327 mult = +1;
    4328 }
    4329
    4330 assert(mult == +1 || mult == -1);
    4331 if( mult == -1 )
    4332 {
    4333 /* scale the constraint with -1 */
    4334 SCIPdebugMsg(scip, "multiply linear constraint with -1.0\n");
    4336 SCIP_CALL( scaleCons(scip, cons, -1.0) );
    4337
    4338 /* scalecons() can delete variables, but scaling with -1 should not do that */
    4339 assert(nvars == consdata->nvars);
    4340 }
    4341
    4342 /*
    4343 * rationals to integrals
    4344 *
    4345 * @todo try scaling only on behalf of non-continuous variables
    4346 */
    4347 success = TRUE;
    4348 scm = 1;
    4349 for( i = 0; i < nvars && success && scm <= maxmult; ++i )
    4350 {
    4351 if( !SCIPisIntegral(scip, vals[i]) )
    4352 {
    4353 /* epsilon has been slightly decreased above - to be on the safe side */
    4354 success = SCIPrealToRational(vals[i], -epsilon, epsilon , maxmult, &numerator, &denominator);
    4355 if( success )
    4356 scm = SCIPcalcSmaComMul(scm, denominator);
    4357 }
    4358 }
    4359 assert(scm >= 1);
    4360
    4361 /* it might be that we have really big coefficients, but all are integral, in that case we want to divide them by
    4362 * their greatest common divisor
    4363 */
    4364 onlyintegral = TRUE;
    4365 if( scm == 1 )
    4366 {
    4367 for( i = nvars - 1; i >= 0; --i )
    4368 {
    4369 if( !SCIPisIntegral(scip, vals[i]) )
    4370 {
    4371 onlyintegral = FALSE;
    4372 break;
    4373 }
    4374 }
    4375 }
    4376
    4377 success = success && (scm <= maxmult || (scm == 1 && onlyintegral));
    4378 if( success && scm != 1 )
    4379 {
    4380 /* scale the constraint with the smallest common multiple of all denominators */
    4381 SCIPdebugMsg(scip, "scale linear constraint with %" SCIP_LONGINT_FORMAT " to make coefficients integral\n", scm);
    4383 SCIP_CALL( scaleCons(scip, cons, (SCIP_Real)scm) );
    4384
    4385 if( consdata->validmaxabsval )
    4386 {
    4387 consdata->maxabsval *= REALABS((SCIP_Real)scm);
    4388 if( !SCIPisIntegral(scip, consdata->maxabsval) )
    4389 {
    4390 consdata->validmaxabsval = FALSE;
    4391 consdata->maxabsval = SCIP_INVALID;
    4392 consdataCalcMaxAbsval(consdata);
    4393 }
    4394 }
    4395
    4396 if( consdata->validminabsval )
    4397 {
    4398 consdata->minabsval *= REALABS((SCIP_Real)scm);
    4399 if( !SCIPisIntegral(scip, consdata->minabsval) )
    4400 {
    4401 consdata->validminabsval = FALSE;
    4402 consdata->minabsval = SCIP_INVALID;
    4403 consdataCalcMinAbsval(consdata);
    4404 }
    4405 }
    4406
    4407 /* get new consdata information, because scalecons() might have deleted variables */
    4408 vals = consdata->vals;
    4409 nvars = consdata->nvars;
    4410 assert(nvars == 0 || vals != NULL);
    4411 }
    4412
    4413 /*
    4414 * division by greatest common divisor
    4415 */
    4416 if( success && nvars >= 1 )
    4417 {
    4418 /* all coefficients are integral: divide them by their greatest common divisor */
    4419 assert(SCIPisIntegral(scip, vals[0]));
    4420
    4421 gcd = (SCIP_Longint)(REALABS(vals[0]) + feastol);
    4422 for( i = 1; i < nvars && gcd > 1; ++i )
    4423 {
    4424 assert(SCIPisIntegral(scip, vals[i]));
    4425 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[i]) + feastol));
    4426 }
    4427
    4428 if( gcd > 1 )
    4429 {
    4430 /* since the lhs/rhs is not respected for gcd calculation it can happen that we detect infeasibility */
    4431 if( !consdata->hascontvar && onlyintegral )
    4432 {
    4433 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) && !SCIPisFeasIntegral(scip, consdata->rhs / gcd) )
    4434 {
    4435 *infeasible = TRUE;
    4436
    4437 SCIPdebugMsg(scip, "detected infeasibility of constraint after scaling with gcd=%" SCIP_LONGINT_FORMAT ":\n", gcd);
    4439
    4440 return SCIP_OKAY;
    4441 }
    4442 }
    4443
    4444 /* divide the constraint by the greatest common divisor of the coefficients */
    4445 SCIPdebugMsg(scip, "divide linear constraint by greatest common divisor %" SCIP_LONGINT_FORMAT "\n", gcd);
    4447 SCIP_CALL( scaleCons(scip, cons, 1.0/(SCIP_Real)gcd) );
    4448
    4449 if( consdata->validmaxabsval )
    4450 {
    4451 consdata->maxabsval /= REALABS((SCIP_Real)gcd);
    4452 }
    4453 if( consdata->validminabsval )
    4454 {
    4455 consdata->minabsval /= REALABS((SCIP_Real)gcd);
    4456 }
    4457 }
    4458 }
    4459
    4460 /* mark constraint to be normalized */
    4461 consdata->normalized = TRUE;
    4462
    4463 SCIPdebugMsg(scip, "normalized constraint:\n");
    4465
    4466 return SCIP_OKAY;
    4467}
    4468
    4469/** replaces multiple occurrences of a variable by a single non-zero coefficient */
    4470static
    4472 SCIP* scip, /**< SCIP data structure */
    4473 SCIP_CONS* cons /**< linear constraint */
    4474 )
    4475{
    4476 SCIP_CONSDATA* consdata;
    4477 SCIP_VAR* var;
    4478 SCIP_Real valsum;
    4479 int v;
    4480
    4481 assert(scip != NULL);
    4482 assert(cons != NULL);
    4483
    4484 consdata = SCIPconsGetData(cons);
    4485 assert(consdata != NULL);
    4486
    4487 if( consdata->merged )
    4488 return SCIP_OKAY;
    4489
    4490 /* sort the constraint */
    4491 SCIP_CALL( consdataSort(scip, consdata) );
    4492
    4493 v = consdata->nvars - 1;
    4494
    4495 /* go backwards through the constraint looking for multiple occurrences of the same variable;
    4496 * backward direction is necessary, since delCoefPos() modifies the given position and
    4497 * the subsequent ones
    4498 */
    4499 while( v >= 0 )
    4500 {
    4501 var = consdata->vars[v];
    4502 valsum = consdata->vals[v];
    4503
    4504 /* sum multiple occurrences */
    4505 while( v >= 1 && consdata->vars[v-1] == var )
    4506 {
    4507 SCIP_CALL( delCoefPos(scip, cons, v) );
    4508 --v;
    4509 valsum += consdata->vals[v];
    4510 }
    4511
    4512 assert(consdata->vars[v] == var);
    4513
    4514 /* modify the last existing occurrence of the variable */
    4515 if( SCIPisZero(scip, valsum) )
    4516 {
    4517 SCIP_CALL( delCoefPos(scip, cons, v) );
    4518 }
    4519 else if( valsum != consdata->vals[v] ) /*lint !e777*/
    4520 {
    4521 SCIP_CALL( chgCoefPos(scip, cons, v, valsum) );
    4522 }
    4523
    4524 --v;
    4525 }
    4526
    4527 consdata->merged = TRUE;
    4528
    4529 return SCIP_OKAY;
    4530}
    4531
    4532/** replaces all fixed and aggregated variables by their non-fixed counterparts */
    4533static
    4535 SCIP* scip, /**< SCIP data structure */
    4536 SCIP_CONS* cons, /**< linear constraint */
    4537 SCIP_Bool* infeasible /**< pointer to store if infeasibility is detected; or NULL if this
    4538 * information is not needed; in this case, we apply all fixings
    4539 * instead of stopping after the first infeasible one */
    4540 )
    4541{
    4542 SCIP_CONSDATA* consdata;
    4543 int v;
    4544
    4545 assert(scip != NULL);
    4546 assert(cons != NULL);
    4547
    4548 if( infeasible != NULL )
    4549 *infeasible = FALSE;
    4550
    4551 consdata = SCIPconsGetData(cons);
    4552 assert(consdata != NULL);
    4553
    4554 if( consdata->eventdata == NULL )
    4555 {
    4556 SCIP_CONSHDLR* conshdlr;
    4557 SCIP_CONSHDLRDATA* conshdlrdata;
    4558
    4559 conshdlr = SCIPconsGetHdlr(cons);
    4560 assert(conshdlr != NULL);
    4561
    4562 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4563 assert(conshdlrdata != NULL);
    4564
    4565 /* catch bound change events of variables */
    4566 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
    4567 assert(consdata->eventdata != NULL);
    4568 }
    4569
    4570 if( !consdata->removedfixings )
    4571 {
    4572 SCIP_Real lhssubtrahend;
    4573 SCIP_Real rhssubtrahend;
    4574
    4575 /* if an unmodifiable row has been added to the LP, then we cannot apply fixing anymore (cannot change a row)
    4576 * this should not happen, as applyFixings is called in addRelaxation() before creating and adding a row
    4577 */
    4578 assert(consdata->row == NULL || !SCIProwIsInLP(consdata->row) || SCIProwIsModifiable(consdata->row));
    4579
    4580 lhssubtrahend = 0.0;
    4581 rhssubtrahend = 0.0;
    4582
    4583 SCIPdebugMsg(scip, "applying fixings:\n");
    4585
    4586 v = 0;
    4587 while( v < consdata->nvars )
    4588 {
    4589 SCIP_VAR* var = consdata->vars[v];
    4590 SCIP_Real scalar = consdata->vals[v];
    4591 SCIP_Real constant = 0.0;
    4592 assert(SCIPvarIsTransformed(var));
    4593
    4594 SCIP_CALL( SCIPgetProbvarSum(scip, &var, &scalar, &constant) );
    4595
    4596 switch( SCIPvarGetStatus(var) )
    4597 {
    4599 SCIPerrorMessage("original variable in transformed linear constraint\n");
    4600 return SCIP_INVALIDDATA;
    4601
    4604 SCIPerrorMessage("aggregated variable after resolving linear term\n");
    4605 return SCIP_INVALIDDATA;
    4606
    4609 if( var != consdata->vars[v] )
    4610 {
    4611 assert(scalar != 0.0);
    4612 SCIP_CALL( addCoef(scip, cons, var, scalar) );
    4613 SCIP_CALL( delCoefPos(scip, cons, v) );
    4614
    4615 assert(!SCIPisInfinity(scip, ABS(constant)));
    4616 if( !SCIPisInfinity(scip, -consdata->lhs) )
    4617 lhssubtrahend += constant;
    4618 if( !SCIPisInfinity(scip, consdata->rhs) )
    4619 rhssubtrahend += constant;
    4620 }
    4621 ++v;
    4622 break;
    4623
    4625 if( scalar != 0.0 )
    4626 {
    4627 SCIP_VAR** aggrvars;
    4628 SCIP_Real* aggrscalars;
    4629 SCIP_Real aggrconstant;
    4630 int naggrvars;
    4631 int i;
    4632
    4634 aggrvars = SCIPvarGetMultaggrVars(var);
    4635 aggrscalars = SCIPvarGetMultaggrScalars(var);
    4636 aggrconstant = SCIPvarGetMultaggrConstant(var);
    4637 naggrvars = SCIPvarGetMultaggrNVars(var);
    4638
    4639 for( i = 0; i < naggrvars; ++i )
    4640 {
    4641 SCIP_CALL( addCoef(scip, cons, aggrvars[i], scalar * aggrscalars[i]) );
    4642 }
    4643
    4644 constant += scalar * aggrconstant;
    4645 }
    4646 /*lint -fallthrough*/
    4647
    4649 if( !SCIPisInfinity(scip, -consdata->lhs) )
    4650 {
    4651 if( SCIPisInfinity(scip, ABS(constant)) )
    4652 {
    4653 /* if lhs gets infinity it means that the problem is infeasible */
    4654 if( constant < 0.0 )
    4655 {
    4657
    4658 if( infeasible != NULL )
    4659 {
    4660 *infeasible = TRUE;
    4661 return SCIP_OKAY;
    4662 }
    4663 }
    4664 else
    4665 {
    4666 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
    4667 }
    4668 }
    4669 else
    4670 lhssubtrahend += constant;
    4671 }
    4672 if( !SCIPisInfinity(scip, consdata->rhs) )
    4673 {
    4674 if( SCIPisInfinity(scip, ABS(constant)) )
    4675 {
    4676 /* if rhs gets -infinity it means that the problem is infeasible */
    4677 if( constant > 0.0 )
    4678 {
    4679 SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
    4680
    4681 if( infeasible != NULL )
    4682 {
    4683 *infeasible = TRUE;
    4684 return SCIP_OKAY;
    4685 }
    4686 }
    4687 else
    4688 {
    4690 }
    4691 }
    4692 else
    4693 rhssubtrahend += constant;
    4694 }
    4695 SCIP_CALL( delCoefPos(scip, cons, v) );
    4696 break;
    4697
    4698 default:
    4699 SCIPerrorMessage("unknown variable status\n");
    4700 SCIPABORT();
    4701 return SCIP_INVALIDDATA; /*lint !e527*/
    4702 }
    4703 }
    4704
    4705 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->lhs) )
    4706 {
    4707 /* check left hand side of unmodifiable empty constraint with former feasibility tolerance */
    4708 if( !SCIPconsIsModifiable(cons) && consdata->nvars == 0 )
    4709 {
    4710 if( SCIPisFeasLT(scip, lhssubtrahend, consdata->lhs) )
    4711 {
    4713
    4714 if( infeasible != NULL )
    4715 {
    4716 *infeasible = TRUE;
    4717 return SCIP_OKAY;
    4718 }
    4719 }
    4720 else
    4721 {
    4722 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
    4723 }
    4724 }
    4725 /* for normal numbers that are relatively equal, subtraction can lead to cancellation,
    4726 * causing wrong fixings of other variables --> better use a real zero here
    4727 */
    4728 else if( SCIPisGE(scip, ABS(consdata->lhs), 1.0) && SCIPisEQ(scip, lhssubtrahend, consdata->lhs) )
    4729 {
    4730 SCIP_CALL( chgLhs(scip, cons, 0.0) );
    4731 }
    4732 else
    4733 {
    4734 SCIP_CALL( chgLhs(scip, cons, consdata->lhs - lhssubtrahend) );
    4735 }
    4736 }
    4737 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs) )
    4738 {
    4739 /* check right hand side of unmodifiable empty constraint with former feasibility tolerance */
    4740 if( !SCIPconsIsModifiable(cons) && consdata->nvars == 0 )
    4741 {
    4742 if( SCIPisFeasGT(scip, rhssubtrahend, consdata->rhs) )
    4743 {
    4744 SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
    4745
    4746 if( infeasible != NULL )
    4747 {
    4748 *infeasible = TRUE;
    4749 return SCIP_OKAY;
    4750 }
    4751 }
    4752 else
    4753 {
    4755 }
    4756 }
    4757 /* for normal numbers that are relatively equal, subtraction can lead to cancellation,
    4758 * causing wrong fixings of other variables --> better use a real zero here
    4759 */
    4760 else if( SCIPisGE(scip, ABS(consdata->rhs), 1.0) && SCIPisEQ(scip, rhssubtrahend, consdata->rhs) )
    4761 {
    4762 SCIP_CALL( chgRhs(scip, cons, 0.0) );
    4763 }
    4764 else
    4765 {
    4766 SCIP_CALL( chgRhs(scip, cons, consdata->rhs - rhssubtrahend) );
    4767 }
    4768 }
    4769 consdata->removedfixings = TRUE;
    4770
    4771 SCIPdebugMsg(scip, "after fixings:\n");
    4773
    4774 /* if aggregated variables have been replaced, multiple entries of the same variable are possible and we have
    4775 * to clean up the constraint
    4776 */
    4777 SCIP_CALL( mergeMultiples(scip, cons) );
    4778
    4779 SCIPdebugMsg(scip, "after merging:\n");
    4781 }
    4782 assert(consdata->removedfixings);
    4783
    4784#ifndef NDEBUG
    4785 /* check, if all fixings are applied */
    4786 for( v = 0; v < consdata->nvars; ++v )
    4787 assert(SCIPvarIsActive(consdata->vars[v]));
    4788#endif
    4789
    4790 return SCIP_OKAY;
    4791}
    4792
    4793/** for each variable in the linear constraint, except the inferred variable, adds one bound to the conflict analysis'
    4794 * candidate store (bound depends on sign of coefficient and whether the left or right hand side was the reason for the
    4795 * inference variable's bound change); the conflict analysis can be initialized with the linear constraint being the
    4796 * conflict detecting constraint by using NULL as inferred variable
    4797 */
    4798static
    4800 SCIP* scip, /**< SCIP data structure */
    4801 SCIP_CONS* cons, /**< constraint that inferred the bound change */
    4802 SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
    4803 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
    4804 int inferpos, /**< position of the inferred variable in the vars array */
    4805 SCIP_Bool reasonisrhs /**< is the right hand side responsible for the bound change? */
    4806 )
    4807{
    4808 SCIP_CONSDATA* consdata;
    4809 SCIP_VAR** vars;
    4810 SCIP_Real* vals;
    4811 int nvars;
    4812 int i;
    4813
    4814 assert(scip != NULL);
    4815 assert(cons != NULL);
    4816
    4817 consdata = SCIPconsGetData(cons);
    4818
    4819 assert(consdata != NULL);
    4820
    4821 vars = consdata->vars;
    4822 vals = consdata->vals;
    4823 nvars = consdata->nvars;
    4824
    4825 assert(vars != NULL || nvars == 0);
    4826 assert(vals != NULL || nvars == 0);
    4827
    4828 assert(-1 <= inferpos && inferpos < nvars);
    4829 assert((infervar == NULL) == (inferpos == -1));
    4830 assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
    4831
    4832 /* for each variable, add the bound to the conflict queue, that is responsible for the minimal or maximal
    4833 * residual value, depending on whether the left or right hand side is responsible for the bound change:
    4834 * - if the right hand side is the reason, the minimal residual activity is responsible
    4835 * - if the left hand side is the reason, the maximal residual activity is responsible
    4836 */
    4837
    4838 /* if the variable is integral we only need to add reason bounds until the propagation could be applied */
    4839 if( infervar == NULL || SCIPvarIsIntegral(infervar) )
    4840 {
    4841 SCIP_Real minresactivity;
    4842 SCIP_Real maxresactivity;
    4843 SCIP_Bool ismintight;
    4844 SCIP_Bool ismaxtight;
    4845 SCIP_Bool isminsettoinfinity;
    4846 SCIP_Bool ismaxsettoinfinity;
    4847
    4848 minresactivity = -SCIPinfinity(scip);
    4849 maxresactivity = SCIPinfinity(scip);
    4850
    4851 /* calculate the minimal and maximal global activity of all other variables involved in the constraint */
    4852 if( infervar != NULL )
    4853 {
    4854 assert(vals != NULL); /* for flexelint */
    4855 if( reasonisrhs )
    4856 consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, &minresactivity, NULL,
    4857 &ismintight, NULL, &isminsettoinfinity, NULL);
    4858 else
    4859 consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, NULL, &maxresactivity,
    4860 NULL, &ismaxtight, NULL, &ismaxsettoinfinity);
    4861 }
    4862 else
    4863 {
    4864 if( reasonisrhs )
    4865 consdataGetGlbActivityBounds(scip, consdata, FALSE, &minresactivity, NULL,
    4866 &ismintight, NULL, &isminsettoinfinity, NULL);
    4867 else
    4868 consdataGetGlbActivityBounds(scip, consdata, FALSE, NULL, &maxresactivity,
    4869 NULL, &ismaxtight, NULL, &ismaxsettoinfinity);
    4870 }
    4871
    4872 /* we can only do something clever, if the residual activity is finite and not relaxed */
    4873 if( (reasonisrhs && !isminsettoinfinity && ismintight) || (!reasonisrhs && !ismaxsettoinfinity && ismaxtight) ) /*lint !e644*/
    4874 {
    4875 SCIP_Real rescap;
    4876 SCIP_Bool resactisinf;
    4877
    4878 resactisinf = FALSE;
    4879
    4880 /* calculate the residual capacity that would be left, if the variable would be set to one more / one less
    4881 * than its inferred bound
    4882 */
    4883 if( infervar != NULL )
    4884 {
    4885 assert(vals != NULL); /* for flexelint */
    4886
    4887 if( reasonisrhs )
    4888 {
    4889 if( SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
    4890 {
    4891 consdataGetReliableResidualActivity(scip, consdata, infervar, &minresactivity, TRUE, TRUE);
    4892 if( SCIPisInfinity(scip, -minresactivity) )
    4893 resactisinf = TRUE;
    4894 }
    4895 rescap = consdata->rhs - minresactivity;
    4896 }
    4897 else
    4898 {
    4899 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
    4900 {
    4901 consdataGetReliableResidualActivity(scip, consdata, infervar, &maxresactivity, FALSE, TRUE);
    4902 if( SCIPisInfinity(scip, maxresactivity) )
    4903 resactisinf = TRUE;
    4904 }
    4905 rescap = consdata->lhs - maxresactivity;
    4906 }
    4907
    4908 if( reasonisrhs == (vals[inferpos] > 0.0) )
    4909 rescap -= vals[inferpos] * (SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) + 1.0);
    4910 else
    4911 rescap -= vals[inferpos] * (SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) - 1.0);
    4912 }
    4913 else
    4914 rescap = (reasonisrhs ? consdata->rhs - minresactivity : consdata->lhs - maxresactivity);
    4915
    4916 if( !resactisinf )
    4917 {
    4918 /* now add bounds as reasons until the residual capacity is exceeded */
    4919 for( i = 0; i < nvars; ++i )
    4920 {
    4921 assert( vars != NULL && vals != NULL ); /* for lint */
    4922
    4923 /* zero coefficients and the inferred variable can be ignored */
    4924 if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
    4925 continue;
    4926
    4927 /* check if the residual capacity is exceeded */
    4928 if( (reasonisrhs && SCIPisFeasNegative(scip, rescap))
    4929 || (!reasonisrhs && SCIPisFeasPositive(scip, rescap)) )
    4930 break;
    4931
    4932 /* update the residual capacity due to the local bound of this variable */
    4933 if( reasonisrhs == (vals[i] > 0.0) )
    4934 {
    4935 /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound */
    4936 SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
    4937 rescap -= vals[i] * (SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetLbGlobal(vars[i]));
    4938 }
    4939 else
    4940 {
    4941 /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound */
    4942 SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
    4943 rescap -= vals[i] * (SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetUbGlobal(vars[i]));
    4944 }
    4945 }
    4946 return SCIP_OKAY;
    4947 }
    4948 }
    4949 }
    4950
    4951 /* for a bound change on a continuous variable, all locally changed bounds are responsible */
    4952 for( i = 0; i < nvars; ++i )
    4953 {
    4954 assert(vars != NULL); /* for flexelint */
    4955 assert(vals != NULL); /* for flexelint */
    4956
    4957 /* zero coefficients and the inferred variable can be ignored */
    4958 if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
    4959 continue;
    4960
    4961 if( reasonisrhs == (vals[i] > 0.0) )
    4962 {
    4963 /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound is responsible */
    4964 SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
    4965 }
    4966 else
    4967 {
    4968 /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound is responsible */
    4969 SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
    4970 }
    4971 }
    4972
    4973 return SCIP_OKAY;
    4974}
    4975
    4976/** for each variable in the linear ranged row constraint, except the inferred variable, adds the bounds of all fixed
    4977 * variables to the conflict analysis' candidate store; the conflict analysis can be initialized
    4978 * with the linear constraint being the conflict detecting constraint by using NULL as inferred variable
    4979 */
    4980static
    4982 SCIP* scip, /**< SCIP data structure */
    4983 SCIP_CONS* cons, /**< constraint that inferred the bound change */
    4984 SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
    4985 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
    4986 int inferpos /**< position of the inferred variable in the vars array, or -1 */
    4987 )
    4988{
    4989 SCIP_CONSDATA* consdata;
    4990 SCIP_VAR** vars;
    4991 int nvars;
    4992 int v;
    4993
    4994 assert(scip != NULL);
    4995 assert(cons != NULL);
    4996
    4997 consdata = SCIPconsGetData(cons);
    4998 assert(consdata != NULL);
    4999 vars = consdata->vars;
    5000 nvars = consdata->nvars;
    5001 assert(vars != NULL || nvars == 0);
    5002 assert(-1 <= inferpos && inferpos < nvars);
    5003 assert((infervar == NULL) == (inferpos == -1));
    5004 assert(inferpos == -1 || vars != NULL);
    5005 assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
    5006
    5007 /* collect all fixed variables */
    5008 for( v = nvars - 1; v >= 0; --v )
    5009 {
    5010 assert(vars != NULL); /* for flexelint */
    5011
    5012 /* need to add old bounds before propagation of inferrence variable */
    5013 if( vars[v] == infervar )
    5014 {
    5015 assert(vars[v] != NULL);
    5016
    5017 if( !SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetLbGlobal(vars[v])) )
    5018 {
    5019 /* @todo get boundchange index before this last boundchange and correct the index */
    5020 SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
    5021 }
    5022
    5023 if( !SCIPisEQ(scip, SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetUbGlobal(vars[v])) )
    5024 {
    5025 /* @todo get boundchange index before this last boundchange and correct the index */
    5026 SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
    5027 }
    5028
    5029 continue;
    5030 }
    5031
    5032 /* check for fixed variables */
    5033 if( SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE)) )
    5034 {
    5035 /* add all bounds of fixed variables which lead to the boundchange of the given inference variable */
    5036 SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
    5037 SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
    5038 }
    5039 }
    5040
    5041 return SCIP_OKAY;
    5042}
    5043
    5044/** add reasoning variables to conflict candidate queue which led to the conflict */
    5045static
    5047 SCIP* scip, /**< SCIP data structure */
    5048 SCIP_VAR** vars, /**< variables reasoning the infeasibility */
    5049 int nvars, /**< number of variables reasoning the infeasibility */
    5050 SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
    5051 SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
    5052 )
    5053{
    5054 int v;
    5055
    5056 assert(scip != NULL);
    5057
    5058 /* collect all variables for which the local bounds differ from their global bounds */
    5059 for( v = nvars - 1; v >= 0; --v )
    5060 {
    5061 assert(vars != NULL);
    5062
    5063 /* check for local bound changes variables */
    5064 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(vars[v]), SCIPvarGetLbGlobal(vars[v])) )
    5065 {
    5066 /* add conflict bound */
    5067 SCIP_CALL( SCIPaddConflictLb(scip, vars[v], 0) );
    5068 }
    5069
    5070 if( !SCIPisEQ(scip, SCIPvarGetUbLocal(vars[v]), SCIPvarGetUbGlobal(vars[v])) )
    5071 {
    5072 SCIP_CALL( SCIPaddConflictUb(scip, vars[v], 0) );
    5073 }
    5074 }
    5075
    5076 if( var != NULL )
    5077 {
    5078 if( bound < SCIPvarGetLbLocal(var) )
    5079 {
    5080 SCIP_CALL( SCIPaddConflictLb(scip, var, 0) );
    5081 }
    5082
    5083 if( bound > SCIPvarGetUbLocal(var) )
    5084 {
    5085 SCIP_CALL( SCIPaddConflictUb(scip, var, 0) );
    5086 }
    5087 }
    5088
    5089 return SCIP_OKAY;
    5090}
    5091
    5092/** resolves a propagation on the given variable by supplying the variables needed for applying the corresponding
    5093 * propagation rule (see propagateCons()):
    5094 * (1) activity residuals of all other variables tighten bounds of single variable
    5095 */
    5096static
    5098 SCIP* scip, /**< SCIP data structure */
    5099 SCIP_CONS* cons, /**< constraint that inferred the bound change */
    5100 SCIP_VAR* infervar, /**< variable that was deduced */
    5101 INFERINFO inferinfo, /**< inference information */
    5102 SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
    5103 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
    5104 SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
    5105 )
    5106{
    5107 SCIP_CONSDATA* consdata;
    5108 SCIP_VAR** vars;
    5109#ifndef NDEBUG
    5110 SCIP_Real* vals;
    5111#endif
    5112 int nvars;
    5113 int inferpos;
    5114
    5115 assert(scip != NULL);
    5116 assert(cons != NULL);
    5117 assert(result != NULL);
    5118
    5119 consdata = SCIPconsGetData(cons);
    5120 assert(consdata != NULL);
    5121 vars = consdata->vars;
    5122 nvars = consdata->nvars;
    5123#ifndef NDEBUG
    5124 vals = consdata->vals;
    5125 assert(vars != NULL);
    5126 assert(vals != NULL);
    5127#endif
    5128
    5129 /* get the position of the inferred variable in the vars array */
    5130 inferpos = inferInfoGetPos(inferinfo);
    5131 if( inferpos >= nvars || vars[inferpos] != infervar )
    5132 {
    5133 /* find inference variable in constraint */
    5134 /**@todo use a binary search here; the variables can be sorted by variable index */
    5135 for( inferpos = 0; inferpos < nvars && vars[inferpos] != infervar; ++inferpos )
    5136 {}
    5137 }
    5138 assert(inferpos < nvars);
    5139 assert(vars[inferpos] == infervar);
    5140 assert(!SCIPisZero(scip, vals[inferpos]));
    5141
    5142 switch( inferInfoGetProprule(inferinfo) )
    5143 {
    5144 case PROPRULE_1_RHS:
    5145 /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
    5146 * constraint (only taking the other variables into account) didn't leave enough space for a larger
    5147 * domain in order to not exceed the right hand side of the inequality
    5148 */
    5149 assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_UPPER));
    5150 SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, TRUE) );
    5151 *result = SCIP_SUCCESS;
    5152 break;
    5153
    5154 case PROPRULE_1_LHS:
    5155 /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
    5156 * constraint (only taking the other variables into account) didn't leave enough space for a larger
    5157 * domain in order to not fall below the left hand side of the inequality
    5158 */
    5159 assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_LOWER));
    5160 SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, FALSE) );
    5161 *result = SCIP_SUCCESS;
    5162 break;
    5163
    5165 /* the bound of the variable was tightened, because some variables were already fixed and the leftover only allow
    5166 * the given inference variable to their bounds in this given ranged row
    5167 */
    5168
    5169 /* check that we really have a ranged row here */
    5170 assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
    5171 SCIP_CALL( addConflictFixedVars(scip, cons, infervar, bdchgidx, inferpos) );
    5172 *result = SCIP_SUCCESS;
    5173 break;
    5174
    5175 case PROPRULE_INVALID:
    5176 default:
    5177 SCIPerrorMessage("invalid inference information %d in linear constraint <%s> at position %d for %s bound of variable <%s>\n",
    5178 inferInfoGetProprule(inferinfo), SCIPconsGetName(cons), inferInfoGetPos(inferinfo),
    5179 boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(infervar));
    5180 SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
    5181 SCIPinfoMessage(scip, NULL, ";\n");
    5182 return SCIP_INVALIDDATA;
    5183 }
    5184
    5185 return SCIP_OKAY;
    5186}
    5187
    5188/** analyzes conflicting bounds on given constraint, and adds conflict constraint to problem */
    5189static
    5191 SCIP* scip, /**< SCIP data structure */
    5192 SCIP_CONS* cons, /**< conflict detecting constraint */
    5193 SCIP_Bool reasonisrhs /**< is the right hand side responsible for the conflict? */
    5194 )
    5195{
    5196 /* conflict analysis can only be applied in solving stage and if it is turned on */
    5198 return SCIP_OKAY;
    5199
    5200 /* initialize conflict analysis */
    5202
    5203 /* add the conflicting bound for each variable of infeasible constraint to conflict candidate queue */
    5204 SCIP_CALL( addConflictBounds(scip, cons, NULL, NULL, -1, reasonisrhs) );
    5205
    5206 /* analyze the conflict */
    5208
    5209 return SCIP_OKAY;
    5210}
    5211
    5212/** check if there is any hope of tightening some bounds */
    5213static
    5215 SCIP_CONS* cons /**< linear constraint */
    5216 )
    5217{
    5218 SCIP_CONSDATA* consdata;
    5219 int infcountmin;
    5220 int infcountmax;
    5221
    5222 consdata = SCIPconsGetData(cons);
    5223 assert(consdata != NULL);
    5224
    5225 infcountmin = consdata->minactivityneginf
    5226 + consdata->minactivityposinf
    5227 + consdata->minactivityneghuge
    5228 + consdata->minactivityposhuge;
    5229 infcountmax = consdata->maxactivityneginf
    5230 + consdata->maxactivityposinf
    5231 + consdata->maxactivityneghuge
    5232 + consdata->maxactivityposhuge;
    5233
    5234 if( infcountmin > 1 && infcountmax > 1 )
    5235 return FALSE;
    5236
    5237 return TRUE;
    5238}
    5239
    5240/** tighten upper bound */
    5241static
    5243 SCIP* scip, /**< SCIP data structure */
    5244 SCIP_CONS* cons, /**< linear constraint */
    5245 int pos, /**< variable position */
    5246 PROPRULE proprule, /**< propagation rule that deduced the value */
    5247 SCIP_Real newub, /**< new upper bound */
    5248 SCIP_Real oldub, /**< old upper bound */
    5249 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
    5250 int* nchgbds, /**< pointer to count the total number of tightened bounds */
    5251 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
    5252 )
    5253{
    5254 SCIP_CONSDATA* consdata;
    5255 SCIP_VAR* var;
    5256 SCIP_Real lb;
    5257 SCIP_Bool infeasible;
    5258 SCIP_Bool tightened;
    5259
    5260 assert(cons != NULL);
    5261 assert(!SCIPisInfinity(scip, newub));
    5262
    5263 consdata = SCIPconsGetData(cons);
    5264 assert(consdata != NULL);
    5265 var = consdata->vars[pos];
    5266 assert(var != NULL);
    5267
    5268 lb = SCIPvarGetLbLocal(var);
    5269 newub = SCIPadjustedVarUb(scip, var, newub);
    5270
    5271 if( force || SCIPisUbBetter(scip, newub, lb, oldub) )
    5272 {
    5273 SCIP_VARTYPE vartype = SCIPvarGetType(var);
    5274 SCIP_IMPLINTTYPE impltype = SCIPvarGetImplType(var);
    5275
    5276 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
    5277 SCIPconsGetName(cons), SCIPvarGetName(var), lb, oldub, consdata->vals[pos],
    5278 QUAD_TO_DBL(consdata->minactivity), QUAD_TO_DBL(consdata->maxactivity), consdata->lhs, consdata->rhs, newub);
    5279
    5280 /* tighten upper bound */
    5281 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
    5282
    5283 if( infeasible )
    5284 {
    5285 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
    5286 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
    5287
    5288 /* analyze conflict */
    5290
    5291 *cutoff = TRUE;
    5292 }
    5293 else if( tightened )
    5294 {
    5295 assert(SCIPisFeasLE(scip, SCIPvarGetUbLocal(var), oldub));
    5296 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
    5297 SCIPconsGetName(cons), SCIPvarGetName(var), lb, SCIPvarGetUbLocal(var));
    5298
    5299 (*nchgbds)++;
    5300
    5301 /* if variable type was changed we might be able to upgrade the constraint */
    5302 if( SCIPvarGetType(var) != vartype || SCIPvarGetImplType(var) != impltype )
    5303 consdata->upgradetried = FALSE;
    5304 }
    5305 }
    5306 return SCIP_OKAY;
    5307}
    5308
    5309/** tighten lower bound */
    5310static
    5312 SCIP* scip, /**< SCIP data structure */
    5313 SCIP_CONS* cons, /**< linear constraint */
    5314 int pos, /**< variable position */
    5315 PROPRULE proprule, /**< propagation rule that deduced the value */
    5316 SCIP_Real newlb, /**< new lower bound */
    5317 SCIP_Real oldlb, /**< old lower bound */
    5318 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
    5319 int* nchgbds, /**< pointer to count the total number of tightened bounds */
    5320 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
    5321 )
    5322{
    5323 SCIP_CONSDATA* consdata;
    5324 SCIP_VAR* var;
    5325 SCIP_Real ub;
    5326 SCIP_Bool infeasible;
    5327 SCIP_Bool tightened;
    5328
    5329 assert(cons != NULL);
    5330 assert(!SCIPisInfinity(scip, newlb));
    5331
    5332 consdata = SCIPconsGetData(cons);
    5333 assert(consdata != NULL);
    5334 var = consdata->vars[pos];
    5335 assert(var != NULL);
    5336
    5337 ub = SCIPvarGetUbLocal(var);
    5338 newlb = SCIPadjustedVarLb(scip, var, newlb);
    5339
    5340 if( force || SCIPisLbBetter(scip, newlb, oldlb, ub) )
    5341 {
    5342 SCIP_VARTYPE vartype = SCIPvarGetType(var);
    5343 SCIP_IMPLINTTYPE impltype = SCIPvarGetImplType(var);
    5344
    5345 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
    5346 SCIPconsGetName(cons), SCIPvarGetName(var), oldlb, ub, consdata->vals[pos],
    5347 QUAD_TO_DBL(consdata->minactivity), QUAD_TO_DBL(consdata->maxactivity), consdata->lhs, consdata->rhs, newlb);
    5348
    5349 /* tighten lower bound */
    5350 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
    5351
    5352 if( infeasible )
    5353 {
    5354 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
    5355 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
    5356
    5357 /* analyze conflict */
    5359
    5360 *cutoff = TRUE;
    5361 }
    5362 else if( tightened )
    5363 {
    5364 assert(SCIPisFeasGE(scip, SCIPvarGetLbLocal(var), oldlb));
    5365 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
    5366 SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetLbLocal(var), ub);
    5367
    5368 (*nchgbds)++;
    5369
    5370 /* if variable type was changed we might be able to upgrade the constraint */
    5371 if( SCIPvarGetType(var) != vartype || SCIPvarGetImplType(var) != impltype )
    5372 consdata->upgradetried = FALSE;
    5373 }
    5374 }
    5375 return SCIP_OKAY;
    5376}
    5377
    5378/** tightens bounds of a single variable due to activity bounds (easy case) */
    5379static
    5381 SCIP* scip, /**< SCIP data structure */
    5382 SCIP_CONS* cons, /**< linear constraint */
    5383 int pos, /**< position of the variable in the vars array */
    5384 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
    5385 int* nchgbds, /**< pointer to count the total number of tightened bounds */
    5386 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
    5387 )
    5388{
    5389 SCIP_CONSDATA* consdata;
    5390 SCIP_VAR* var;
    5391 SCIP_Real val;
    5392 SCIP_Real lb;
    5393 SCIP_Real ub;
    5394 SCIP_Real lhs;
    5395 SCIP_Real rhs;
    5396
    5397 assert(scip != NULL);
    5398 assert(cons != NULL);
    5399 assert(cutoff != NULL);
    5400 assert(nchgbds != NULL);
    5401
    5402 /* we cannot tighten variables' bounds, if the constraint may be not complete */
    5403 if( SCIPconsIsModifiable(cons) )
    5404 return SCIP_OKAY;
    5405
    5406 consdata = SCIPconsGetData(cons);
    5407 assert(consdata != NULL);
    5408 assert(0 <= pos && pos < consdata->nvars);
    5409
    5410 *cutoff = FALSE;
    5411
    5412 var = consdata->vars[pos];
    5413 assert(var != NULL);
    5414
    5415 /* we cannot tighten bounds of multi-aggregated variables */
    5417 return SCIP_OKAY;
    5418
    5419 val = consdata->vals[pos];
    5420 lhs = consdata->lhs;
    5421 rhs = consdata->rhs;
    5422 assert(!SCIPisZero(scip, val));
    5423 assert(!SCIPisInfinity(scip, lhs));
    5424 assert(!SCIPisInfinity(scip, -rhs));
    5425
    5426 lb = SCIPvarGetLbLocal(var);
    5427 ub = SCIPvarGetUbLocal(var);
    5428 assert(SCIPisLE(scip, lb, ub));
    5429
    5430 /* recompute activities if needed */
    5431 if( !consdata->validactivities )
    5432 consdataCalcActivities(scip, consdata);
    5433 assert(consdata->validactivities);
    5434 if( !consdata->validminact )
    5436 assert(consdata->validminact);
    5437
    5438 if( val > 0.0 )
    5439 {
    5440 /* check, if we can tighten the variable's upper bound */
    5441 if( !SCIPisInfinity(scip, rhs) )
    5442 {
    5443 SCIP_Real slack;
    5444 SCIP_Real alpha;
    5445
    5446 /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
    5447 assert(consdata->validminact);
    5448
    5449 /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
    5450 if( SCIPisFeasLT(scip, rhs, QUAD_TO_DBL(consdata->minactivity)) )
    5451 {
    5452 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
    5453 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->minactivity), rhs);
    5454
    5455 *cutoff = TRUE;
    5456 return SCIP_OKAY;
    5457 }
    5458
    5459 slack = rhs - QUAD_TO_DBL(consdata->minactivity);
    5460
    5461 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
    5462 * it to zero
    5463 */
    5464 if( !SCIPisPositive(scip, slack) )
    5465 slack = 0.0;
    5466
    5467 alpha = val * (ub - lb);
    5468 assert(!SCIPisNegative(scip, alpha));
    5469
    5470 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
    5471 {
    5472 SCIP_Real newub;
    5473
    5474 /* compute new upper bound */
    5475 newub = lb + (slack / val);
    5476
    5477 SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_RHS, newub, ub, cutoff, nchgbds, force) );
    5478
    5479 if( *cutoff )
    5480 {
    5481 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
    5482 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
    5483
    5484 return SCIP_OKAY;
    5485 }
    5486
    5487 /* collect the new upper bound which is needed for the lower bound computation */
    5488 ub = SCIPvarGetUbLocal(var);
    5489 }
    5490 }
    5491
    5492 /* check, if we can tighten the variable's lower bound */
    5493 if( !SCIPisInfinity(scip, -lhs) )
    5494 {
    5495 SCIP_Real slack;
    5496 SCIP_Real alpha;
    5497
    5498 /* make sure the max activity is reliable */
    5499 if( !consdata->validmaxact )
    5500 {
    5502 }
    5503 assert(consdata->validmaxact);
    5504
    5505 /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
    5506 if( SCIPisFeasLT(scip, QUAD_TO_DBL(consdata->maxactivity), lhs) )
    5507 {
    5508 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
    5509 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->maxactivity), lhs);
    5510
    5511 *cutoff = TRUE;
    5512 return SCIP_OKAY;
    5513 }
    5514
    5515 slack = QUAD_TO_DBL(consdata->maxactivity) - lhs;
    5516
    5517 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
    5518 * it to zero
    5519 */
    5520 if( !SCIPisPositive(scip, slack) )
    5521 slack = 0.0;
    5522
    5523 alpha = val * (ub - lb);
    5524 assert(!SCIPisNegative(scip, alpha));
    5525
    5526 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
    5527 {
    5528 SCIP_Real newlb;
    5529
    5530 /* compute new lower bound */
    5531 newlb = ub - (slack / val);
    5532
    5533 SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_LHS, newlb, lb, cutoff, nchgbds, force) );
    5534
    5535 if( *cutoff )
    5536 {
    5537 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
    5538 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
    5539
    5540 return SCIP_OKAY;
    5541 }
    5542 }
    5543 }
    5544 }
    5545 else
    5546 {
    5547 /* check, if we can tighten the variable's lower bound */
    5548 if( !SCIPisInfinity(scip, rhs) )
    5549 {
    5550 SCIP_Real slack;
    5551 SCIP_Real alpha;
    5552
    5553 /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
    5554 assert(consdata->validminact);
    5555
    5556 /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
    5557 if( SCIPisFeasLT(scip, rhs, QUAD_TO_DBL(consdata->minactivity)) )
    5558 {
    5559 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
    5560 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->minactivity), rhs);
    5561
    5562 *cutoff = TRUE;
    5563 return SCIP_OKAY;
    5564 }
    5565
    5566 slack = rhs - QUAD_TO_DBL(consdata->minactivity);
    5567
    5568 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
    5569 * it to zero
    5570 */
    5571 if( !SCIPisPositive(scip, slack) )
    5572 slack = 0.0;
    5573
    5574 alpha = val * (lb - ub);
    5575 assert(!SCIPisNegative(scip, alpha));
    5576
    5577 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
    5578 {
    5579 SCIP_Real newlb;
    5580
    5581 /* compute new lower bound */
    5582 newlb = ub + slack / val;
    5583
    5584 SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_RHS, newlb, lb, cutoff, nchgbds, force) );
    5585
    5586 if( *cutoff )
    5587 {
    5588 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
    5589 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
    5590
    5591 return SCIP_OKAY;
    5592 }
    5593 /* collect the new lower bound which is needed for the upper bound computation */
    5594 lb = SCIPvarGetLbLocal(var);
    5595 }
    5596 }
    5597
    5598 /* check, if we can tighten the variable's upper bound */
    5599 if( !SCIPisInfinity(scip, -lhs) )
    5600 {
    5601 SCIP_Real slack;
    5602 SCIP_Real alpha;
    5603
    5604 /* make sure the max activity is reliable */
    5605 if( !consdata->validmaxact )
    5606 {
    5608 }
    5609 assert(consdata->validmaxact);
    5610
    5611 /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
    5612 if( SCIPisFeasLT(scip, QUAD_TO_DBL(consdata->maxactivity), lhs) )
    5613 {
    5614 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
    5615 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->maxactivity), lhs);
    5616
    5617 *cutoff = TRUE;
    5618 return SCIP_OKAY;
    5619 }
    5620
    5621 slack = QUAD_TO_DBL(consdata->maxactivity) - lhs;
    5622
    5623 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
    5624 * it to zero
    5625 */
    5626 if( !SCIPisPositive(scip, slack) )
    5627 slack = 0.0;
    5628
    5629 alpha = val * (lb - ub);
    5630 assert(!SCIPisNegative(scip, alpha));
    5631
    5632 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
    5633 {
    5634 SCIP_Real newub;
    5635
    5636 /* compute new upper bound */
    5637 newub = lb - (slack / val);
    5638
    5639 SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_LHS, newub, ub, cutoff, nchgbds, force) );
    5640
    5641 if( *cutoff )
    5642 {
    5643 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
    5644 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
    5645
    5646 return SCIP_OKAY;
    5647 }
    5648 }
    5649 }
    5650 }
    5651
    5652 return SCIP_OKAY;
    5653}
    5654
    5655/** analyzes conflicting bounds on given ranged row constraint, and adds conflict constraint to problem */
    5656static
    5658 SCIP* scip, /**< SCIP data structure */
    5659 SCIP_CONS* cons, /**< conflict detecting constraint */
    5660 SCIP_VAR** vars, /**< variables reasoning the infeasibility */
    5661 int nvars, /**< number of variables reasoning the infeasibility */
    5662 SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
    5663 SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
    5664 )
    5665{
    5666#ifndef NDEBUG
    5667 SCIP_CONSDATA* consdata;
    5668
    5669 assert(scip != NULL);
    5670 assert(cons != NULL);
    5671
    5672 consdata = SCIPconsGetData(cons);
    5673 assert(consdata != NULL);
    5674 assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
    5675#endif
    5676
    5677 /* conflict analysis can only be applied in solving stage and if it is turned on */
    5679 return SCIP_OKAY;
    5680
    5681 /* initialize conflict analysis */
    5683
    5684 /* add the conflicting fixed variables of this ranged row constraint to conflict candidate queue */
    5686
    5687 /* add reasoning variables to conflict candidate queue which led to the conflict */
    5688 SCIP_CALL( addConflictReasonVars(scip, vars, nvars, var, bound) );
    5689
    5690 /* analyze the conflict */
    5692
    5693 return SCIP_OKAY;
    5694}
    5695
    5696/** propagate ranged rows
    5697 *
    5698 * Check ranged rows for possible solutions, possibly detect infeasibility, fix variables due to having only one possible
    5699 * solution, tighten bounds if having only two possible solutions or add constraints which propagate a subset of
    5700 * variables better.
    5701 *
    5702 * Example:
    5703 * c1: 12 x1 + 9 x2 - x3 = 0 with x1, x2 free and 1 <= x3 <= 2
    5704 *
    5705 * x3 needs to be a multiple of 3, so the instance is infeasible.
    5706 *
    5707 * Example:
    5708 * c1: 12 x1 + 9 x2 - x3 = 1 with x1, x2 free and 1 <= x3 <= 2
    5709 *
    5710 * The only possible value for x3 is 2, so the variable will be fixed.
    5711 *
    5712 * @todo add holes if possible
    5713 */
    5714static
    5716 SCIP* scip, /**< SCIP data structure */
    5717 SCIP_CONS* cons, /**< linear constraint */
    5718 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
    5719 int* nfixedvars, /**< pointer to count number of fixed variables */
    5720 int* nchgbds, /**< pointer to count the number of bound changes */
    5721 int* naddconss /**< pointer to count number of added constraints */
    5722 )
    5723{
    5724 SCIP_CONSHDLRDATA* conshdlrdata;
    5725 SCIP_CONSHDLR* conshdlr;
    5726 SCIP_CONSDATA* consdata;
    5727 SCIP_VAR** infcheckvars;
    5728 SCIP_Real* infcheckvals;
    5729 SCIP_Real minactinfvars;
    5730 SCIP_Real maxactinfvars;
    5731 SCIP_Real lb;
    5732 SCIP_Real ub;
    5733 SCIP_Real feastol;
    5734 SCIP_Real fixedact;
    5735 SCIP_Real lhs;
    5736 SCIP_Real rhs;
    5737 SCIP_Real absminbincoef;
    5738 SCIP_Longint gcd;
    5739 SCIP_Longint gcdtmp;
    5740 SCIP_Bool minactinfvarsinvalid;
    5741 SCIP_Bool maxactinfvarsinvalid;
    5742 SCIP_Bool possiblegcd;
    5743 SCIP_Bool gcdisone;
    5744 SCIP_Bool addartconss;
    5745 int ninfcheckvars;
    5746 int nunfixedvars;
    5747 int nfixedconsvars;
    5748 int ncontvars;
    5749 int pos;
    5750 int v;
    5751
    5752 assert(scip != NULL);
    5753 assert(cons != NULL);
    5754 assert(cutoff != NULL);
    5755 assert(nfixedvars != NULL);
    5756 assert(nchgbds != NULL);
    5757 assert(naddconss != NULL);
    5758
    5759 /* modifiable constraint can be changed so we do not have all necessary information */
    5760 if( SCIPconsIsModifiable(cons) )
    5761 return SCIP_OKAY;
    5762
    5763 consdata = SCIPconsGetData(cons);
    5764 assert(consdata != NULL);
    5765
    5766 /* we already did full ranged row propagation */
    5767 if( consdata->rangedrowpropagated == 2 )
    5768 return SCIP_OKAY;
    5769
    5770 /* at least three variables are needed */
    5771 if( consdata->nvars < 3 )
    5772 return SCIP_OKAY;
    5773
    5774 /* do nothing on normal inequalities */
    5775 if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
    5776 return SCIP_OKAY;
    5777
    5778 /* get constraint handler data */
    5779 conshdlr = SCIPconsGetHdlr(cons);
    5780 assert(conshdlr != NULL);
    5781 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    5782 assert(conshdlrdata != NULL);
    5783
    5784 addartconss = conshdlrdata->rangedrowartcons && SCIPgetDepth(scip) < 1 && !SCIPinProbing(scip) && !SCIPinRepropagation(scip);
    5785
    5786 /* we may add artificial constraints */
    5787 if( addartconss )
    5788 consdata->rangedrowpropagated = 2;
    5789 /* we are not allowed to add artificial constraints during propagation; if nothing changed on this constraint since
    5790 * the last rangedrowpropagation, we can stop; otherwise, we mark this constraint to be rangedrowpropagated without
    5791 * artificial constraints
    5792 */
    5793 else
    5794 {
    5795 if( consdata->rangedrowpropagated > 0 )
    5796 return SCIP_OKAY;
    5797
    5798 consdata->rangedrowpropagated = 1;
    5799 }
    5800
    5801 fixedact = 0;
    5802 nfixedconsvars = 0;
    5803
    5804 /* calculate fixed activity and number of fixed variables */
    5805 for( v = consdata->nvars - 1; v >= 0; --v )
    5806 {
    5807 /* all zero coefficients should be eliminated */
    5808 assert(!SCIPisZero(scip, consdata->vals[v]));
    5809
    5810 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
    5811 {
    5812 fixedact += SCIPvarGetLbLocal(consdata->vars[v]) * consdata->vals[v];
    5813 ++nfixedconsvars;
    5814 }
    5815 }
    5816
    5817 /* do not work with huge fixed activities */
    5818 if( SCIPisHugeValue(scip, REALABS(fixedact)) )
    5819 return SCIP_OKAY;
    5820
    5821 /* compute lhs and rhs for unfixed variables only and get number of unfixed variables */
    5822 assert(!SCIPisInfinity(scip, -fixedact) && !SCIPisInfinity(scip, fixedact));
    5823 lhs = consdata->lhs - fixedact;
    5824 rhs = consdata->rhs - fixedact;
    5825 nunfixedvars = consdata->nvars - nfixedconsvars;
    5826
    5827 /* allocate temporary memory for variables and coefficients which may lead to infeasibility */
    5828 SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvars, nunfixedvars) );
    5829 SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvals, nunfixedvars) );
    5830
    5831 absminbincoef = SCIP_REAL_MAX;
    5832 ncontvars = 0;
    5833 gcdisone = TRUE;
    5834 possiblegcd = TRUE;
    5835
    5836 /* we now partition all unfixed variables in two groups:
    5837 *
    5838 * The first one contains all integral variables with integral coefficient so that all variables in this group will
    5839 * have a gcd greater than 1. This group will be implicitly given.
    5840 *
    5841 * The second group will contain all left unfixed variables and will be saved as infcheckvars with corresponding
    5842 * coefficients as infcheckvals. The order of these variables should be the same as in the consdata object.
    5843 */
    5844
    5845 /* first find integral variables with integral coefficient greater than 1, thereby collecting all other unfixed
    5846 * variables
    5847 */
    5848 ninfcheckvars = 0;
    5849 v = -1;
    5850 pos = -1;
    5851 do
    5852 {
    5853 ++v;
    5854
    5855 /* partition the variables, do not change the order of collection, because it might be used later on */
    5856 while( v < consdata->nvars && ( !SCIPvarIsIntegral(consdata->vars[v])
    5857 || !SCIPisIntegral(scip, consdata->vals[v]) || SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0) ) )
    5858 {
    5859 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
    5860 {
    5861 if( !SCIPvarIsIntegral(consdata->vars[v]) )
    5862 ++ncontvars;
    5863 else if( SCIPvarIsBinary(consdata->vars[v]) )
    5864 {
    5865 SCIP_Real absval;
    5866
    5867 absval = REALABS(consdata->vals[v]);
    5868
    5869 if( absminbincoef > absval )
    5870 absminbincoef = absval;
    5871 }
    5872
    5873 gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
    5874 possiblegcd = FALSE;
    5875 infcheckvars[ninfcheckvars] = consdata->vars[v];
    5876 infcheckvals[ninfcheckvars] = consdata->vals[v];
    5877 ++ninfcheckvars;
    5878
    5879 if( pos == -1 )
    5880 pos = v;
    5881 }
    5882 ++v;
    5883 }
    5884 }
    5885 while( v < consdata->nvars && SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) );
    5886
    5887 /* if the first group of variables is empty, we stop */
    5888 /* @todo try to propagate/split up a constraint of the form:
    5889 * x_1 + ... + x_m + a_1*y_1 + ... + a_n*y_n = k + c,
    5890 * with k \in Z, c \in (d,d + 1], d \in Z, (a_1*y_1 + ... + a_n*y_n) \in (c-1 + d,d + 1]
    5891 */
    5892 if( v == consdata->nvars )
    5893 goto TERMINATE;
    5894
    5895 /* we need at least two non-continuous variables */
    5896 if( ncontvars + 2 > nunfixedvars )
    5897 goto TERMINATE;
    5898
    5899 assert(!SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])));
    5900 assert(SCIPvarIsIntegral(consdata->vars[v]) && SCIPisIntegral(scip, consdata->vals[v]) && REALABS(consdata->vals[v]) > 1.5);
    5901
    5902 feastol = SCIPfeastol(scip);
    5903
    5904 gcd = (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol);
    5905 assert(gcd >= 2);
    5906
    5907 /* go on to partition the variables, do not change the order of collection, because it might be used later on;
    5908 * calculate gcd over the first part of variables */
    5909 for( ; v < consdata->nvars; ++v )
    5910 {
    5911 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
    5912 continue;
    5913
    5914 if( SCIPvarIsBinary(consdata->vars[v]) )
    5915 {
    5916 SCIP_Real absval;
    5917
    5918 absval = REALABS(consdata->vals[v]);
    5919
    5920 if( absminbincoef > absval )
    5921 absminbincoef = absval;
    5922 }
    5923
    5924 if( !SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v])
    5925 || SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0) )
    5926 {
    5927 if( !SCIPvarIsIntegral(consdata->vars[v]) )
    5928 ++ncontvars;
    5929
    5930 gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
    5931 possiblegcd = FALSE;
    5932 infcheckvars[ninfcheckvars] = consdata->vars[v];
    5933 infcheckvals[ninfcheckvars] = consdata->vals[v];
    5934
    5935 ++ninfcheckvars;
    5936
    5937 if( pos == -1 )
    5938 pos = v;
    5939 }
    5940 else
    5941 {
    5942 assert(REALABS(consdata->vals[v]) > 1.5);
    5943
    5944 gcdtmp = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol));
    5945 assert(gcdtmp >= 1);
    5946
    5947 if( gcdtmp == 1 )
    5948 {
    5949 infcheckvars[ninfcheckvars] = consdata->vars[v];
    5950 infcheckvals[ninfcheckvars] = consdata->vals[v];
    5951
    5952 ++ninfcheckvars;
    5953
    5954 if( pos == -1 )
    5955 pos = v;
    5956 }
    5957 else
    5958 gcd = gcdtmp;
    5959 }
    5960 }
    5961 assert(gcd >= 2);
    5962
    5963 /* it should not happen that all variables are of integral type and have a gcd >= 2, this should be done by
    5964 * normalizeCons() */
    5965 if( ninfcheckvars == 0 )
    5966 goto TERMINATE;
    5967
    5968 assert(pos >= 0);
    5969
    5970 minactinfvarsinvalid = FALSE;
    5971 maxactinfvarsinvalid = FALSE;
    5972 maxactinfvars = 0.0;
    5973 minactinfvars = 0.0;
    5974
    5975 /* calculate activities over all infcheckvars */
    5976 for( v = ninfcheckvars - 1; v >= 0; --v )
    5977 {
    5978 lb = SCIPvarGetLbLocal(infcheckvars[v]);
    5979 ub = SCIPvarGetUbLocal(infcheckvars[v]);
    5980
    5981 if( SCIPisInfinity(scip, -lb) )
    5982 {
    5983 if( infcheckvals[v] < 0.0 )
    5984 maxactinfvarsinvalid = TRUE;
    5985 else
    5986 minactinfvarsinvalid = TRUE;
    5987 }
    5988 else
    5989 {
    5990 if( infcheckvals[v] < 0.0 )
    5991 maxactinfvars += infcheckvals[v] * lb;
    5992 else
    5993 minactinfvars += infcheckvals[v] * lb;
    5994 }
    5995
    5996 if( SCIPisInfinity(scip, ub) )
    5997 {
    5998 if( infcheckvals[v] > 0.0 )
    5999 maxactinfvarsinvalid = TRUE;
    6000 else
    6001 minactinfvarsinvalid = TRUE;
    6002 }
    6003 else
    6004 {
    6005 if( infcheckvals[v] > 0.0 )
    6006 maxactinfvars += infcheckvals[v] * ub;
    6007 else
    6008 minactinfvars += infcheckvals[v] * ub;
    6009 }
    6010
    6011 /* better abort on to big values */
    6012 if( SCIPisHugeValue(scip, -minactinfvars) )
    6013 minactinfvarsinvalid = TRUE;
    6014 if( SCIPisHugeValue(scip, maxactinfvars) )
    6015 maxactinfvarsinvalid = TRUE;
    6016
    6017 if( minactinfvarsinvalid || maxactinfvarsinvalid )
    6018 goto TERMINATE;
    6019 }
    6020 assert(!minactinfvarsinvalid && !maxactinfvarsinvalid);
    6021
    6022 SCIPdebugMsg(scip, "minactinfvarsinvalid = %u, minactinfvars = %g, maxactinfvarsinvalid = %u, maxactinfvars = %g, gcd = %lld, ninfcheckvars = %d, ncontvars = %d\n",
    6023 minactinfvarsinvalid, minactinfvars, maxactinfvarsinvalid, maxactinfvars, gcd, ninfcheckvars, ncontvars);
    6024
    6025 /* @todo maybe we took the wrong variables as infcheckvars - we could try to exchange integer variables */
    6026 /* @todo if minactinfvarsinvalid or maxactinfvarsinvalid are true, try to exchange both partitions to maybe get valid
    6027 * activities */
    6028 /* @todo calculate minactivity and maxactivity for all non-intcheckvars, and use this for better bounding,
    6029 * !!!note!!!
    6030 * that therefore the conflict variables in addConflictFixedVars() need to be extended by all variables which
    6031 * are not at their global bound
    6032 */
    6033
    6034 /* check if between left hand side and right hand side there exists a feasible point, if not, the constraint leads to
    6035 * infeasibility */
    6036 if( !SCIPisIntegral(scip, (lhs - maxactinfvars) / gcd) &&
    6037 SCIPisGT(scip, SCIPceil(scip, (lhs - maxactinfvars) / gcd) * gcd, rhs - minactinfvars) )
    6038 {
    6039 SCIPdebugMsg(scip, "no feasible value exists, constraint <%s> leads to infeasibility", SCIPconsGetName(cons));
    6041
    6042 /* start conflict analysis */
    6043 /* @todo improve conflict analysis by adding relaxed bounds */
    6044 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
    6045
    6046 *cutoff = TRUE;
    6047 }
    6048 else if( ncontvars == 0 )
    6049 {
    6050 SCIP_Longint gcdinfvars = -1;
    6051
    6052 /* check for gcd over all infcheckvars */
    6053 if( possiblegcd )
    6054 {
    6055 v = ninfcheckvars - 1;
    6056 gcdinfvars = (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol);
    6057 assert(gcdinfvars >= 2);
    6058
    6059 for( ; v >= 0 && gcdinfvars >= 2; --v )
    6060 {
    6061 gcdinfvars = SCIPcalcGreComDiv(gcdinfvars, (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol));
    6062 }
    6063 }
    6064 else if( gcdisone )
    6065 gcdinfvars = 1;
    6066
    6067 SCIPdebugMsg(scip, "gcdinfvars =%lld, possiblegcd = %u\n", gcdinfvars, possiblegcd);
    6068
    6069 /* compute solutions for this ranged row, if all variables are of integral type with integral coefficients */
    6070 if( gcdinfvars >= 1 )
    6071 {
    6072 SCIP_Real value;
    6073 SCIP_Real value2;
    6074 SCIP_Real minvalue = SCIP_INVALID;
    6075 SCIP_Real maxvalue = SCIP_INVALID;
    6076 int nsols = 0;
    6077
    6078 value = SCIPceil(scip, minactinfvars - SCIPfeastol(scip));
    6079
    6080 /* check how many possible solutions exist */
    6081 while( SCIPisLE(scip, value, maxactinfvars) )
    6082 {
    6083 value2 = value + gcd * (SCIPceil(scip, (lhs - value) / gcd));
    6084
    6085 /* value2 might violate lhs due to numerics, in this case take the next divisible number */
    6086 if( !SCIPisGE(scip, value2, lhs) )
    6087 {
    6088 value2 += gcd;
    6089 }
    6090
    6091 if( SCIPisLE(scip, value2, rhs) )
    6092 {
    6093 ++nsols;
    6094
    6095 /* early termination if we found more than two solutions */
    6096 if( nsols == 3 )
    6097 break;
    6098
    6099 if( minvalue == SCIP_INVALID ) /*lint !e777*/
    6100 minvalue = value;
    6101
    6102 maxvalue = value;
    6103 }
    6104 value += gcdinfvars;
    6105 }
    6106 assert(nsols < 2 || minvalue <= maxvalue);
    6107
    6108 /* determine last possible solution for better bounding */
    6109 if( nsols == 3 )
    6110 {
    6111#ifndef NDEBUG
    6112 SCIP_Real secondsolval = maxvalue;
    6113#endif
    6114 value = SCIPfloor(scip, maxactinfvars + SCIPfeastol(scip));
    6115
    6116 /* check how many possible solutions exist */
    6117 while( SCIPisGE(scip, value, minactinfvars) )
    6118 {
    6119 value2 = value + gcd * (SCIPfloor(scip, (rhs - value) / gcd));
    6120
    6121 /* value2 might violate rhs due to numerics, in this case take the next divisible number */
    6122 if( !SCIPisLE(scip, value2, rhs) )
    6123 {
    6124 value2 -= gcd;
    6125 }
    6126
    6127 if( SCIPisGE(scip, value2, lhs) )
    6128 {
    6129 maxvalue = value;
    6130 assert(maxvalue > minvalue);
    6131 break;
    6132 }
    6133 value -= gcdinfvars;
    6134 }
    6135 assert(maxvalue > secondsolval);
    6136 }
    6137
    6138 SCIPdebugMsg(scip, "here nsols %s %d, minsolvalue = %g, maxsolvalue = %g, ninfcheckvars = %d, nunfixedvars = %d\n",
    6139 nsols > 2 ? ">=" : "=", nsols, minvalue, maxvalue, ninfcheckvars, nunfixedvars);
    6140
    6141 /* no possible solution found */
    6142 if( nsols == 0 )
    6143 {
    6144 SCIPdebugMsg(scip, "gcdinfvars = %lld, gcd = %lld, correctedlhs = %g, correctedrhs = %g\n",
    6145 gcdinfvars, gcd, lhs, rhs);
    6146 SCIPdebugMsg(scip, "no solution found; constraint <%s> leads to infeasibility\n", SCIPconsGetName(cons));
    6148
    6149 /* start conflict analysis */
    6150 /* @todo improve conflict analysis by adding relaxed bounds */
    6151 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
    6152
    6153 *cutoff = TRUE;
    6154 }
    6155 /* if only one solution exists, we can extract a new constraint or fix variables */
    6156 else if( nsols == 1 )
    6157 {
    6158 assert(minvalue == maxvalue); /*lint !e777*/
    6159
    6160 /* we can fix the only variable in our second set of variables */
    6161 if( ninfcheckvars == 1 )
    6162 {
    6163 SCIP_Bool fixed;
    6164
    6165 assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
    6166
    6167 SCIPdebugMsg(scip, "fixing single variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
    6168 SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]),
    6169 SCIPvarGetUbLocal(infcheckvars[0]), maxvalue/infcheckvals[0]);
    6170
    6171 /* fix variable to only possible value */
    6172 SCIP_CALL( SCIPinferVarFixCons(scip, infcheckvars[0], maxvalue/infcheckvals[0], cons,
    6173 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &fixed) );
    6174
    6175 if( *cutoff )
    6176 {
    6177 /* start conflict analysis */
    6178 /* @todo improve conflict analysis by adding relaxed bounds */
    6179 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
    6180 }
    6181
    6182 if( fixed )
    6183 ++(*nfixedvars);
    6184 }
    6185 else
    6186 {
    6187 /* check for exactly one unfixed variable which is not part of the infcheckvars */
    6188 if( ninfcheckvars == nunfixedvars - 1 )
    6189 {
    6191 SCIP_Bool foundvar = FALSE;
    6192 SCIP_Bool fixed;
    6193 int w = 0;
    6194
    6195 assert(ninfcheckvars > 0);
    6196
    6197 /* find variable which is not an infcheckvar and fix it */
    6198 for( v = 0; v < consdata->nvars - 1; ++v )
    6199 {
    6200 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
    6201 {
    6202 if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
    6203 {
    6204#ifndef NDEBUG
    6205 int v2 = v + 1;
    6206 int w2 = w;
    6207
    6208 assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
    6209
    6210 for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
    6211 {
    6212 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
    6213 continue;
    6214
    6215 assert(consdata->vars[v2] == infcheckvars[w2]);
    6216 ++w2;
    6217 }
    6218 assert(w2 == ninfcheckvars);
    6219#endif
    6220 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
    6221
    6222 foundvar = TRUE;
    6223
    6224 if( consdata->vals[v] < 0 )
    6225 {
    6226 bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
    6227 }
    6228 else
    6229 {
    6230 bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
    6231 }
    6232
    6233 SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
    6234 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
    6235 SCIPvarGetUbLocal(consdata->vars[v]), bound);
    6236
    6237 /* fix variable to only possible value */
    6238 SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
    6239 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
    6240
    6241 if( *cutoff )
    6242 {
    6243 /* start conflict analysis */
    6244 /* @todo improve conflict analysis by adding relaxed bounds */
    6245 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
    6246 consdata->vars[v], bound) );
    6247 }
    6248
    6249 if( fixed )
    6250 ++(*nfixedvars);
    6251
    6252 break;
    6253 }
    6254
    6255 ++w;
    6256 }
    6257 }
    6258
    6259 /* maybe last variable was the not infcheckvar */
    6260 if( !foundvar )
    6261 {
    6262 assert(v == consdata->nvars - 1);
    6263 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
    6264
    6265 if( consdata->vals[v] < 0 )
    6266 {
    6267 bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
    6268 }
    6269 else
    6270 {
    6271 bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
    6272 }
    6273
    6274 SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
    6275 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
    6276 SCIPvarGetUbLocal(consdata->vars[v]), bound);
    6277
    6278 /* fix variable to only possible value */
    6279 SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
    6280 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
    6281
    6282 if( *cutoff )
    6283 {
    6284 /* start conflict analysis */
    6285 /* @todo improve conflict analysis by adding relaxed bounds */
    6286 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
    6287 consdata->vars[v], bound) );
    6288 }
    6289
    6290 if( fixed )
    6291 ++(*nfixedvars);
    6292 }
    6293 }
    6294 else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
    6295 {
    6296 /* aggregation possible if we have two variables, but this will be done later on */
    6297 SCIP_CONS* newcons;
    6298 char name[SCIP_MAXSTRLEN];
    6299
    6300 /* create, add, and release new artificial constraint */
    6301 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
    6302 ++conshdlrdata->naddconss;
    6303
    6304 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
    6305
    6306 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals,
    6307 maxvalue, maxvalue, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
    6308 SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
    6309
    6310 SCIPdebugPrintCons(scip, newcons, NULL);
    6311
    6312 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    6313
    6314 ++(*naddconss);
    6315 }
    6316 }
    6317 }
    6318 /* at least two solutions */
    6319 else
    6320 {
    6321 /* @todo If we found more than one solution, can we reduce domains due to dualpresolving? */
    6322
    6323 /* only one variable in the second set, so we can bound this variables */
    6324 if( ninfcheckvars == 1 )
    6325 {
    6326 SCIP_Bool tightened;
    6327 SCIP_Real newlb;
    6328 SCIP_Real newub;
    6329
    6330 assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
    6331
    6332 if( infcheckvals[0] < 0 )
    6333 {
    6334 newlb = maxvalue/infcheckvals[0];
    6335 newub = minvalue/infcheckvals[0];
    6336 }
    6337 else
    6338 {
    6339 newlb = minvalue/infcheckvals[0];
    6340 newub = maxvalue/infcheckvals[0];
    6341 }
    6342 assert(newlb < newub);
    6343
    6344 if( newlb > SCIPvarGetLbLocal(infcheckvars[0]) )
    6345 {
    6346 /* update lower bound of variable */
    6347 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
    6348 SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]), newlb);
    6349
    6350 /* tighten variable lower bound to minimal possible value */
    6351 SCIP_CALL( SCIPinferVarLbCons(scip, infcheckvars[0], newlb, cons,
    6352 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
    6353
    6354 if( *cutoff )
    6355 {
    6356 /* start conflict analysis */
    6357 /* @todo improve conflict analysis by adding relaxed bounds */
    6358 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
    6359 }
    6360
    6361 if( tightened )
    6362 ++(*nchgbds);
    6363 }
    6364
    6365 if( newub < SCIPvarGetUbLocal(infcheckvars[0]) )
    6366 {
    6367 /* update upper bound of variable */
    6368 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
    6369 SCIPvarGetName(infcheckvars[0]), SCIPvarGetUbLocal(infcheckvars[0]), newub);
    6370
    6371 /* tighten variable upper bound to maximal possible value */
    6372 SCIP_CALL( SCIPinferVarUbCons(scip, infcheckvars[0], newub, cons,
    6373 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
    6374
    6375 if( *cutoff )
    6376 {
    6377 /* start conflict analysis */
    6378 /* @todo improve conflict analysis by adding relaxed bounds */
    6379 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
    6380 }
    6381
    6382 if( tightened )
    6383 ++(*nchgbds);
    6384 }
    6385 }
    6386 /* check if we have only one variable not in infcheckvars, if so we can tighten this variable */
    6387 else if( ninfcheckvars == nunfixedvars - 1 )
    6388 {
    6389 SCIP_Bool foundvar = FALSE;
    6390 SCIP_Bool tightened;
    6391 SCIP_Real newlb;
    6392 SCIP_Real newub;
    6393 int w = 0;
    6394
    6395 assert(ninfcheckvars > 0);
    6396 assert(minvalue < maxvalue);
    6397
    6398 /* find variable which is not an infcheckvar and fix it */
    6399 for( v = 0; v < consdata->nvars - 1; ++v )
    6400 {
    6401 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
    6402 {
    6403 if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
    6404 {
    6405#ifndef NDEBUG
    6406 int v2 = v + 1;
    6407 int w2 = w;
    6408
    6409 assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
    6410
    6411 for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
    6412 {
    6413 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
    6414 continue;
    6415
    6416 assert(consdata->vars[v2] == infcheckvars[w2]);
    6417 ++w2;
    6418 }
    6419 assert(w2 == ninfcheckvars);
    6420#endif
    6421
    6422 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
    6423 foundvar = TRUE;
    6424
    6425 if( consdata->vals[v] < 0 )
    6426 {
    6427 newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
    6428 newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
    6429 }
    6430 else
    6431 {
    6432 newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
    6433 newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
    6434 }
    6435 assert(SCIPisLE(scip, newlb, newub));
    6436
    6437 if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
    6438 {
    6439 /* update lower bound of variable */
    6440 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
    6441 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
    6442
    6443 /* tighten variable lower bound to minimal possible value */
    6444 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
    6445 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
    6446
    6447 if( *cutoff )
    6448 {
    6449 /* start conflict analysis */
    6450 /* @todo improve conflict analysis by adding relaxed bounds */
    6451 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
    6452 consdata->vars[v], newlb) );
    6453 }
    6454
    6455 if( tightened )
    6456 ++(*nchgbds);
    6457 }
    6458
    6459 if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
    6460 {
    6461 /* update upper bound of variable */
    6462 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
    6463 SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
    6464
    6465 /* tighten variable upper bound to maximal possible value */
    6466 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
    6467 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
    6468
    6469 if( *cutoff )
    6470 {
    6471 /* start conflict analysis */
    6472 /* @todo improve conflict analysis by adding relaxed bounds */
    6473 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
    6474 consdata->vars[v], newub) );
    6475 }
    6476
    6477 if( tightened )
    6478 ++(*nchgbds);
    6479 }
    6480
    6481 break;
    6482 }
    6483
    6484 ++w;
    6485 }
    6486 }
    6487
    6488 /* maybe last variable was the not infcheckvar */
    6489 if( !foundvar )
    6490 {
    6491 assert(v == consdata->nvars - 1);
    6492 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
    6493
    6494 if( consdata->vals[v] < 0 )
    6495 {
    6496 newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
    6497 newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
    6498 }
    6499 else
    6500 {
    6501 newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
    6502 newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
    6503 }
    6504 assert(SCIPisLE(scip, newlb, newub));
    6505
    6506 if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
    6507 {
    6508 /* update lower bound of variable */
    6509 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
    6510 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
    6511
    6512 /* tighten variable lower bound to minimal possible value */
    6513 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
    6514 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
    6515
    6516 if( *cutoff )
    6517 {
    6518 /* start conflict analysis */
    6519 /* @todo improve conflict analysis by adding relaxed bounds */
    6520 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newlb) );
    6521 }
    6522
    6523 if( tightened )
    6524 ++(*nchgbds);
    6525 }
    6526
    6527 if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
    6528 {
    6529 /* update upper bound of variable */
    6530 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
    6531 SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
    6532
    6533 /* tighten variable upper bound to maximal possible value */
    6534 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
    6535 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
    6536
    6537 if( *cutoff )
    6538 {
    6539 /* start conflict analysis */
    6540 /* @todo improve conflict analysis by adding relaxed bounds */
    6541 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newub) );
    6542 }
    6543
    6544 if( tightened )
    6545 ++(*nchgbds);
    6546 }
    6547 }
    6548 }
    6549 /* at least two solutions and more than one variable, so we add a new constraint which bounds the feasible
    6550 * region for our infcheckvars, if possible
    6551 */
    6552 else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
    6553 {
    6554 SCIP_CONS* newcons;
    6555 char name[SCIP_MAXSTRLEN];
    6556 SCIP_Real newlhs;
    6557 SCIP_Real newrhs;
    6558
    6559 assert(maxvalue > minvalue);
    6560
    6561 if( SCIPisGT(scip, minvalue, minactinfvars) )
    6562 newlhs = minvalue;
    6563 else
    6564 newlhs = -SCIPinfinity(scip);
    6565
    6566 if( SCIPisLT(scip, maxvalue, maxactinfvars) )
    6567 newrhs = maxvalue;
    6568 else
    6569 newrhs = SCIPinfinity(scip);
    6570
    6571 if( !SCIPisInfinity(scip, -newlhs) || !SCIPisInfinity(scip, newrhs) )
    6572 {
    6573 /* create, add, and release new artificial constraint */
    6574 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons1_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
    6575 ++conshdlrdata->naddconss;
    6576
    6577 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
    6578
    6579 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
    6581 SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
    6582
    6583 SCIPdebugPrintCons(scip, newcons, NULL);
    6584 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    6585
    6586 ++(*naddconss);
    6587 }
    6588 /* @todo maybe add constraint for all variables which are not infcheckvars, lhs should be minvalue, rhs
    6589 * should be maxvalue */
    6590 }
    6591 }
    6592 }
    6593 }
    6594 else if( addartconss && ncontvars < ninfcheckvars )
    6595 {
    6596 SCIP_Real maxact = 0.0;
    6597 SCIP_Real minact = 0.0;
    6598 int w = 0;
    6599
    6600 /* compute activities of non-infcheckvars */
    6601 for( v = 0; v < consdata->nvars; ++v )
    6602 {
    6603 if( w < ninfcheckvars && consdata->vars[v] == infcheckvars[w] )
    6604 {
    6605 ++w;
    6606 continue;
    6607 }
    6608
    6609 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
    6610 {
    6611 if( SCIPvarIsBinary(consdata->vars[v]) )
    6612 {
    6613 if( consdata->vals[v] > 0.0 )
    6614 maxact += consdata->vals[v];
    6615 else
    6616 minact += consdata->vals[v];
    6617 }
    6618 else
    6619 {
    6620 SCIP_Real tmpval;
    6621
    6622 assert(SCIPvarIsIntegral(consdata->vars[v]));
    6623
    6624 if( consdata->vals[v] > 0.0 )
    6625 {
    6626 tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
    6627
    6628 if( SCIPisHugeValue(scip, -tmpval) )
    6629 break;
    6630
    6631 minact += tmpval;
    6632
    6633 tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
    6634
    6635 if( SCIPisHugeValue(scip, tmpval) )
    6636 break;
    6637
    6638 maxact += tmpval;
    6639 }
    6640 else
    6641 {
    6642 tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
    6643
    6644 if( SCIPisHugeValue(scip, -tmpval) )
    6645 break;
    6646
    6647 minact += tmpval;
    6648
    6649 tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
    6650
    6651 if( SCIPisHugeValue(scip, tmpval) )
    6652 break;
    6653
    6654 maxact += tmpval;
    6655 }
    6656 }
    6657 }
    6658 }
    6659
    6660 if( v == consdata->nvars && !SCIPisHugeValue(scip, -minact) && !SCIPisHugeValue(scip, maxact) )
    6661 {
    6662 SCIP_CONS* newcons;
    6663 char name[SCIP_MAXSTRLEN];
    6664 SCIP_Real newlhs;
    6665 SCIP_Real newrhs;
    6666
    6667 assert(maxact > minact);
    6668 assert(w == ninfcheckvars);
    6669
    6670 newlhs = lhs - maxact;
    6671 newrhs = rhs - minact;
    6672 assert(newlhs < newrhs);
    6673
    6674 /* create, add, and release new artificial constraint */
    6675 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons2_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
    6676 ++conshdlrdata->naddconss;
    6677
    6678 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
    6679
    6680 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
    6682 SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
    6683
    6684 SCIPdebugPrintCons(scip, newcons, NULL);
    6685 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    6686
    6687 ++(*naddconss);
    6688 }
    6689 }
    6690
    6691 TERMINATE:
    6692 SCIPfreeBufferArray(scip, &infcheckvals);
    6693 SCIPfreeBufferArray(scip, &infcheckvars);
    6694
    6695 return SCIP_OKAY;
    6696}
    6697
    6698/** tightens bounds of a single variable due to activity bounds */
    6699static
    6701 SCIP* scip, /**< SCIP data structure */
    6702 SCIP_CONS* cons, /**< linear constraint */
    6703 int pos, /**< position of the variable in the vars array */
    6704 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
    6705 int* nchgbds, /**< pointer to count the total number of tightened bounds */
    6706 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
    6707 )
    6708{
    6709 SCIP_CONSDATA* consdata;
    6710 SCIP_VAR* var;
    6711 SCIP_Real val;
    6712 SCIP_Real lb;
    6713 SCIP_Real ub;
    6714 SCIP_Real minresactivity;
    6715 SCIP_Real maxresactivity;
    6716 SCIP_Real lhs;
    6717 SCIP_Real rhs;
    6718 SCIP_Bool infeasible;
    6719 SCIP_Bool tightened;
    6720 SCIP_Bool ismintight;
    6721 SCIP_Bool ismaxtight;
    6722 SCIP_Bool isminsettoinfinity;
    6723 SCIP_Bool ismaxsettoinfinity;
    6724
    6725 assert(scip != NULL);
    6726 assert(cons != NULL);
    6727 assert(cutoff != NULL);
    6728 assert(nchgbds != NULL);
    6729
    6730 /* we cannot tighten variables' bounds, if the constraint may be not complete */
    6731 if( SCIPconsIsModifiable(cons) )
    6732 return SCIP_OKAY;
    6733
    6734 consdata = SCIPconsGetData(cons);
    6735 assert(consdata != NULL);
    6736 assert(0 <= pos && pos < consdata->nvars);
    6737
    6738 *cutoff = FALSE;
    6739
    6740 var = consdata->vars[pos];
    6741
    6742 /* we cannot tighten bounds of multi-aggregated variables */
    6744 return SCIP_OKAY;
    6745
    6746 val = consdata->vals[pos];
    6747 lhs = consdata->lhs;
    6748 rhs = consdata->rhs;
    6749 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
    6750 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
    6751 assert(var != NULL);
    6752 assert(!SCIPisZero(scip, val));
    6753 assert(!SCIPisInfinity(scip, lhs));
    6754 assert(!SCIPisInfinity(scip, -rhs));
    6755
    6756 lb = SCIPvarGetLbLocal(var);
    6757 ub = SCIPvarGetUbLocal(var);
    6758 assert(SCIPisLE(scip, lb, ub));
    6759
    6760 if( val > 0.0 )
    6761 {
    6762 /* check, if we can tighten the variable's bounds reliably, therefore only consider sides which are small or
    6763 * relatively different to the residual activity bound to avoid cancellation leading to numerical difficulties
    6764 */
    6765 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && ismintight
    6766 && ( SCIPisLT(scip, ABS(rhs), 1.0) || !SCIPisEQ(scip, minresactivity / rhs, 1.0) ) )
    6767 {
    6768 SCIP_Real newub;
    6769
    6770 newub = (rhs - minresactivity)/val;
    6771
    6772 if( !SCIPisInfinity(scip, newub) &&
    6773 ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
    6774 {
    6775 SCIP_Bool activityunreliable;
    6776 activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
    6777
    6778 /* check minresactivities for reliability */
    6779 if( activityunreliable )
    6780 {
    6781 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
    6782 newub = (rhs - minresactivity)/val;
    6783 activityunreliable = SCIPisInfinity(scip, -minresactivity) ||
    6784 (!SCIPisUbBetter(scip, newub, lb, ub) && (!SCIPisFeasLT(scip, newub, ub) || !SCIPvarIsIntegral(var))
    6785 && (!force || !SCIPisLT(scip, newub, ub)));
    6786 }
    6787
    6788 if( !activityunreliable )
    6789 {
    6790 /* tighten upper bound */
    6791 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
    6792 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
    6793 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_RHS, pos), force,
    6794 &infeasible, &tightened) );
    6795 if( infeasible )
    6796 {
    6797 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
    6798 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
    6799
    6800 /* analyze conflict */
    6802
    6803 *cutoff = TRUE;
    6804 return SCIP_OKAY;
    6805 }
    6806 if( tightened )
    6807 {
    6808 ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
    6809 assert(SCIPisFeasLE(scip, ub, newub));
    6810 (*nchgbds)++;
    6811
    6812 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
    6813 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
    6814 }
    6815 }
    6816 }
    6817 }
    6818
    6819 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && ismaxtight
    6820 && ( SCIPisLT(scip, ABS(lhs), 1.0) || !SCIPisEQ(scip, maxresactivity / lhs, 1.0) ) )
    6821 {
    6822 SCIP_Real newlb;
    6823
    6824 newlb = (lhs - maxresactivity)/val;
    6825 if( !SCIPisInfinity(scip, -newlb) &&
    6826 ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
    6827 {
    6828 /* check maxresactivities for reliability */
    6829 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
    6830 {
    6831 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
    6832 newlb = (lhs - maxresactivity)/val;
    6833
    6834 if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisLbBetter(scip, newlb, lb, ub)
    6835 && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
    6836 && (!force || !SCIPisGT(scip, newlb, lb))) )
    6837 return SCIP_OKAY;
    6838 }
    6839
    6840 /* tighten lower bound */
    6841 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
    6842 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
    6843 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_LHS, pos), force,
    6844 &infeasible, &tightened) );
    6845 if( infeasible )
    6846 {
    6847 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
    6848 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
    6849
    6850 /* analyze conflict */
    6852
    6853 *cutoff = TRUE;
    6854 return SCIP_OKAY;
    6855 }
    6856 if( tightened )
    6857 {
    6858 lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
    6859 assert(SCIPisFeasGE(scip, lb, newlb));
    6860 (*nchgbds)++;
    6861 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
    6862 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
    6863 }
    6864 }
    6865 }
    6866 }
    6867 else
    6868 {
    6869 /* check, if we can tighten the variable's bounds reliably, therefore only consider sides which are small or
    6870 * relatively different to the residual activity bound to avoid cancellation leading to numerical difficulties
    6871 */
    6872 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && ismintight
    6873 && ( SCIPisLT(scip, ABS(rhs), 1.0) || !SCIPisEQ(scip, minresactivity / rhs, 1.0) ) )
    6874 {
    6875 SCIP_Real newlb;
    6876
    6877 newlb = (rhs - minresactivity)/val;
    6878 if( !SCIPisInfinity(scip, -newlb) &&
    6879 ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
    6880 {
    6881 SCIP_Bool activityunreliable;
    6882 activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
    6883 /* check minresactivities for reliability */
    6884 if( activityunreliable )
    6885 {
    6886 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
    6887 newlb = (rhs - minresactivity)/val;
    6888
    6889 activityunreliable = SCIPisInfinity(scip, -minresactivity)
    6890 || (!SCIPisLbBetter(scip, newlb, lb, ub) && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
    6891 && (!force || !SCIPisGT(scip, newlb, lb)));
    6892 }
    6893
    6894 if( !activityunreliable )
    6895 {
    6896 /* tighten lower bound */
    6897 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
    6898 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
    6899 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_RHS, pos), force,
    6900 &infeasible, &tightened) );
    6901 if( infeasible )
    6902 {
    6903 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
    6904 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
    6905
    6906 /* analyze conflict */
    6908
    6909 *cutoff = TRUE;
    6910 return SCIP_OKAY;
    6911 }
    6912 if( tightened )
    6913 {
    6914 lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
    6915 assert(SCIPisFeasGE(scip, lb, newlb));
    6916 (*nchgbds)++;
    6917 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
    6918 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
    6919 }
    6920 }
    6921 }
    6922 }
    6923
    6924 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && ismaxtight
    6925 && ( SCIPisLT(scip, ABS(lhs), 1.0) || !SCIPisEQ(scip, maxresactivity / lhs, 1.0) ) )
    6926 {
    6927 SCIP_Real newub;
    6928
    6929 newub = (lhs - maxresactivity)/val;
    6930 if( !SCIPisInfinity(scip, newub) &&
    6931 ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
    6932 {
    6933 /* check maxresactivities for reliability */
    6934 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
    6935 {
    6936 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
    6937 newub = (lhs - maxresactivity)/val;
    6938
    6939 if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisUbBetter(scip, newub, lb, ub)
    6940 && (!SCIPisFeasLT(scip, newub, ub) && !SCIPvarIsIntegral(var))
    6941 && (!force || !SCIPisLT(scip, newub, ub))) )
    6942 return SCIP_OKAY;
    6943 }
    6944
    6945 /* tighten upper bound */
    6946 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g], newub=%.15g\n",
    6947 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
    6948 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_LHS, pos), force,
    6949 &infeasible, &tightened) );
    6950 if( infeasible )
    6951 {
    6952 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
    6953 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
    6954
    6955 /* analyze conflict */
    6957
    6958 *cutoff = TRUE;
    6959 return SCIP_OKAY;
    6960 }
    6961 if( tightened )
    6962 {
    6963 ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
    6964 assert(SCIPisFeasLE(scip, ub, newub));
    6965 (*nchgbds)++;
    6966 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
    6967 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
    6968 }
    6969 }
    6970 }
    6971 }
    6972
    6973 return SCIP_OKAY;
    6974}
    6975
    6976#define MAXTIGHTENROUNDS 10
    6977
    6978/** tightens bounds of variables in constraint due to activity bounds */
    6979static
    6981 SCIP* scip, /**< SCIP data structure */
    6982 SCIP_CONS* cons, /**< linear constraint */
    6983 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
    6984 SCIP_Bool sortvars, /**< should variables be used in sorted order? */
    6985 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
    6986 int* nchgbds /**< pointer to count the total number of tightened bounds */
    6987 )
    6988{
    6989 SCIP_CONSDATA* consdata;
    6990 unsigned int tightenmode;
    6991 int nvars;
    6992 int nrounds;
    6993 int lastchange;
    6994 int oldnchgbds;
    6995#ifndef SCIP_DEBUG
    6996 int oldnchgbdstotal;
    6997#endif
    6998 int v;
    6999 SCIP_Bool force;
    7000 SCIP_Bool easycase;
    7001
    7002 assert(scip != NULL);
    7003 assert(cons != NULL);
    7004 assert(nchgbds != NULL);
    7005 assert(cutoff != NULL);
    7006
    7007 *cutoff = FALSE;
    7008
    7009 /* we cannot tighten variables' bounds, if the constraint may be not complete */
    7010 if( SCIPconsIsModifiable(cons) )
    7011 return SCIP_OKAY;
    7012
    7013 /* if a constraint was created after presolve, then it may hold fixed variables
    7014 * if there are even multi-aggregated variables, then we cannot do bound tightening on these
    7015 * thus, ensure here again that variable fixings have been applied
    7016 */
    7017 SCIP_CALL( applyFixings(scip, cons, cutoff) );
    7018 if( *cutoff )
    7019 return SCIP_OKAY;
    7020
    7021 /* check if constraint has any chances of tightening bounds */
    7022 if( !canTightenBounds(cons) )
    7023 return SCIP_OKAY;
    7024
    7025 consdata = SCIPconsGetData(cons);
    7026 assert(consdata != NULL);
    7027
    7028 nvars = consdata->nvars;
    7029 force = (nvars == 1) && !SCIPconsIsModifiable(cons);
    7030
    7031 /* we are at the root node or during presolving */
    7032 if( SCIPgetDepth(scip) < 1 )
    7033 tightenmode = 2;
    7034 else
    7035 tightenmode = 1;
    7036
    7037 /* stop if we already tightened the constraint and the tightening is not forced */
    7038 if( !force && (consdata->boundstightened >= tightenmode) ) /*lint !e574*/
    7039 return SCIP_OKAY;
    7040
    7041 /* ensure that the variables are properly sorted */
    7042 if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
    7043 {
    7044 SCIP_CALL( consdataSort(scip, consdata) );
    7045 assert(consdata->coefsorted);
    7046 }
    7047
    7048 /* update maximal activity delta if necessary */
    7049 if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
    7051
    7052 assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
    7053 assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
    7054 checkMaxActivityDelta(scip, consdata);
    7055
    7056 /* this may happen if all variables are fixed */
    7057 if( SCIPisFeasZero(scip, consdata->maxactdelta) )
    7058 return SCIP_OKAY;
    7059
    7060 if( !SCIPisInfinity(scip, consdata->maxactdelta) )
    7061 {
    7062 SCIP_Real slack;
    7063 SCIP_Real surplus;
    7064 SCIP_Real minactivity;
    7065 SCIP_Real maxactivity;
    7066 SCIP_Bool ismintight;
    7067 SCIP_Bool ismaxtight;
    7068 SCIP_Bool isminsettoinfinity;
    7069 SCIP_Bool ismaxsettoinfinity;
    7070
    7071 /* use maximal activity delta to skip propagation (cannot deduce anything) */
    7072 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &ismintight, &ismaxtight,
    7073 &isminsettoinfinity, &ismaxsettoinfinity);
    7074 assert(!SCIPisInfinity(scip, minactivity));
    7075 assert(!SCIPisInfinity(scip, -maxactivity));
    7076
    7077 slack = (SCIPisInfinity(scip, consdata->rhs) || isminsettoinfinity) ? SCIPinfinity(scip) : (consdata->rhs - minactivity);
    7078 surplus = (SCIPisInfinity(scip, -consdata->lhs) || ismaxsettoinfinity) ? SCIPinfinity(scip) : (maxactivity - consdata->lhs);
    7079
    7080 /* check if the constraint will propagate */
    7081 if( SCIPisLE(scip, consdata->maxactdelta, MIN(slack, surplus)) )
    7082 return SCIP_OKAY;
    7083 }
    7084
    7085 /* check if we can use fast implementation for easy and numerically well behaved cases */
    7086 easycase = SCIPisLT(scip, consdata->maxactdelta, maxeasyactivitydelta);
    7087
    7088 /* as long as the bounds might be tightened again, try to tighten them; abort after a maximal number of rounds */
    7089 lastchange = -1;
    7090
    7091#ifndef SCIP_DEBUG
    7092 oldnchgbds = 0;
    7093 oldnchgbdstotal = *nchgbds;
    7094#endif
    7095
    7096 for( nrounds = 0; (force || consdata->boundstightened < tightenmode) && nrounds < MAXTIGHTENROUNDS; ++nrounds ) /*lint !e574*/
    7097 {
    7098 /* ensure that the variables are properly sorted
    7099 *
    7100 * note: it might happen that integer variables become binary during bound tightening at the root node
    7101 */
    7102 if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
    7103 {
    7104 SCIP_CALL( consdataSort(scip, consdata) );
    7105 assert(consdata->coefsorted);
    7106 }
    7107
    7108 /* mark the constraint to have the variables' bounds tightened */
    7109 consdata->boundstightened = (unsigned int)tightenmode;
    7110
    7111 /* try to tighten the bounds of each variable in the constraint. During solving process, the binary variable
    7112 * sorting enables skipping variables
    7113 */
    7114 v = 0;
    7115 while( v < nvars && v != lastchange && !(*cutoff) )
    7116 {
    7117 oldnchgbds = *nchgbds;
    7118
    7119 if( easycase )
    7120 {
    7121 SCIP_CALL( tightenVarBoundsEasy(scip, cons, v, cutoff, nchgbds, force) );
    7122 }
    7123 else
    7124 {
    7125 SCIP_CALL( tightenVarBounds(scip, cons, v, cutoff, nchgbds, force) );
    7126 }
    7127
    7128 /* if there was no progress, skip the rest of the binary variables */
    7129 if( *nchgbds > oldnchgbds )
    7130 {
    7131 lastchange = v;
    7132 ++v;
    7133 }
    7134 else if( consdata->coefsorted && v < consdata->nbinvars - 1
    7135 && !SCIPisFeasEQ(scip, SCIPvarGetUbLocal(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v])) )
    7136 v = consdata->nbinvars;
    7137 else
    7138 ++v;
    7139 }
    7140
    7141#ifndef SCIP_DEBUG
    7142 SCIPdebugMessage("linear constraint <%s> found %d bound changes in round %d\n", SCIPconsGetName(cons),
    7143 *nchgbds - oldnchgbdstotal, nrounds);
    7144 oldnchgbdstotal += oldnchgbds;
    7145#endif
    7146 }
    7147
    7148#ifndef NDEBUG
    7149 if( force && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
    7150 assert(*cutoff || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->vars[0]), SCIPvarGetUbLocal(consdata->vars[0])));
    7151#endif
    7152
    7153 return SCIP_OKAY;
    7154}
    7155
    7156/** checks linear constraint for feasibility of given solution or current solution */
    7157static
    7159 SCIP* scip, /**< SCIP data structure */
    7160 SCIP_CONS* cons, /**< linear constraint */
    7161 SCIP_SOL* sol, /**< solution to be checked, or NULL for current solution */
    7162 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
    7163 SCIP_Bool checkrelmaxabs, /**< Should the violation for a constraint with side 0.0 be checked relative
    7164 * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
    7165 SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
    7166 )
    7167{
    7168 SCIP_CONSDATA* consdata;
    7169 SCIP_Real activity;
    7170 SCIP_Real absviol;
    7171 SCIP_Real relviol;
    7172 SCIP_Real lhsviol;
    7173 SCIP_Real rhsviol;
    7174
    7175 assert(scip != NULL);
    7176 assert(cons != NULL);
    7177 assert(violated != NULL);
    7178
    7179 SCIPdebugMsg(scip, "checking linear constraint <%s>\n", SCIPconsGetName(cons));
    7181
    7182 consdata = SCIPconsGetData(cons);
    7183 assert(consdata != NULL);
    7184
    7185 *violated = FALSE;
    7186
    7187 if( consdata->row != NULL )
    7188 {
    7189 if( !checklprows && SCIProwIsInLP(consdata->row) )
    7190 return SCIP_OKAY;
    7191 else if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
    7192 activity = consdataComputePseudoActivity(scip, consdata);
    7193 else
    7194 activity = SCIPgetRowSolActivity(scip, consdata->row, sol);
    7195 }
    7196 else
    7197 activity = consdataGetActivity(scip, consdata, sol);
    7198
    7199 SCIPdebugMsg(scip, " consdata activity=%.15g (lhs=%.15g, rhs=%.15g, row=%p, checklprows=%u, rowinlp=%u, sol=%p, hascurrentnodelp=%u)\n",
    7200 activity, consdata->lhs, consdata->rhs, (void*)consdata->row, checklprows,
    7201 consdata->row == NULL ? 0 : SCIProwIsInLP(consdata->row), (void*)sol,
    7202 consdata->row == NULL ? FALSE : SCIPhasCurrentNodeLP(scip));
    7203
    7204 /* calculate absolute and relative bound violations */
    7205 lhsviol = consdata->lhs - activity;
    7206 rhsviol = activity - consdata->rhs;
    7207
    7208 absviol = 0.0;
    7209 relviol = 0.0;
    7210 if( (lhsviol > 0) && (lhsviol > rhsviol) )
    7211 {
    7212 absviol = lhsviol;
    7213 relviol = SCIPrelDiff(consdata->lhs, activity);
    7214 }
    7215 else if( rhsviol > 0 )
    7216 {
    7217 absviol = rhsviol;
    7218 relviol = SCIPrelDiff(activity, consdata->rhs);
    7219 }
    7220
    7221 /* the activity of pseudo solutions may be invalid if it comprises positive and negative infinity contributions; we
    7222 * return infeasible for safety
    7223 */
    7224 if( activity == SCIP_INVALID ) /*lint !e777*/
    7225 {
    7226 assert(sol == NULL);
    7227 *violated = TRUE;
    7228
    7229 /* set violation of invalid pseudo solutions */
    7230 absviol = SCIP_INVALID;
    7231 relviol = SCIP_INVALID;
    7232
    7233 /* reset constraint age since we are in enforcement */
    7235 }
    7236 /* check with relative tolerances (the default) */
    7237 else if( !consdata->checkabsolute && (SCIPisFeasLT(scip, activity, consdata->lhs) || SCIPisFeasGT(scip, activity, consdata->rhs)) )
    7238 {
    7239 /* the "normal" check: one of the two sides is violated */
    7240 if( !checkrelmaxabs )
    7241 {
    7242 *violated = TRUE;
    7243
    7244 /* only reset constraint age if we are in enforcement */
    7245 if( sol == NULL )
    7246 {
    7248 }
    7249 }
    7250 /* the (much) more complicated check: we try to disregard random noise and violations of a 0.0 side which are
    7251 * small compared to the absolute values occurring in the activity
    7252 */
    7253 else
    7254 {
    7255 SCIP_Real maxabs;
    7256 SCIP_Real coef;
    7257 SCIP_Real absval;
    7258 SCIP_Real solval;
    7259 int v;
    7260
    7261 maxabs = 1.0;
    7262
    7263 /* compute maximum absolute value */
    7264 for( v = 0; v < consdata->nvars; ++v )
    7265 {
    7266 if( consdata->vals != NULL )
    7267 {
    7268 coef = consdata->vals[v];
    7269 }
    7270 else
    7271 coef = 1.0;
    7272
    7273 solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
    7274 absval = REALABS( coef * solval );
    7275 maxabs = MAX( maxabs, absval );
    7276 }
    7277
    7278 /* regard left hand side, first */
    7279 if( SCIPisFeasLT(scip, activity, consdata->lhs) )
    7280 {
    7281 /* check whether violation is random noise */
    7282 if( (consdata->lhs - activity) <= (1e-15 * maxabs) )
    7283 {
    7284 SCIPdebugMsg(scip, " lhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
    7285 consdata->lhs - activity, maxabs);
    7286 SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
    7287
    7288 /* only increase constraint age if we are in enforcement */
    7289 if( sol == NULL )
    7290 {
    7291 SCIP_CALL( SCIPincConsAge(scip, cons) );
    7292 }
    7293 }
    7294 /* lhs is violated and lhs is 0.0: use relative tolerance w.r.t. largest absolute value */
    7295 else if( SCIPisZero(scip, consdata->lhs) )
    7296 {
    7297 if( (consdata->lhs - activity) <= (SCIPfeastol(scip) * maxabs) )
    7298 {
    7299 SCIPdebugMsg(scip, " lhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
    7300 consdata->lhs - activity, maxabs);
    7301 SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
    7302
    7303 /* only increase constraint age if we are in enforcement */
    7304 if( sol == NULL )
    7305 {
    7306 SCIP_CALL( SCIPincConsAge(scip, cons) );
    7307 }
    7308 }
    7309 else
    7310 {
    7311 *violated = TRUE;
    7312
    7313 /* only reset constraint age if we are in enforcement */
    7314 if( sol == NULL )
    7315 {
    7317 }
    7318 }
    7319 }
    7320 else
    7321 {
    7322 *violated = TRUE;
    7323
    7324 /* only reset constraint age if we are in enforcement */
    7325 if( sol == NULL )
    7326 {
    7328 }
    7329 }
    7330 }
    7331
    7332 /* now regard right hand side */
    7333 if( SCIPisFeasGT(scip, activity, consdata->rhs) )
    7334 {
    7335 /* check whether violation is random noise */
    7336 if( (activity - consdata->rhs) <= (1e-15 * maxabs) )
    7337 {
    7338 SCIPdebugMsg(scip, " rhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
    7339 activity - consdata->rhs, maxabs);
    7340 SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
    7341
    7342 /* only increase constraint age if we are in enforcement */
    7343 if( sol == NULL )
    7344 {
    7345 SCIP_CALL( SCIPincConsAge(scip, cons) );
    7346 }
    7347 }
    7348 /* rhs is violated and rhs is 0.0, use relative tolerance w.r.t. largest absolute value */
    7349 else if( SCIPisZero(scip, consdata->rhs) )
    7350 {
    7351 if( (activity - consdata->rhs) <= (SCIPfeastol(scip) * maxabs) )
    7352 {
    7353 SCIPdebugMsg(scip, " rhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
    7354 activity - consdata->rhs, maxabs);
    7355 SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
    7356
    7357 /* only increase constraint age if we are in enforcement */
    7358 if( sol == NULL )
    7359 {
    7360 SCIP_CALL( SCIPincConsAge(scip, cons) );
    7361 }
    7362 }
    7363 else
    7364 {
    7365 *violated = TRUE;
    7366
    7367 /* only reset constraint age if we are in enforcement */
    7368 if( sol == NULL )
    7369 {
    7371 }
    7372 }
    7373 }
    7374 else
    7375 {
    7376 *violated = TRUE;
    7377
    7378 /* only reset constraint age if we are in enforcement */
    7379 if( sol == NULL )
    7380 {
    7382 }
    7383 }
    7384 }
    7385 }
    7386 }
    7387 /* check with absolute tolerances */
    7388 else if( consdata->checkabsolute &&
    7389 ((!SCIPisInfinity(scip, -consdata->lhs) && SCIPisGT(scip, consdata->lhs-activity, SCIPfeastol(scip))) ||
    7390 (!SCIPisInfinity(scip, consdata->rhs) && SCIPisGT(scip, activity-consdata->rhs, SCIPfeastol(scip)))) )
    7391 {
    7392 *violated = TRUE;
    7393
    7394 /* only reset constraint age if we are in enforcement */
    7395 if( sol == NULL )
    7396 {
    7398 }
    7399 }
    7400 else
    7401 {
    7402 /* only increase constraint age if we are in enforcement */
    7403 if( sol == NULL )
    7404 {
    7405 SCIP_CALL( SCIPincConsAge(scip, cons) );
    7406 }
    7407 }
    7408
    7409 /* update absolute and relative violation of the solution */
    7410 if( sol != NULL )
    7411 SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
    7412
    7413 return SCIP_OKAY;
    7414}
    7415
    7416/** creates an LP row in a linear constraint data */
    7417static
    7419 SCIP* scip, /**< SCIP data structure */
    7420 SCIP_CONS* cons /**< linear constraint */
    7421 )
    7422{
    7423 SCIP_CONSDATA* consdata;
    7424
    7425 assert(scip != NULL);
    7426 assert(cons != NULL);
    7427
    7428 consdata = SCIPconsGetData(cons);
    7429 assert(consdata != NULL);
    7430 assert(consdata->row == NULL);
    7431
    7432 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
    7434
    7435 SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) );
    7436
    7437 return SCIP_OKAY;
    7438}
    7439
    7440/** adds linear constraint as cut to the LP */
    7441static
    7443 SCIP* scip, /**< SCIP data structure */
    7444 SCIP_CONS* cons, /**< linear constraint */
    7445 SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
    7446 )
    7447{
    7448 SCIP_CONSDATA* consdata;
    7449
    7450 assert(scip != NULL);
    7451 assert(cons != NULL);
    7452
    7453 consdata = SCIPconsGetData(cons);
    7454 assert(consdata != NULL);
    7455
    7456 if( consdata->row == NULL )
    7457 {
    7458 if( !SCIPconsIsModifiable(cons) )
    7459 {
    7460 /* replace all fixed variables by active counterparts, as we have no chance to do this anymore after the row has been added to the LP
    7461 * removing this here will make test cons/linear/fixedvar.c fail (as of 2018-12-03)
    7462 */
    7463 SCIP_CALL( applyFixings(scip, cons, cutoff) );
    7464 if( *cutoff )
    7465 return SCIP_OKAY;
    7466 }
    7467
    7468 /* convert consdata object into LP row */
    7469 SCIP_CALL( createRow(scip, cons) );
    7470 }
    7471 assert(consdata->row != NULL);
    7472
    7473 if( consdata->nvars == 0 )
    7474 {
    7475 SCIPdebugMsg(scip, "Empty linear constraint enters LP: <%s>\n", SCIPconsGetName(cons));
    7476 }
    7477
    7478 /* insert LP row as cut */
    7479 if( !SCIProwIsInLP(consdata->row) )
    7480 {
    7481 SCIPdebugMsg(scip, "adding relaxation of linear constraint <%s>: ", SCIPconsGetName(cons));
    7482 SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL)) );
    7483 /* if presolving is turned off, the row might be trivial */
    7484 if ( ! SCIPisInfinity(scip, -consdata->lhs) || ! SCIPisInfinity(scip, consdata->rhs) )
    7485 {
    7486 SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, cutoff) );
    7487 }
    7488 }
    7489
    7490 return SCIP_OKAY;
    7491}
    7492
    7493/** adds linear constraint as row to the NLP, if not added yet */
    7494static
    7496 SCIP* scip, /**< SCIP data structure */
    7497 SCIP_CONS* cons /**< linear constraint */
    7498 )
    7499{
    7500 SCIP_CONSDATA* consdata;
    7501
    7502 assert(SCIPisNLPConstructed(scip));
    7503
    7504 /* skip deactivated, redundant, or local linear constraints (the NLP does not allow for local rows at the moment) */
    7505 if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsLocal(cons) )
    7506 return SCIP_OKAY;
    7507
    7508 consdata = SCIPconsGetData(cons);
    7509 assert(consdata != NULL);
    7510
    7511 if( consdata->nlrow == NULL )
    7512 {
    7513 assert(consdata->lhs <= consdata->rhs);
    7514
    7515 SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons),
    7516 0.0, consdata->nvars, consdata->vars, consdata->vals, NULL, consdata->lhs, consdata->rhs, SCIP_EXPRCURV_LINEAR) );
    7517
    7518 assert(consdata->nlrow != NULL);
    7519 }
    7520
    7521 if( !SCIPnlrowIsInNLP(consdata->nlrow) )
    7522 {
    7523 SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow) );
    7524 }
    7525
    7526 return SCIP_OKAY;
    7527}
    7528
    7529/** separates linear constraint: adds linear constraint as cut, if violated by given solution */
    7530static
    7532 SCIP* scip, /**< SCIP data structure */
    7533 SCIP_CONS* cons, /**< linear constraint */
    7534 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
    7535 SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
    7536 SCIP_Bool separatecards, /**< should knapsack cardinality cuts be generated? */
    7537 SCIP_Bool separateall, /**< should all constraints be subject to cardinality cut generation instead of only
    7538 * the ones with non-zero dual value? */
    7539 int* ncuts, /**< pointer to add up the number of found cuts */
    7540 SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
    7541 )
    7542{
    7543 SCIP_CONSDATA* consdata;
    7544 SCIP_Bool violated;
    7545 int oldncuts;
    7546
    7547 assert(scip != NULL);
    7548 assert(conshdlrdata != NULL);
    7549 assert(cons != NULL);
    7550 assert(cutoff != NULL);
    7551
    7552 consdata = SCIPconsGetData(cons);
    7553 assert(ncuts != NULL);
    7554 assert(consdata != NULL);
    7555
    7556 oldncuts = *ncuts;
    7557 *cutoff = FALSE;
    7558
    7559 SCIP_CALL( checkCons(scip, cons, sol, (sol != NULL), conshdlrdata->checkrelmaxabs, &violated) );
    7560
    7561 if( violated )
    7562 {
    7563 /* insert LP row as cut */
    7564 SCIP_CALL( addRelaxation(scip, cons, cutoff) );
    7565 (*ncuts)++;
    7566 }
    7567 else if( !SCIPconsIsModifiable(cons) && separatecards && consdata->nvars > 0 )
    7568 {
    7569 /* relax linear constraint into knapsack constraint and separate lifted cardinality cuts */
    7570 if( !separateall && sol == NULL )
    7571 {
    7572 /* we only want to call the knapsack cardinality cut separator for rows that have a non-zero dual solution */
    7573 if( consdata->row != NULL && SCIProwIsInLP(consdata->row) )
    7574 {
    7575 SCIP_Real dualsol;
    7576
    7577 dualsol = SCIProwGetDualsol(consdata->row);
    7578 if( SCIPisFeasNegative(scip, dualsol) )
    7579 {
    7580 if( !SCIPisInfinity(scip, consdata->rhs) )
    7581 {
    7582 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
    7583 consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
    7584 }
    7585 }
    7586 else if( SCIPisFeasPositive(scip, dualsol) )
    7587 {
    7588 if( !SCIPisInfinity(scip, -consdata->lhs) )
    7589 {
    7590 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
    7591 consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
    7592 }
    7593 }
    7594 }
    7595 }
    7596 else
    7597 {
    7598 if( !SCIPisInfinity(scip, consdata->rhs) )
    7599 {
    7600 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
    7601 consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
    7602 }
    7603 if( !SCIPisInfinity(scip, -consdata->lhs) )
    7604 {
    7605 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
    7606 consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
    7607 }
    7608 }
    7609 }
    7610
    7611 if( *ncuts > oldncuts )
    7612 {
    7614 }
    7615
    7616 return SCIP_OKAY;
    7617}
    7618
    7619/** propagation method for linear constraints */
    7620static
    7622 SCIP* scip, /**< SCIP data structure */
    7623 SCIP_CONS* cons, /**< linear constraint */
    7624 SCIP_Bool tightenbounds, /**< should the variable's bounds be tightened? */
    7625 SCIP_Bool rangedrowpropagation,/**< should ranged row propagation be performed? */
    7626 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
    7627 SCIP_Bool sortvars, /**< should variable sorting for faster propagation be used? */
    7628 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
    7629 int* nchgbds, /**< pointer to count the number of bound changes */
    7630 int* naddconss /**< pointer to count number of added constraints */
    7631 )
    7632{
    7633 SCIP_CONSDATA* consdata;
    7634 SCIP_Real minactivity;
    7635 SCIP_Real maxactivity;
    7636 SCIP_Bool isminacttight;
    7637 SCIP_Bool ismaxacttight;
    7638 SCIP_Bool isminsettoinfinity;
    7639 SCIP_Bool ismaxsettoinfinity;
    7640
    7641 assert(scip != NULL);
    7642 assert(cons != NULL);
    7643 assert(cutoff != NULL);
    7644 assert(nchgbds != NULL);
    7645
    7646 /*SCIPdebugMsg(scip, "propagating linear constraint <%s>\n", SCIPconsGetName(cons));*/
    7647
    7648 consdata = SCIPconsGetData(cons);
    7649 assert(consdata != NULL);
    7650
    7651 if( consdata->eventdata == NULL )
    7652 {
    7653 SCIP_CONSHDLR* conshdlr;
    7654 SCIP_CONSHDLRDATA* conshdlrdata;
    7655
    7656 conshdlr = SCIPconsGetHdlr(cons);
    7657 assert(conshdlr != NULL);
    7658
    7659 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    7660 assert(conshdlrdata != NULL);
    7661
    7662 /* catch bound change events of variables */
    7663 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
    7664 assert(consdata->eventdata != NULL);
    7665 }
    7666
    7667 *cutoff = FALSE;
    7668
    7669 /* we can only infer activity bounds of the linear constraint, if it is not modifiable */
    7670 if( !SCIPconsIsModifiable(cons) )
    7671 {
    7672 /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
    7674 {
    7675 SCIP_CALL( SCIPincConsAge(scip, cons) );
    7676 }
    7677
    7678 /* tighten the variable's bounds */
    7679 if( tightenbounds )
    7680 {
    7681 int oldnchgbds;
    7682
    7683 oldnchgbds = *nchgbds;
    7684
    7685 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
    7686
    7687 if( *nchgbds > oldnchgbds )
    7688 {
    7690 }
    7691 }
    7692
    7693 /* propagate ranged rows */
    7694 if( rangedrowpropagation && tightenbounds && !(*cutoff) )
    7695 {
    7696 int nfixedvars = 0;
    7697
    7698 SCIPdebug( int oldnchgbds = *nchgbds; )
    7699
    7700 SCIP_CALL( rangedRowPropagation(scip, cons, cutoff, &nfixedvars, nchgbds, naddconss) );
    7701
    7702 if( *cutoff )
    7703 {
    7704 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible\n", SCIPconsGetName(cons));
    7705 }
    7706 else
    7707 {
    7708 SCIPdebug( SCIPdebugMsg(scip, "linear constraint <%s> found %d bound changes and %d fixings\n", SCIPconsGetName(cons), *nchgbds - oldnchgbds, nfixedvars); )
    7709 }
    7710
    7711 if( nfixedvars > 0 )
    7712 *nchgbds += 2 * nfixedvars;
    7713 } /*lint !e438*/
    7714
    7715 /* check constraint for infeasibility and redundancy */
    7716 if( !(*cutoff) )
    7717 {
    7718 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
    7719 &isminsettoinfinity, &ismaxsettoinfinity);
    7720
    7721 if( SCIPisFeasGT(scip, minactivity, consdata->rhs) )
    7722 {
    7723 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (rhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
    7724 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
    7725
    7726 /* analyze conflict */
    7728
    7730 *cutoff = TRUE;
    7731 }
    7732 else if( SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
    7733 {
    7734 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (lhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
    7735 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
    7736
    7737 /* analyze conflict */
    7739
    7741 *cutoff = TRUE;
    7742 }
    7743 else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
    7744 {
    7745 SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
    7746 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
    7747
    7748 /* remove the constraint locally unless it has become empty, in which case it is removed globally */
    7749 if( consdata->nvars > 0 )
    7751 else
    7752 SCIP_CALL( SCIPdelCons(scip, cons) );
    7753 }
    7754 }
    7755 }
    7756
    7757 return SCIP_OKAY;
    7758}
    7759
    7760
    7761/*
    7762 * Presolving methods
    7763 */
    7764
    7765/** converts all variables with fixed domain into FIXED variables */
    7766static
    7768 SCIP* scip, /**< SCIP data structure */
    7769 SCIP_CONS* cons, /**< linear constraint */
    7770 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
    7771 int* nfixedvars /**< pointer to count the total number of fixed variables */
    7772 )
    7773{
    7774 SCIP_CONSDATA* consdata;
    7775 SCIP_VAR* var;
    7776 SCIP_VARSTATUS varstatus;
    7777 SCIP_Real lb;
    7778 SCIP_Real ub;
    7779 SCIP_Bool fixed;
    7780 SCIP_Bool infeasible;
    7781 int v;
    7782
    7783 assert(scip != NULL);
    7784 assert(cons != NULL);
    7785 assert(cutoff != NULL);
    7786 assert(nfixedvars != NULL);
    7787
    7788 consdata = SCIPconsGetData(cons);
    7789 assert(consdata != NULL);
    7790
    7791 for( v = 0; v < consdata->nvars; ++v )
    7792 {
    7793 assert(consdata->vars != NULL);
    7794 var = consdata->vars[v];
    7795 varstatus = SCIPvarGetStatus(var);
    7796
    7797 if( varstatus != SCIP_VARSTATUS_FIXED )
    7798 {
    7799 lb = SCIPvarGetLbGlobal(var);
    7800 ub = SCIPvarGetUbGlobal(var);
    7801 if( SCIPisEQ(scip, lb, ub) )
    7802 {
    7803 SCIP_Real fixval;
    7804
    7805 fixval = SCIPselectSimpleValue(lb, ub, MAXDNOM);
    7806 SCIPdebugMsg(scip, "converting variable <%s> with fixed bounds [%.15g,%.15g] into fixed variable fixed at %.15g\n",
    7807 SCIPvarGetName(var), lb, ub, fixval);
    7808 SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
    7809 if( infeasible )
    7810 {
    7811 SCIPdebugMsg(scip, " -> infeasible fixing\n");
    7812 *cutoff = TRUE;
    7813 return SCIP_OKAY;
    7814 }
    7815 if( fixed )
    7816 (*nfixedvars)++;
    7817 }
    7818 }
    7819 }
    7820
    7821 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
    7822
    7823 if( infeasible )
    7824 {
    7825 SCIPdebugMsg(scip, " -> infeasible fixing\n");
    7826 *cutoff = TRUE;
    7827 return SCIP_OKAY;
    7828 }
    7829
    7830 assert(consdata->removedfixings);
    7831
    7832 return SCIP_OKAY;
    7833}
    7834
    7835#define MAX_CLIQUE_NONZEROS_PER_CONS 1000000
    7836
    7837/** extracts cliques of the constraint and adds them to SCIP
    7838 *
    7839 * The following clique extraction mechanism are implemeneted
    7840 *
    7841 * 1. collect binary variables and sort them in non increasing order, then
    7842 *
    7843 * a) if the constraint has a finite right hand side and the negative infinity counters for the minactivity are zero
    7844 * then add the variables as a clique for which all successive pairs of coefficients fullfill the following
    7845 * condition
    7846 *
    7847 * minactivity + vals[i] + vals[i+1] > rhs
    7848 *
    7849 * and also add the binary to binary implication also for non-successive variables for which the same argument
    7850 * holds
    7851 *
    7852 * minactivity + vals[i] + vals[j] > rhs
    7853 *
    7854 * e.g. 5.3 x1 + 3.6 x2 + 3.3 x3 + 2.1 x4 <= 5.5 (all x are binary) would lead to the clique (x1, x2, x3) and the
    7855 * binary to binary implications x1 = 1 => x4 = 0 and x2 = 1 => x4 = 0
    7856 *
    7857 * b) if the constraint has a finite left hand side and the positive infinity counters for the maxactivity are zero
    7858 * then add the variables as a clique for which all successive pairs of coefficients fullfill the follwoing
    7859 * condition
    7860 *
    7861 * maxactivity + vals[i] + vals[i-1] < lhs
    7862 *
    7863 * and also add the binary to binary implication also for non-successive variables for which the same argument
    7864 * holds
    7865 *
    7866 * maxactivity + vals[i] + vals[j] < lhs
    7867 *
    7868 * e.g. you could multiply the above example by -1
    7869 *
    7870 * c) the constraint has a finite right hand side and a finite minactivity then add the variables as a negated
    7871 * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
    7872 * condition
    7873 *
    7874 * minactivity - vals[i] - vals[i-1] > rhs
    7875 *
    7876 * and also add the binary to binary implication also for non-successive variables for which the
    7877 * same argument holds
    7878 *
    7879 * minactivity - vals[i] - vals[j] > rhs
    7880 *
    7881 * e.g. -4 x1 -3 x2 - 2 x3 + 2 x4 <= -4 would lead to the (negated) clique (~x1, ~x2) and the binary to binary
    7882 * implication x1 = 0 => x3 = 1
    7883 *
    7884 * d) the constraint has a finite left hand side and a finite maxactivity then add the variables as a negated
    7885 * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
    7886 * condition
    7887 *
    7888 * maxactivity - vals[i] - vals[i+1] < lhs
    7889 *
    7890 * and also add the binary to binary implication also for non-successive variables for which the same argument
    7891 * holds
    7892 *
    7893 * maxactivity - vals[i] - vals[j] < lhs
    7894 *
    7895 * e.g. you could multiply the above example by -1
    7896 *
    7897 * 2. if the linear constraint represents a set-packing or set-partitioning constraint, the whole constraint is added
    7898 * as clique, (this part is done at the end of the method)
    7899 *
    7900 */
    7901static
    7903 SCIP* scip, /**< SCIP data structure */
    7904 SCIP_CONS* cons, /**< linear constraint */
    7905 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
    7906 SCIP_Bool sortvars, /**< should variables be used in sorted order? */
    7907 int* nfixedvars, /**< pointer to count number of fixed variables */
    7908 int* nchgbds, /**< pointer to count the total number of tightened bounds */
    7909 SCIP_Bool* cutoff /**< pointer to store TRUE, if a cutoff was found */
    7910 )
    7911{
    7912 SCIP_VAR** vars;
    7913 SCIP_Real* vals;
    7914 SCIP_CONSDATA* consdata;
    7915 SCIP_Bool lhsclique;
    7916 SCIP_Bool rhsclique;
    7917 SCIP_Bool finitelhs;
    7918 SCIP_Bool finiterhs;
    7919 SCIP_Bool finiteminact;
    7920 SCIP_Bool finitemaxact;
    7921 SCIP_Bool finitenegminact;
    7922 SCIP_Bool finitenegmaxact;
    7923 SCIP_Bool finiteposminact;
    7924 SCIP_Bool finiteposmaxact;
    7925 SCIP_Bool infeasible;
    7926 SCIP_Bool stopped;
    7927 int cliquenonzerosadded;
    7928 int v;
    7929 int i;
    7930 int nposcoefs;
    7931 int nnegcoefs;
    7932 int nvars;
    7933
    7934 assert(scip != NULL);
    7935 assert(cons != NULL);
    7936 assert(nfixedvars != NULL);
    7937 assert(nchgbds != NULL);
    7938 assert(cutoff != NULL);
    7939 assert(!SCIPconsIsDeleted(cons));
    7940
    7941 consdata = SCIPconsGetData(cons);
    7942 assert(consdata != NULL);
    7943
    7944 if( consdata->nvars < 2 )
    7945 return SCIP_OKAY;
    7946
    7947 /* add implications if possible
    7948 *
    7949 * for now we only add binary to non-binary implications, and this is only done for the binary variable with the
    7950 * maximal absolute contribution and also only if this variable would force all other variables to their bound
    7951 * corresponding to the global minimal activity of the constraint
    7952 */
    7953 if( !consdata->implsadded )
    7954 {
    7955 /* sort variables by variable type */
    7956 SCIP_CALL( consdataSort(scip, consdata) );
    7957
    7958 /* @todo we might extract implications/cliques if SCIPvarIsBinary() variables exist and we have integer variables
    7959 * up front, might change sorting correspondingly
    7960 */
    7961 /* fast abort if no binaries seem to exist
    7962 * "seem to", because there are rare situations in which variables may actually not be sorted by type, even though consdataSort has been called
    7963 * this situation can occur if, e.g., the type of consdata->vars[1] has been changed to binary, but the corresponding variable event has
    7964 * not been executed yet, because it is the eventExecLinear() which marks the variables array as unsorted (set consdata->indexsorted to FALSE),
    7965 * which is the requirement for consdataSort() to actually resort the variables
    7966 * we assume that in this situation the below code may be executed in a future presolve round, after the variable events have been executed
    7967 */
    7968 if( !SCIPvarIsBinary(consdata->vars[0]) )
    7969 return SCIP_OKAY;
    7970
    7971 nvars = consdata->nvars;
    7972 vars = consdata->vars;
    7973 vals = consdata->vals;
    7974
    7975 /* recompute activities if needed */
    7976 if( !consdata->validactivities )
    7977 consdataCalcActivities(scip, consdata);
    7978 assert(consdata->validactivities);
    7979
    7980 finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
    7981 finiterhs = !SCIPisInfinity(scip, consdata->rhs);
    7982 finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
    7983 finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
    7984 finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
    7985 finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
    7986 finiteminact = (finitenegminact && finiteposminact);
    7987 finitemaxact = (finitenegmaxact && finiteposmaxact);
    7988
    7989 if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
    7990 {
    7991 SCIP_Real maxabscontrib = -1.0;
    7992 SCIP_Bool posval = FALSE;
    7993 SCIP_Bool allbinary = TRUE;
    7994 int oldnchgbds = *nchgbds;
    7995 int nbdchgs = 0;
    7996 int nimpls = 0;
    7997 int position = -1;
    7998
    7999 /* we need a valid minimal/maximal activity to add cliques */
    8000 if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
    8001 {
    8003 assert(consdata->validglbminact);
    8004 }
    8005
    8006 if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
    8007 {
    8009 assert(consdata->validglbmaxact);
    8010 }
    8011 assert(consdata->validglbminact || consdata->validglbmaxact);
    8012
    8013 /* @todo extend this to local/constraint probing */
    8014
    8015 /* determine maximal contribution to the activity */
    8016 for( v = nvars - 1; v >= 0; --v )
    8017 {
    8018 if( SCIPvarIsBinary(vars[v]) )
    8019 {
    8020 if( vals[v] > 0 )
    8021 {
    8022 SCIP_Real value = vals[v] * SCIPvarGetUbGlobal(vars[v]);
    8023
    8024 if( value > maxabscontrib )
    8025 {
    8026 maxabscontrib = value;
    8027 position = v;
    8028 posval = TRUE;
    8029 }
    8030 }
    8031 else
    8032 {
    8033 SCIP_Real value = vals[v] * SCIPvarGetLbGlobal(vars[v]);
    8034
    8035 value = REALABS(value);
    8036
    8037 if( value > maxabscontrib )
    8038 {
    8039 maxabscontrib = value;
    8040 position = v;
    8041 posval = FALSE;
    8042 }
    8043 }
    8044 }
    8045 else
    8046 allbinary = FALSE;
    8047 }
    8048 assert(0 <= position && position < nvars);
    8049
    8050 if( !SCIPisEQ(scip, maxabscontrib, 1.0) && !allbinary )
    8051 {
    8052 /* if the right hand side and the minimal activity are finite and changing the variable with the biggest
    8053 * influence to their bound forces all other variables to be at their minimal contribution, we can add these
    8054 * implications
    8055 */
    8056 if( finiterhs && finiteminact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbminactivity), consdata->rhs - maxabscontrib) )
    8057 {
    8058 for( v = nvars - 1; v >= 0; --v )
    8059 {
    8060 /* binary to binary implications will be collected when extrating cliques */
    8061 if( !SCIPvarIsBinary(vars[v]) )
    8062 {
    8063 if( v != position )
    8064 {
    8065 if( vals[v] > 0 )
    8066 {
    8067 /* add implications */
    8068 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
    8069 ++nimpls;
    8070 *nchgbds += nbdchgs;
    8071 }
    8072 else
    8073 {
    8074 /* add implications */
    8075 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
    8076 ++nimpls;
    8077 *nchgbds += nbdchgs;
    8078 }
    8079
    8080 if( infeasible )
    8081 {
    8082 *cutoff = TRUE;
    8083 break;
    8084 }
    8085 }
    8086 }
    8087 /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
    8088 else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY && !SCIPvarIsImpliedIntegral(vars[v]) )
    8089 break;
    8090 }
    8091 }
    8092
    8093 /* if the left hand side and the maximal activity are finite and changing the variable with the biggest
    8094 * influence to their bound forces all other variables to be at their minimal contribution, we can add these
    8095 * implications
    8096 */
    8097 if( finitelhs && finitemaxact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbmaxactivity), consdata->lhs - maxabscontrib) )
    8098 {
    8099 for( v = nvars - 1; v >= 0; --v )
    8100 {
    8101 /* binary to binary implications will be collected when extrating cliques */
    8102 if( !SCIPvarIsBinary(vars[v]) )
    8103 {
    8104 if( v != position )
    8105 {
    8106 if( vals[v] > 0 )
    8107 {
    8108 /* add implications */
    8109 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
    8110 ++nimpls;
    8111 *nchgbds += nbdchgs;
    8112 }
    8113 else
    8114 {
    8115 /* add implications */
    8116 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
    8117 ++nimpls;
    8118 *nchgbds += nbdchgs;
    8119 }
    8120
    8121 if( infeasible )
    8122 {
    8123 *cutoff = TRUE;
    8124 break;
    8125 }
    8126 }
    8127 }
    8128 /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
    8129 else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
    8130 break;
    8131 }
    8132 }
    8133
    8134 /* did we find some implications */
    8135 if( nimpls > 0 )
    8136 {
    8137 SCIPdebugMsg(scip, "extracted %d implications from constraint %s which led to %d bound changes, %scutoff detetcted\n", nimpls, SCIPconsGetName(cons), *nchgbds - oldnchgbds, *cutoff ? "" : "no ");
    8138
    8139 if( *cutoff )
    8140 return SCIP_OKAY;
    8141
    8142 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
    8143 if( *nchgbds - oldnchgbds > 0 )
    8144 {
    8145 /* check for fixed variables */
    8146 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
    8147 if( *cutoff )
    8148 return SCIP_OKAY;
    8149
    8150 /* tighten variable's bounds */
    8151 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
    8152 if( *cutoff )
    8153 return SCIP_OKAY;
    8154
    8155 /* check for fixed variables */
    8156 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
    8157 if( *cutoff )
    8158 return SCIP_OKAY;
    8159 }
    8160 }
    8161 }
    8162 }
    8163
    8164 consdata->implsadded = TRUE;
    8165 }
    8166
    8167 /* check if we already added the cliques of this constraint */
    8168 if( consdata->cliquesadded )
    8169 return SCIP_OKAY;
    8170
    8171 consdata->cliquesadded = TRUE;
    8172 cliquenonzerosadded = 0;
    8173 stopped = FALSE;
    8174
    8175 /* sort variables by variable type */
    8176 SCIP_CALL( consdataSort(scip, consdata) );
    8177
    8178 nvars = consdata->nvars;
    8179 vars = consdata->vars;
    8180 vals = consdata->vals;
    8181
    8182 /**@todo extract more cliques, implications and variable bounds from linear constraints */
    8183
    8184 /* recompute activities if needed */
    8185 if( !consdata->validactivities )
    8186 consdataCalcActivities(scip, consdata);
    8187 assert(consdata->validactivities);
    8188
    8189 finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
    8190 finiterhs = !SCIPisInfinity(scip, consdata->rhs);
    8191 finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
    8192 finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
    8193 finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
    8194 finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
    8195 finiteminact = (finitenegminact && finiteposminact);
    8196 finitemaxact = (finitenegmaxact && finiteposmaxact);
    8197
    8198 /* 1. we wheck whether some variables do not fit together into this constraint and add the corresponding clique
    8199 * information
    8200 */
    8201 if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
    8202 {
    8203 SCIP_VAR** binvars;
    8204 SCIP_Real* binvarvals;
    8205 int nposbinvars = 0;
    8206 int nnegbinvars = 0;
    8207 int allonebinary = 0;
    8208
    8209 SCIP_CALL( SCIPallocBufferArray(scip, &binvars, nvars) );
    8210 SCIP_CALL( SCIPallocBufferArray(scip, &binvarvals, nvars) );
    8211
    8212 /* collect binary variables */
    8213 for( i = 0; i < nvars; ++i )
    8214 {
    8215 if( SCIPvarIsBinary(vars[i]) )
    8216 {
    8217 assert(!SCIPisZero(scip, vals[i]));
    8218
    8219 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
    8220 ++allonebinary;
    8221
    8222 binvars[nposbinvars + nnegbinvars] = vars[i];
    8223 binvarvals[nposbinvars + nnegbinvars] = vals[i];
    8224
    8225 if( SCIPisPositive(scip, vals[i]) )
    8226 ++nposbinvars;
    8227 else
    8228 ++nnegbinvars;
    8229
    8230 assert(nposbinvars + nnegbinvars <= nvars);
    8231 }
    8232 /* stop searching for binary variables, because the constraint data is sorted */
    8233 else if( !SCIPvarIsIntegral(vars[i]) )
    8234 break;
    8235 }
    8236 assert(nposbinvars + nnegbinvars <= nvars);
    8237
    8238 /* setppc constraints will be handled later; we need at least two binary variables with same sign to extract
    8239 * cliques
    8240 */
    8241 if( allonebinary < nvars && (nposbinvars >= 2 || nnegbinvars >= 2) )
    8242 {
    8243 SCIP_Real threshold;
    8244 int oldnchgbds = *nchgbds;
    8245 int nbdchgs;
    8246 int jstart;
    8247 int j;
    8248
    8249 /* we need a valid minimal/maximal activity to add cliques */
    8250 if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
    8251 {
    8253 assert(consdata->validglbminact);
    8254 }
    8255
    8256 if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
    8257 {
    8259 assert(consdata->validglbmaxact);
    8260 }
    8261 assert(consdata->validglbminact || consdata->validglbmaxact);
    8262
    8263 /* sort coefficients non-increasing to be faster in the clique search */
    8264 SCIPsortDownRealPtr(binvarvals, (void**) binvars, nposbinvars + nnegbinvars);
    8265
    8266 /* case a) */
    8267 if( finiterhs && finitenegminact && nposbinvars >= 2 )
    8268 {
    8269 /* compute value that needs to be exceeded */
    8270 threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
    8271
    8272 j = 1;
    8273#ifdef SCIP_DISABLED_CODE /* assertion should only hold when constraints were fully propagated and boundstightened */
    8274 /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
    8275 assert(SCIPisFeasLE(scip, binvarvals[0], threshold));
    8276#endif
    8277 /* check if at least two variables are in a clique */
    8278 if( SCIPisFeasGT(scip, binvarvals[0] + binvarvals[j], threshold) )
    8279 {
    8280 ++j;
    8281 /* check for extending the clique */
    8282 while( j < nposbinvars )
    8283 {
    8284 if( !SCIPisFeasGT(scip, binvarvals[j-1] + binvarvals[j], threshold) )
    8285 break;
    8286 ++j;
    8287 }
    8288 assert(j >= 2);
    8289
    8290 /* add clique with at least two variables */
    8291 SCIP_CALL( SCIPaddClique(scip, binvars, NULL, j, FALSE, &infeasible, &nbdchgs) );
    8292
    8293 if( infeasible )
    8294 *cutoff = TRUE;
    8295
    8296 *nchgbds += nbdchgs;
    8297
    8298 cliquenonzerosadded += j;
    8299 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
    8300 stopped = TRUE;
    8301
    8302 /* exchange the last variable in the clique if possible and add all new ones */
    8303 if( !stopped && !(*cutoff) && j < nposbinvars )
    8304 {
    8305 SCIP_VAR** clqvars;
    8306 int lastfit = j - 2;
    8307 assert(lastfit >= 0);
    8308
    8309 /* copy all 'main'-clique variables */
    8310 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
    8311
    8312 /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
    8313 while( lastfit >= 0 && j < nposbinvars )
    8314 {
    8315 /* check if two variables are in a clique */
    8316 if( SCIPisFeasGT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
    8317 {
    8318 clqvars[lastfit + 1] = binvars[j];
    8319
    8320 /* add clique with at least two variables */
    8321 SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
    8322
    8323 if( infeasible )
    8324 {
    8325 *cutoff = TRUE;
    8326 break;
    8327 }
    8328
    8329 *nchgbds += nbdchgs;
    8330
    8331 cliquenonzerosadded += (lastfit + 2);
    8332 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
    8333 {
    8334 stopped = TRUE;
    8335 break;
    8336 }
    8337
    8338 ++j;
    8339 }
    8340 else
    8341 --lastfit;
    8342 }
    8343
    8344 SCIPfreeBufferArray(scip, &clqvars);
    8345 }
    8346 }
    8347 }
    8348
    8349 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
    8350 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
    8351 {
    8352 /* check for fixed variables */
    8353 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
    8354
    8355 if( !*cutoff )
    8356 {
    8357 /* tighten variable's bounds */
    8358 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
    8359
    8360 if( !*cutoff )
    8361 {
    8362 /* check for fixed variables */
    8363 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
    8364
    8365 if( !*cutoff )
    8366 {
    8367 /* sort variables by variable type */
    8368 SCIP_CALL( consdataSort(scip, consdata) );
    8369
    8370 /* recompute activities if needed */
    8371 if( !consdata->validactivities )
    8372 consdataCalcActivities(scip, consdata);
    8373 assert(consdata->validactivities);
    8374
    8375 nvars = consdata->nvars;
    8376 vars = consdata->vars;
    8377 vals = consdata->vals;
    8378 nposbinvars = 0;
    8379 nnegbinvars = 0;
    8380 allonebinary = 0;
    8381
    8382 /* update binary variables */
    8383 for( i = 0; i < nvars; ++i )
    8384 {
    8385 if( SCIPvarIsBinary(vars[i]) )
    8386 {
    8387 assert(!SCIPisZero(scip, vals[i]));
    8388
    8389 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
    8390 ++allonebinary;
    8391
    8392 binvars[nposbinvars + nnegbinvars] = vars[i];
    8393 binvarvals[nposbinvars + nnegbinvars] = vals[i];
    8394
    8395 if( SCIPisPositive(scip, vals[i]) )
    8396 ++nposbinvars;
    8397 else
    8398 ++nnegbinvars;
    8399
    8400 assert(nposbinvars + nnegbinvars <= nvars);
    8401 }
    8402 /* stop searching for binary variables, because the constraint data is sorted */
    8403 else if( !SCIPvarIsIntegral(vars[i]) )
    8404 break;
    8405 }
    8406 assert(nposbinvars + nnegbinvars <= nvars);
    8407 }
    8408 }
    8409 }
    8410
    8411 oldnchgbds = *nchgbds;
    8412 }
    8413
    8414 /* case b) */
    8415 if( !stopped && !(*cutoff) && finitelhs && finiteposmaxact && nnegbinvars >= 2 )
    8416 {
    8417 /* compute value that needs to be deceeded */
    8418 threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
    8419
    8420 i = nposbinvars + nnegbinvars - 1;
    8421 j = i - 1;
    8422#ifdef SCIP_DISABLED_CODE
    8423 /* assertion should only hold when constraints were fully propagated and boundstightened */
    8424 /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
    8425 assert(SCIPisFeasGE(scip, binvarvals[i], threshold));
    8426#endif
    8427 /* check if two variables are in a clique */
    8428 if( SCIPisFeasLT(scip, binvarvals[i] + binvarvals[j], threshold) )
    8429 {
    8430 --j;
    8431 /* check for extending the clique */
    8432 while( j >= nposbinvars )
    8433 {
    8434 if( !SCIPisFeasLT(scip, binvarvals[j+1] + binvarvals[j], threshold) )
    8435 break;
    8436 --j;
    8437 }
    8438 jstart = j;
    8439
    8440 assert(i - j >= 2);
    8441 /* add clique with at least two variables */
    8442 SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), NULL, i - j, FALSE, &infeasible, &nbdchgs) );
    8443
    8444 if( infeasible )
    8445 *cutoff = TRUE;
    8446
    8447 *nchgbds += nbdchgs;
    8448
    8449 cliquenonzerosadded += (i - j);
    8450 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
    8451 stopped = TRUE;
    8452
    8453 /* exchange the last variable in the clique if possible and add all new ones */
    8454 if( !stopped && !(*cutoff) && jstart >= nposbinvars )
    8455 {
    8456 SCIP_VAR** clqvars;
    8457 int lastfit = jstart + 1;
    8458 assert(lastfit < i);
    8459
    8460 /* copy all 'main'-clique variables */
    8461 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
    8462 ++lastfit;
    8463
    8464 /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
    8465 while( lastfit <= i && j >= nposbinvars )
    8466 {
    8467 /* check if two variables are in a clique */
    8468 if( SCIPisFeasLT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
    8469 {
    8470 assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
    8471 clqvars[lastfit - jstart - 2] = binvars[j];
    8472
    8473 assert(i - lastfit + 2 >= 2);
    8474 /* add clique with at least two variables */
    8475 SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), NULL, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
    8476
    8477 if( infeasible )
    8478 {
    8479 *cutoff = TRUE;
    8480 break;
    8481 }
    8482
    8483 *nchgbds += nbdchgs;
    8484
    8485 cliquenonzerosadded += (i - lastfit + 2);
    8486 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
    8487 {
    8488 stopped = TRUE;
    8489 break;
    8490 }
    8491
    8492 --j;
    8493 }
    8494 else
    8495 ++lastfit;
    8496 }
    8497
    8498 SCIPfreeBufferArray(scip, &clqvars);
    8499 }
    8500 }
    8501 }
    8502
    8503 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
    8504 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
    8505 {
    8506 /* check for fixed variables */
    8507 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
    8508
    8509 if( !*cutoff )
    8510 {
    8511 /* tighten variable's bounds */
    8512 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
    8513
    8514 if( !*cutoff )
    8515 {
    8516 /* check for fixed variables */
    8517 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
    8518
    8519 if( !*cutoff )
    8520 {
    8521 /* sort variables by variable type */
    8522 SCIP_CALL( consdataSort(scip, consdata) );
    8523
    8524 /* recompute activities if needed */
    8525 if( !consdata->validactivities )
    8526 consdataCalcActivities(scip, consdata);
    8527 assert(consdata->validactivities);
    8528
    8529 nvars = consdata->nvars;
    8530 vars = consdata->vars;
    8531 vals = consdata->vals;
    8532 nposbinvars = 0;
    8533 nnegbinvars = 0;
    8534 allonebinary = 0;
    8535
    8536 /* update binary variables */
    8537 for( i = 0; i < nvars; ++i )
    8538 {
    8539 if( SCIPvarIsBinary(vars[i]) )
    8540 {
    8541 assert(!SCIPisZero(scip, vals[i]));
    8542
    8543 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
    8544 ++allonebinary;
    8545
    8546 binvars[nposbinvars + nnegbinvars] = vars[i];
    8547 binvarvals[nposbinvars + nnegbinvars] = vals[i];
    8548
    8549 if( SCIPisPositive(scip, vals[i]) )
    8550 ++nposbinvars;
    8551 else
    8552 ++nnegbinvars;
    8553
    8554 assert(nposbinvars + nnegbinvars <= nvars);
    8555 }
    8556 /* stop searching for binary variables, because the constraint data is sorted */
    8557 else if( !SCIPvarIsIntegral(vars[i]) )
    8558 break;
    8559 }
    8560 assert(nposbinvars + nnegbinvars <= nvars);
    8561 }
    8562 }
    8563 }
    8564
    8565 oldnchgbds = *nchgbds;
    8566 }
    8567
    8568 /* case c) */
    8569 if( !(*cutoff) && finiterhs && finiteminact && nnegbinvars >= 2 )
    8570 {
    8571 SCIP_Bool* values;
    8572
    8573 /* initialize clique values array for adding a negated clique */
    8574 SCIP_CALL( SCIPallocBufferArray(scip, &values, nnegbinvars) );
    8575 BMSclearMemoryArray(values, nnegbinvars);
    8576
    8577 /* compute value that needs to be exceeded */
    8578 threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
    8579
    8580 i = nposbinvars + nnegbinvars - 1;
    8581 j = i - 1;
    8582
    8583#ifdef SCIP_DISABLED_CODE
    8584 /* assertion should only hold when constraints were fully propagated and boundstightened */
    8585 /* check if the variable should not have already been fixed to one */
    8586 assert(!SCIPisFeasGT(scip, binvarvals[i], threshold));
    8587#endif
    8588
    8589 if( SCIPisFeasGT(scip, -binvarvals[i] - binvarvals[j], threshold) )
    8590 {
    8591 --j;
    8592 /* check for extending the clique */
    8593 while( j >= nposbinvars )
    8594 {
    8595 if( !SCIPisFeasGT(scip, -binvarvals[j+1] - binvarvals[j], threshold) )
    8596 break;
    8597 --j;
    8598 }
    8599 jstart = j;
    8600
    8601 assert(i - j >= 2);
    8602 /* add negated clique with at least two variables */
    8603 SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), values, i - j, FALSE, &infeasible, &nbdchgs) );
    8604
    8605 if( infeasible )
    8606 *cutoff = TRUE;
    8607
    8608 *nchgbds += nbdchgs;
    8609
    8610 cliquenonzerosadded += (i - j);
    8611 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
    8612 stopped = TRUE;
    8613
    8614 /* exchange the last variable in the clique if possible and add all new ones */
    8615 if( !stopped && !(*cutoff) && jstart >= nposbinvars )
    8616 {
    8617 SCIP_VAR** clqvars;
    8618 int lastfit = j + 1;
    8619 assert(lastfit < i);
    8620
    8621 /* copy all 'main'-clique variables */
    8622 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
    8623 ++lastfit;
    8624
    8625 /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
    8626 while( lastfit <= i && j >= nposbinvars )
    8627 {
    8628 /* check if two variables are in a negated clique */
    8629 if( SCIPisFeasGT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
    8630 {
    8631 assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
    8632 clqvars[lastfit - jstart - 2] = binvars[j];
    8633
    8634 assert(i - lastfit + 2 >= 2);
    8635 /* add clique with at least two variables */
    8636 SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), values, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
    8637
    8638 if( infeasible )
    8639 {
    8640 *cutoff = TRUE;
    8641 break;
    8642 }
    8643
    8644 *nchgbds += nbdchgs;
    8645
    8646 cliquenonzerosadded += (i - lastfit + 2);
    8647 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
    8648 {
    8649 stopped = TRUE;
    8650 break;
    8651 }
    8652
    8653 --j;
    8654 }
    8655 else
    8656 ++lastfit;
    8657 }
    8658
    8659 SCIPfreeBufferArray(scip, &clqvars);
    8660 }
    8661 }
    8662
    8663 SCIPfreeBufferArray(scip, &values);
    8664 }
    8665
    8666 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
    8667 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
    8668 {
    8669 /* check for fixed variables */
    8670 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
    8671
    8672 if( !*cutoff )
    8673 {
    8674 /* tighten variable's bounds */
    8675 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
    8676
    8677 if( !*cutoff )
    8678 {
    8679 /* check for fixed variables */
    8680 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
    8681
    8682 if( !*cutoff )
    8683 {
    8684 /* sort variables by variable type */
    8685 SCIP_CALL( consdataSort(scip, consdata) );
    8686
    8687 /* recompute activities if needed */
    8688 if( !consdata->validactivities )
    8689 consdataCalcActivities(scip, consdata);
    8690 assert(consdata->validactivities);
    8691
    8692 nvars = consdata->nvars;
    8693 vars = consdata->vars;
    8694 vals = consdata->vals;
    8695 nposbinvars = 0;
    8696 nnegbinvars = 0;
    8697 allonebinary = 0;
    8698
    8699 /* update binary variables */
    8700 for( i = 0; i < nvars; ++i )
    8701 {
    8702 if( SCIPvarIsBinary(vars[i]) )
    8703 {
    8704 assert(!SCIPisZero(scip, vals[i]));
    8705
    8706 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
    8707 ++allonebinary;
    8708
    8709 binvars[nposbinvars + nnegbinvars] = vars[i];
    8710 binvarvals[nposbinvars + nnegbinvars] = vals[i];
    8711
    8712 if( SCIPisPositive(scip, vals[i]) )
    8713 ++nposbinvars;
    8714 else
    8715 ++nnegbinvars;
    8716
    8717 assert(nposbinvars + nnegbinvars <= nvars);
    8718 }
    8719 /* stop searching for binary variables, because the constraint data is sorted */
    8720 else if( !SCIPvarIsIntegral(vars[i]) )
    8721 break;
    8722 }
    8723 assert(nposbinvars + nnegbinvars <= nvars);
    8724 }
    8725 }
    8726 }
    8727 }
    8728
    8729 /* case d) */
    8730 if( !stopped && !(*cutoff) && finitelhs && finitemaxact && nposbinvars >= 2 )
    8731 {
    8732 SCIP_Bool* values;
    8733
    8734 /* initialize clique values array for adding a negated clique */
    8735 SCIP_CALL( SCIPallocBufferArray(scip, &values, nposbinvars) );
    8736 BMSclearMemoryArray(values, nposbinvars);
    8737
    8738 /* compute value that needs to be exceeded */
    8739 threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
    8740
    8741 j = 1;
    8742
    8743#ifdef SCIP_DISABLED_CODE
    8744 /* assertion should only hold when constraints were fully propagated and boundstightened */
    8745 /* check if the variable should not have already been fixed to one */
    8746 assert(!SCIPisFeasLT(scip, -binvarvals[0], threshold));
    8747#endif
    8748
    8749 if( SCIPisFeasLT(scip, -binvarvals[0] - binvarvals[j], threshold) )
    8750 {
    8751 ++j;
    8752 /* check for extending the clique */
    8753 while( j < nposbinvars )
    8754 {
    8755 if( !SCIPisFeasLT(scip, -binvarvals[j-1] - binvarvals[j], threshold) )
    8756 break;
    8757 ++j;
    8758 }
    8759 assert(j >= 2);
    8760
    8761 /* add negated clique with at least two variables */
    8762 SCIP_CALL( SCIPaddClique(scip, binvars, values, j, FALSE, &infeasible, &nbdchgs) );
    8763
    8764 if( infeasible )
    8765 *cutoff = TRUE;
    8766
    8767 *nchgbds += nbdchgs;
    8768
    8769 cliquenonzerosadded += j;
    8770 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
    8771 stopped = TRUE;
    8772
    8773 /* exchange the last variable in the clique if possible and add all new ones */
    8774 if( !stopped && !(*cutoff) && j < nposbinvars )
    8775 {
    8776 SCIP_VAR** clqvars;
    8777 int lastfit = j - 2;
    8778 assert(lastfit >= 0);
    8779
    8780 /* copy all 'main'-clique variables */
    8781 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
    8782
    8783 /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
    8784 while( lastfit >= 0 && j < nposbinvars )
    8785 {
    8786 /* check if two variables are in a negated clique */
    8787 if( SCIPisFeasLT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
    8788 {
    8789 clqvars[lastfit + 1] = binvars[j];
    8790
    8791 /* add clique with at least two variables */
    8792 SCIP_CALL( SCIPaddClique(scip, clqvars, values, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
    8793
    8794 if( infeasible )
    8795 {
    8796 *cutoff = TRUE;
    8797 break;
    8798 }
    8799
    8800 *nchgbds += nbdchgs;
    8801
    8802 cliquenonzerosadded += lastfit + 2;
    8803 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
    8804 break;
    8805
    8806 ++j;
    8807 }
    8808 else
    8809 --lastfit;
    8810 }
    8811
    8812 SCIPfreeBufferArray(scip, &clqvars);
    8813 }
    8814 }
    8815
    8816 SCIPfreeBufferArray(scip, &values);
    8817 }
    8818 }
    8819
    8820 SCIPfreeBufferArray(scip, &binvarvals);
    8821 SCIPfreeBufferArray(scip, &binvars);
    8822
    8823 if( *cutoff )
    8824 return SCIP_OKAY;
    8825 }
    8826
    8827 /* 2. we only check if the constraint is a set packing / partitioning constraint */
    8828
    8829 /* check if all variables are binary, if the coefficients are +1 or -1, and if the right hand side is equal
    8830 * to 1 - number of negative coefficients, or if the left hand side is equal to number of positive coefficients - 1
    8831 */
    8832 nposcoefs = 0;
    8833 nnegcoefs = 0;
    8834 for( i = 0; i < nvars; ++i )
    8835 {
    8836 if( !SCIPvarIsBinary(vars[i]) )
    8837 return SCIP_OKAY;
    8838 else if( SCIPisEQ(scip, vals[i], +1.0) )
    8839 nposcoefs++;
    8840 else if( SCIPisEQ(scip, vals[i], -1.0) )
    8841 nnegcoefs++;
    8842 else
    8843 return SCIP_OKAY;
    8844 }
    8845
    8846 lhsclique = SCIPisEQ(scip, consdata->lhs, (SCIP_Real)nposcoefs - 1.0);
    8847 rhsclique = SCIPisEQ(scip, consdata->rhs, 1.0 - (SCIP_Real)nnegcoefs);
    8848
    8849 if( lhsclique || rhsclique )
    8850 {
    8851 SCIP_Bool* values;
    8852 int nbdchgs;
    8853
    8854 SCIPdebugMsg(scip, "linear constraint <%s>: adding clique with %d vars (%d pos, %d neg)\n",
    8855 SCIPconsGetName(cons), nvars, nposcoefs, nnegcoefs);
    8856 SCIP_CALL( SCIPallocBufferArray(scip, &values, nvars) );
    8857
    8858 for( i = 0; i < nvars; ++i )
    8859 values[i] = (rhsclique == (vals[i] > 0.0));
    8860
    8861 SCIP_CALL( SCIPaddClique(scip, vars, values, nvars, SCIPisEQ(scip, consdata->lhs, consdata->rhs), &infeasible, &nbdchgs) );
    8862
    8863 if( infeasible )
    8864 *cutoff = TRUE;
    8865
    8866 *nchgbds += nbdchgs;
    8867 SCIPfreeBufferArray(scip, &values);
    8868 }
    8869
    8870 return SCIP_OKAY;
    8871}
    8872
    8873/** tightens left and right hand side of constraint due to integrality */
    8874static
    8876 SCIP* scip, /**< SCIP data structure */
    8877 SCIP_CONS* cons, /**< linear constraint */
    8878 int* nchgsides, /**< pointer to count number of side changes */
    8879 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
    8880 )
    8881{
    8882 SCIP_CONSDATA* consdata;
    8883 SCIP_Real newlhs;
    8884 SCIP_Real newrhs;
    8885 SCIP_Bool chglhs;
    8886 SCIP_Bool chgrhs;
    8887 SCIP_Bool integral;
    8888 int i;
    8889
    8890 assert(scip != NULL);
    8891 assert(cons != NULL);
    8892 assert(nchgsides != NULL);
    8893 assert(infeasible != NULL);
    8894
    8895 consdata = SCIPconsGetData(cons);
    8896 assert(consdata != NULL);
    8897
    8898 *infeasible = FALSE;
    8899
    8900 chglhs = FALSE;
    8901 chgrhs = FALSE;
    8902 newlhs = -SCIPinfinity(scip);
    8903 newrhs = SCIPinfinity(scip);
    8904
    8905 if( !SCIPisIntegral(scip, consdata->lhs) || !SCIPisIntegral(scip, consdata->rhs) )
    8906 {
    8907 integral = TRUE;
    8908 for( i = 0; i < consdata->nvars && integral; ++i )
    8909 integral = SCIPvarIsIntegral(consdata->vars[i]) && SCIPisIntegral(scip, consdata->vals[i]);
    8910 if( integral )
    8911 {
    8912 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisIntegral(scip, consdata->lhs) )
    8913 {
    8914 newlhs = SCIPfeasCeil(scip, consdata->lhs);
    8915 chglhs = TRUE;
    8916 }
    8917 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisIntegral(scip, consdata->rhs) )
    8918 {
    8919 newrhs = SCIPfeasFloor(scip, consdata->rhs);
    8920 chgrhs = TRUE;
    8921 }
    8922
    8923 /* check whether rounding would lead to an unsatisfiable constraint */
    8924 if( SCIPisGT(scip, newlhs, newrhs) )
    8925 {
    8926 SCIPdebugMsg(scip, "rounding sides=[%.15g,%.15g] of linear constraint <%s> with integral coefficients and variables only "
    8927 "is infeasible\n", consdata->lhs, consdata->rhs, SCIPconsGetName(cons));
    8928
    8929 *infeasible = TRUE;
    8930 return SCIP_OKAY;
    8931 }
    8932
    8933 SCIPdebugMsg(scip, "linear constraint <%s>: make sides integral: sides=[%.15g,%.15g]\n",
    8934 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
    8935
    8936 if( chglhs )
    8937 {
    8938 assert(!SCIPisInfinity(scip, -newlhs));
    8939
    8940 SCIP_CALL( chgLhs(scip, cons, newlhs) );
    8941 if( !consdata->upgraded )
    8942 (*nchgsides)++;
    8943 }
    8944 if( chgrhs )
    8945 {
    8946 assert(!SCIPisInfinity(scip, newrhs));
    8947
    8948 SCIP_CALL( chgRhs(scip, cons, newrhs) );
    8949 if( !consdata->upgraded )
    8950 (*nchgsides)++;
    8951 }
    8952 SCIPdebugMsg(scip, "linear constraint <%s>: new integral sides: sides=[%.15g,%.15g]\n",
    8953 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
    8954 }
    8955 }
    8956
    8957 return SCIP_OKAY;
    8958}
    8959
    8960/** tightens coefficients of binary, integer, and implied integral variables due to activity bounds in presolving:
    8961 * given an inequality lhs <= a*x + ai*xi <= rhs, with a non-continuous variable li <= xi <= ui
    8962 * let minact := min{a*x + ai*xi}, maxact := max{a*x + ai*xi}
    8963 * (i) ai >= 0:
    8964 * if minact + ai >= lhs and maxact - ai <= rhs: (**)
    8965 * - a deviation from the lower/upper bound of xi would make the left/right hand side redundant
    8966 * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
    8967 * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
    8968 * - change coefficients:
    8969 * ai' := max(lhs - minact, maxact - rhs, 0)
    8970 * lhs' := lhs - (ai - ai')*li
    8971 * rhs' := rhs - (ai - ai')*ui
    8972 * (ii) ai < 0:
    8973 * if minact - ai >= lhs and maxact + ai <= rhs: (***)
    8974 * - a deviation from the upper/lower bound of xi would make the left/right hand side redundant
    8975 * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
    8976 * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
    8977 * - change coefficients:
    8978 * ai' := min(rhs - maxact, minact - lhs, 0)
    8979 * lhs' := lhs - (ai - ai')*ui
    8980 * rhs' := rhs - (ai - ai')*li
    8981 *
    8982 * We further try to remove variables from the constraint;
    8983 * Variables which fulfill conditions (**) or (***) are called relevant variables.
    8984 * A deviation of only one from their bound makes the lhs/rhs feasible (i.e., redundant), even if all other
    8985 * variables are set to their "worst" bound. If all variables which are not relevant cannot make the lhs/rhs
    8986 * redundant, even if they are set to their "best" bound, they can be removed from the constraint. E.g., for binary
    8987 * variables and an inequality x_1 +x_2 +10y_1 +10y_2 >= 5, setting either of the y_i to one suffices to fulfill the
    8988 * inequality, whereas the x_i do not contribute to feasibility and can be removed.
    8989 *
    8990 * @todo use also some tightening procedures for (knapsack) constraints with non-integer coefficients, see
    8991 * cons_knapsack.c the following methods detectRedundantVars() and tightenWeights()
    8992 */
    8993static
    8995 SCIP* scip, /**< SCIP data structure */
    8996 SCIP_CONS* cons, /**< linear constraint */
    8997 int* nchgcoefs, /**< pointer to count total number of changed coefficients */
    8998 int* nchgsides /**< pointer to count number of side changes */
    8999 )
    9000{
    9001 SCIP_CONSDATA* consdata;
    9002 SCIP_VAR* var;
    9003 SCIP_Bool* isvarrelevant;
    9004 SCIP_Real minactivity; /* minimal value w.r.t. the variable's local bounds for the constraint's
    9005 * activity, ignoring the coefficients contributing with infinite value */
    9006 SCIP_Real maxactivity; /* maximal value w.r.t. the variable's local bounds for the constraint's
    9007 * activity, ignoring the coefficients contributing with infinite value */
    9008 SCIP_Bool isminacttight; /* are all contributions to the minactivity non-huge or non-contradicting? */
    9009 SCIP_Bool ismaxacttight; /* are all contributions to the maxactivity non-huge or non-contradicting? */
    9010 SCIP_Bool isminsettoinfinity;
    9011 SCIP_Bool ismaxsettoinfinity;
    9012 SCIP_Real minleftactivity; /* minimal activity without relevant variables */
    9013 SCIP_Real maxleftactivity; /* maximal activity without relevant variables */
    9014 SCIP_Real aggrlhs; /* lhs without minimal activity of relevant variables */
    9015 SCIP_Real aggrrhs; /* rhs without maximal activity of relevant variables */
    9016 SCIP_Real lval; /* candidate for new value arising from considering the left hand side */
    9017 SCIP_Real rval; /* candidate for new value arising from considering the left hand side */
    9018 SCIP_Real val;
    9019 SCIP_Real newval;
    9020 SCIP_Real newlhs;
    9021 SCIP_Real newrhs;
    9022 SCIP_Real lb;
    9023 SCIP_Real ub;
    9024 int i;
    9025
    9026 assert(scip != NULL);
    9027 assert(cons != NULL);
    9028 assert(nchgcoefs != NULL);
    9029 assert(nchgsides != NULL);
    9030
    9031 consdata = SCIPconsGetData(cons);
    9032 assert(consdata != NULL);
    9033
    9034 /* allocate relevance flags */
    9035 SCIP_CALL( SCIPallocBufferArray(scip, &isvarrelevant, consdata->nvars) );
    9036
    9037 /* get the minimal and maximal activity of the constraint */
    9038 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
    9039 &isminsettoinfinity, &ismaxsettoinfinity);
    9040 assert(( isminsettoinfinity && !SCIPisInfinity(scip, -consdata->lhs) )
    9041 || SCIPisLT(scip, minactivity, consdata->lhs)
    9042 || ( ismaxsettoinfinity && !SCIPisInfinity(scip, consdata->rhs) )
    9043 || SCIPisGT(scip, maxactivity, consdata->rhs));
    9044
    9045 minleftactivity = 0.0;
    9046 maxleftactivity = 0.0;
    9047
    9048 /* try to tighten each coefficient */
    9049 i = 0;
    9050 while( i < consdata->nvars )
    9051 {
    9052 /* get coefficient and variable's bounds */
    9053 var = consdata->vars[i];
    9054 val = consdata->vals[i];
    9055 assert(!SCIPisZero(scip, val));
    9056 lb = SCIPvarGetLbLocal(var);
    9057 ub = SCIPvarGetUbLocal(var);
    9058
    9059 /* check sign of coefficient */
    9060 if( val >= 0.0 )
    9061 {
    9062 /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
    9063 isvarrelevant[i] = SCIPvarIsIntegral(var)
    9064 && SCIPisGE(scip, minactivity + val, consdata->lhs) && SCIPisLE(scip, maxactivity - val, consdata->rhs);
    9065
    9066 if( isvarrelevant[i] )
    9067 {
    9068 /* change coefficients:
    9069 * ai' := max(lhs - minact, maxact - rhs)
    9070 * lhs' := lhs - (ai - ai')*li
    9071 * rhs' := rhs - (ai - ai')*ui
    9072 */
    9073
    9074 lval = consdata->lhs - minactivity;
    9075 rval = maxactivity - consdata->rhs;
    9076
    9077 /* Try to avoid cancellation, if there are only two variables */
    9078 if( consdata->nvars == 2 )
    9079 {
    9080 SCIP_Real otherval;
    9081 otherval = consdata->vals[1-i];
    9082
    9083 if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
    9084 {
    9085 lval = consdata->lhs - val*lb;
    9086 lval -= otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
    9087 }
    9088
    9089 if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
    9090 {
    9091 rval = val*ub - consdata->rhs;
    9092 rval += otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
    9093 }
    9094 }
    9095
    9096 newval = MAX3(lval, rval, 0.0);
    9097 assert(SCIPisSumRelLE(scip, newval, val));
    9098
    9099 /* Try to avoid cancellation in computation of lhs/rhs */
    9100 newlhs = consdata->lhs - val * lb;
    9101 newlhs += newval * lb;
    9102 newrhs = consdata->rhs - val * ub;
    9103 newrhs += newval * ub;
    9104
    9105 if( !SCIPisSumRelEQ(scip, newval, val) )
    9106 {
    9107 SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
    9108 SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var), minactivity,
    9109 maxactivity, consdata->lhs, consdata->rhs);
    9110
    9111 /* update the coefficient and the activity bounds */
    9112 if( SCIPisZero(scip, newval) )
    9113 {
    9114 SCIP_CALL( delCoefPos(scip, cons, i) );
    9115 --i;
    9116 }
    9117 else
    9118 {
    9119 SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
    9120 }
    9121 ++(*nchgcoefs);
    9122
    9123 /* get the new minimal and maximal activity of the constraint */
    9124 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight,
    9125 &ismaxacttight, &isminsettoinfinity, &ismaxsettoinfinity);
    9126
    9127 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
    9128 {
    9129 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons),
    9130 consdata->lhs, newlhs);
    9131
    9132 SCIP_CALL( chgLhs(scip, cons, newlhs) );
    9133 (*nchgsides)++;
    9134 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
    9135 }
    9136
    9137 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
    9138 {
    9139 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons),
    9140 consdata->rhs, newrhs);
    9141
    9142 SCIP_CALL( chgRhs(scip, cons, newrhs) );
    9143 (*nchgsides)++;
    9144 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
    9145 }
    9146 }
    9147 }
    9148 else
    9149 {
    9150 if( !SCIPisInfinity(scip, -minleftactivity) )
    9151 {
    9152 assert(!SCIPisInfinity(scip, val));
    9153 assert(!SCIPisInfinity(scip, lb));
    9154 if( SCIPisInfinity(scip, -lb) )
    9155 minleftactivity = -SCIPinfinity(scip);
    9156 else
    9157 minleftactivity += val * lb;
    9158 }
    9159
    9160 if( !SCIPisInfinity(scip, maxleftactivity) )
    9161 {
    9162 assert(!SCIPisInfinity(scip, val));
    9163 assert(!SCIPisInfinity(scip, -ub));
    9164 if( SCIPisInfinity(scip,ub) )
    9165 maxleftactivity = SCIPinfinity(scip);
    9166 else
    9167 maxleftactivity += val * ub;
    9168 }
    9169 }
    9170 }
    9171 else
    9172 {
    9173 /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
    9174 isvarrelevant[i] = SCIPvarIsIntegral(var)
    9175 && SCIPisGE(scip, minactivity - val, consdata->lhs) && SCIPisLE(scip, maxactivity + val, consdata->rhs);
    9176
    9177 if( isvarrelevant[i] )
    9178 {
    9179 /* change coefficients:
    9180 * ai' := min(rhs - maxact, minact - lhs)
    9181 * lhs' := lhs - (ai - ai')*ui
    9182 * rhs' := rhs - (ai - ai')*li
    9183 */
    9184
    9185 lval = minactivity - consdata->lhs;
    9186 rval = consdata->rhs - maxactivity;
    9187
    9188 /* Try to avoid cancellation, if there are only two variables */
    9189 if( consdata->nvars == 2 )
    9190 {
    9191 SCIP_Real otherval;
    9192 otherval = consdata->vals[1-i];
    9193
    9194 if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
    9195 {
    9196 lval = val*ub - consdata->lhs;
    9197 lval += otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
    9198 }
    9199
    9200 if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
    9201 {
    9202 rval = consdata->rhs - val*lb;
    9203 rval -= otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
    9204 }
    9205 }
    9206
    9207 newval = MIN3(lval, rval, 0.0);
    9208 assert(SCIPisSumRelGE(scip, newval, val));
    9209
    9210 /* Try to avoid cancellation in computation of lhs/rhs */
    9211 newlhs = consdata->lhs - val * ub;
    9212 newlhs += newval * ub;
    9213 newrhs = consdata->rhs - val * lb;
    9214 newrhs += newval * lb;
    9215
    9216 if( !SCIPisSumRelEQ(scip, newval, val) )
    9217 {
    9218 SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
    9219 SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var), minactivity,
    9220 maxactivity, consdata->lhs, consdata->rhs);
    9221
    9222 /* update the coefficient and the activity bounds */
    9223 if( SCIPisZero(scip, newval) )
    9224 {
    9225 SCIP_CALL( delCoefPos(scip, cons, i) );
    9226 --i;
    9227 }
    9228 else
    9229 {
    9230 SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
    9231 }
    9232 ++(*nchgcoefs);
    9233
    9234 /* get the new minimal and maximal activity of the constraint */
    9235 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight,
    9236 &ismaxacttight, &isminsettoinfinity, &ismaxsettoinfinity);
    9237
    9238 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
    9239 {
    9240 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons),
    9241 consdata->lhs, newlhs);
    9242
    9243 SCIP_CALL( chgLhs(scip, cons, newlhs) );
    9244 (*nchgsides)++;
    9245 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
    9246 }
    9247
    9248 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
    9249 {
    9250 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons),
    9251 consdata->rhs, newrhs);
    9252
    9253 SCIP_CALL( chgRhs(scip, cons, newrhs) );
    9254 (*nchgsides)++;
    9255 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
    9256 }
    9257 }
    9258 }
    9259 else
    9260 {
    9261 if( !SCIPisInfinity(scip, -minleftactivity) )
    9262 {
    9263 assert(!SCIPisInfinity(scip, -val));
    9264 assert(!SCIPisInfinity(scip, -ub));
    9265 if( SCIPisInfinity(scip, ub) )
    9266 minleftactivity = -SCIPinfinity(scip);
    9267 else
    9268 minleftactivity += val * ub;
    9269 }
    9270
    9271 if( !SCIPisInfinity(scip, maxleftactivity) )
    9272 {
    9273 assert(!SCIPisInfinity(scip, -val));
    9274 assert(!SCIPisInfinity(scip, lb));
    9275 if( SCIPisInfinity(scip, -lb) )
    9276 maxleftactivity = SCIPinfinity(scip);
    9277 else
    9278 maxleftactivity += val * lb;
    9279 }
    9280 }
    9281 }
    9282
    9283 ++i;
    9284 }
    9285
    9286 SCIPdebugMsg(scip, "minleftactivity = %.15g, rhs = %.15g\n",
    9287 minleftactivity, consdata->rhs);
    9288 SCIPdebugMsg(scip, "maxleftactivity = %.15g, lhs = %.15g\n",
    9289 maxleftactivity, consdata->lhs);
    9290
    9291 /* minleft == \infty ==> minactivity == \infty */
    9292 assert(!SCIPisInfinity(scip, -minleftactivity) || SCIPisInfinity(scip, -minactivity));
    9293 assert(!SCIPisInfinity(scip, maxleftactivity) || SCIPisInfinity(scip, maxactivity));
    9294
    9295 /* if the lhs is finite, we will check in the following whether the not relevant variables can make lhs feasible;
    9296 * this is not valid, if the minactivity is -\infty (aggrlhs would be minus infinity in the following computation)
    9297 * or if huge values contributed to the minactivity, because the minactivity is then just a relaxation
    9298 * (<= the exact minactivity), and we might falsely remove coefficients in the following
    9299 */
    9300 assert(!SCIPisInfinity(scip, minactivity));
    9301 if( !SCIPisInfinity(scip, -consdata->lhs) && (SCIPisInfinity(scip, -minactivity) || !isminacttight) )
    9302 goto TERMINATE;
    9303
    9304 /* if the rhs is finite, we will check in the following whether the not relevant variables can make rhs feasible;
    9305 * this is not valid, if the maxactivity is \infty (aggrrhs would be infinity in the following computation)
    9306 * or if huge values contributed to the maxactivity, because the maxactivity is then just a relaxation
    9307 * (>= the exact maxactivity), and we might falsely remove coefficients in the following
    9308 */
    9309 assert(!SCIPisInfinity(scip, -maxactivity));
    9310 if( !SCIPisInfinity(scip, consdata->rhs) && (SCIPisInfinity(scip, maxactivity) || !ismaxacttight) )
    9311 goto TERMINATE;
    9312
    9313 /* correct lhs and rhs by min/max activity of relevant variables
    9314 * relevant variables are all those where a deviation from the bound makes the lhs/rhs redundant
    9315 */
    9316 aggrlhs = consdata->lhs - minactivity + minleftactivity;
    9317 aggrrhs = consdata->rhs - maxactivity + maxleftactivity;
    9318
    9319 /* check if the constraint contains variables whose coefficient can be removed. The reasoning is the following:
    9320 * Each relevant variable can make the lhs/rhs feasible with a deviation of only one in the bound. If _all_ not
    9321 * relevant variables together cannot make lhs/rhs redundant, they can be removed from the constraint. aggrrhs may
    9322 * contain some near-infinity value, but only if rhs is infinity.
    9323 */
    9324 if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasLT(scip, maxleftactivity, aggrlhs))
    9325 && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasGT(scip, minleftactivity, aggrrhs)) )
    9326 {
    9327 SCIP_Real minleftactivitypart;
    9328 SCIP_Real maxleftactivitypart;
    9329
    9330 assert(!SCIPisInfinity(scip, -consdata->lhs) || !SCIPisInfinity(scip, consdata->rhs));
    9331
    9332 /* remove redundant variables from constraint */
    9333 i = 0;
    9334 while( i < consdata->nvars )
    9335 {
    9336 /* consider redundant variable */
    9337 if( !isvarrelevant[i] )
    9338 {
    9339 /* get coefficient and variable's bounds */
    9340 var = consdata->vars[i];
    9341 val = consdata->vals[i];
    9342 assert(!SCIPisZero(scip, val));
    9343 lb = SCIPvarGetLbLocal(var);
    9344 ub = SCIPvarGetUbLocal(var);
    9345
    9346 SCIPdebugMsg(scip, "val = %g\tlhs = %g\trhs = %g\n", val, consdata->lhs, consdata->rhs);
    9347 SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> from constraint since it is redundant\n",
    9348 SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]));
    9349
    9350 /* check sign of coefficient */
    9351 if( val >= 0.0 )
    9352 {
    9353 minleftactivitypart = val * lb;
    9354 maxleftactivitypart = val * ub;
    9355 }
    9356 else
    9357 {
    9358 minleftactivitypart = val * ub;
    9359 maxleftactivitypart = val * lb;
    9360 }
    9361
    9362 /* remove redundant variable */
    9363 isvarrelevant[i] = isvarrelevant[consdata->nvars - 1];
    9364 SCIP_CALL( delCoefPos(scip, cons, i) );
    9365 --i;
    9366
    9367 /* adjust lhs and right hand side */
    9368 newlhs = consdata->lhs - minleftactivitypart;
    9369 newrhs = consdata->rhs - maxleftactivitypart;
    9370
    9371 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
    9372 {
    9373 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons),
    9374 consdata->lhs, newlhs);
    9375
    9376 SCIP_CALL( chgLhs(scip, cons, newlhs) );
    9377 ++(*nchgsides);
    9378 assert(SCIPisEQ(scip, consdata->lhs, newlhs));
    9379 }
    9380
    9381 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
    9382 {
    9383 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons),
    9384 consdata->rhs, newrhs);
    9385
    9386 SCIP_CALL( chgRhs(scip, cons, newrhs) );
    9387 ++(*nchgsides);
    9388 assert(SCIPisEQ(scip, consdata->rhs, newrhs));
    9389 }
    9390 }
    9391
    9392 ++i;
    9393 }
    9394 }
    9395
    9396TERMINATE:
    9397 /* free relevance flags */
    9398 SCIPfreeBufferArray(scip, &isvarrelevant);
    9399
    9400 return SCIP_OKAY;
    9401}
    9402
    9403/** processes equality with only one variable by fixing the variable and deleting the constraint */
    9404static
    9406 SCIP* scip, /**< SCIP data structure */
    9407 SCIP_CONS* cons, /**< linear constraint */
    9408 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
    9409 int* nfixedvars, /**< pointer to count number of fixed variables */
    9410 int* ndelconss /**< pointer to count number of deleted constraints */
    9411 )
    9412{
    9413 SCIP_CONSDATA* consdata;
    9414 SCIP_VAR* var;
    9415 SCIP_Real val;
    9416 SCIP_Real fixval;
    9417 SCIP_Bool infeasible;
    9418 SCIP_Bool fixed;
    9419
    9420 assert(scip != NULL);
    9421 assert(cons != NULL);
    9422 assert(cutoff != NULL);
    9423 assert(nfixedvars != NULL);
    9424 assert(ndelconss != NULL);
    9425
    9426 consdata = SCIPconsGetData(cons);
    9427 assert(consdata != NULL);
    9428 assert(consdata->nvars == 1);
    9429 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
    9430
    9431 /* calculate the value to fix the variable to */
    9432 var = consdata->vars[0];
    9433 val = consdata->vals[0];
    9434 assert(!SCIPisZero(scip, val));
    9435 fixval = SCIPselectSimpleValue(consdata->lhs/val - 0.9 * SCIPepsilon(scip),
    9436 consdata->rhs/val + 0.9 * SCIPepsilon(scip), MAXDNOM);
    9437 SCIPdebugMsg(scip, "linear equality <%s>: fix <%s> == %.15g\n",
    9438 SCIPconsGetName(cons), SCIPvarGetName(var), fixval);
    9439
    9440 /* fix variable */
    9441 SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
    9442 if( infeasible )
    9443 {
    9444 SCIPdebugMsg(scip, " -> infeasible fixing\n");
    9445 *cutoff = TRUE;
    9446 return SCIP_OKAY;
    9447 }
    9448 if( fixed )
    9449 (*nfixedvars)++;
    9450
    9451 /* disable constraint */
    9452 SCIP_CALL( SCIPdelCons(scip, cons) );
    9453 if( !consdata->upgraded )
    9454 (*ndelconss)++;
    9455
    9456 return SCIP_OKAY;
    9457}
    9458
    9459/** processes equality with exactly two variables by aggregating one of the variables and deleting the constraint */
    9460static
    9462 SCIP* scip, /**< SCIP data structure */
    9463 SCIP_CONS* cons, /**< linear constraint */
    9464 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
    9465 int* naggrvars, /**< pointer to count number of aggregated variables */
    9466 int* ndelconss /**< pointer to count number of deleted constraints */
    9467 )
    9468{
    9469 SCIP_CONSDATA* consdata;
    9470 SCIP_Bool infeasible;
    9471 SCIP_Bool redundant;
    9472 SCIP_Bool aggregated;
    9473
    9474 assert(scip != NULL);
    9475 assert(cons != NULL);
    9476 assert(cutoff != NULL);
    9477 assert(naggrvars != NULL);
    9478 assert(ndelconss != NULL);
    9479
    9480 consdata = SCIPconsGetData(cons);
    9481 assert(consdata != NULL);
    9482 assert(consdata->nvars == 2);
    9483 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
    9484
    9485 SCIPdebugMsg(scip, "linear constraint <%s>: aggregate %.15g<%s> + %.15g<%s> == %.15g\n",
    9486 SCIPconsGetName(cons), consdata->vals[0], SCIPvarGetName(consdata->vars[0]),
    9487 consdata->vals[1], SCIPvarGetName(consdata->vars[1]), consdata->rhs);
    9488
    9489 /* aggregate the equality */
    9490 SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], consdata->vals[0], consdata->vals[1],
    9491 consdata->rhs, &infeasible, &redundant, &aggregated) );
    9492
    9493 /* check for infeasibility of aggregation */
    9494 if( infeasible )
    9495 {
    9496 SCIPdebugMsg(scip, " -> infeasible aggregation\n");
    9497 *cutoff = TRUE;
    9498 return SCIP_OKAY;
    9499 }
    9500
    9501 /* count the aggregation */
    9502 if( aggregated )
    9503 (*naggrvars)++;
    9504
    9505 /* delete the constraint, if it is redundant */
    9506 if( redundant )
    9507 {
    9508 SCIP_CALL( SCIPdelCons(scip, cons) );
    9509
    9510 if( !consdata->upgraded )
    9511 (*ndelconss)++;
    9512 }
    9513
    9514 return SCIP_OKAY;
    9515}
    9516
    9517/** calculates the new lhs and rhs of the constraint after the given variable is aggregated out */
    9518static
    9520 SCIP* scip, /**< SCIP data structure */
    9521 SCIP_CONSDATA* consdata, /**< linear constraint data */
    9522 SCIP_VAR* slackvar, /**< variable to be aggregated out */
    9523 SCIP_Real slackcoef, /**< coefficient of variable in constraint */
    9524 SCIP_Real* newlhs, /**< pointer to store new lhs of constraint */
    9525 SCIP_Real* newrhs /**< pointer to store new rhs of constraint */
    9526 )
    9527{
    9528 SCIP_Real slackvarlb;
    9529 SCIP_Real slackvarub;
    9530
    9531 assert(scip != NULL);
    9532 assert(consdata != NULL);
    9533 assert(newlhs != NULL);
    9534 assert(newrhs != NULL);
    9535 assert(!SCIPisInfinity(scip, -consdata->lhs));
    9536 assert(!SCIPisInfinity(scip, consdata->rhs));
    9537
    9538 slackvarlb = SCIPvarGetLbGlobal(slackvar);
    9539 slackvarub = SCIPvarGetUbGlobal(slackvar);
    9540 if( slackcoef > 0.0 )
    9541 {
    9542 if( SCIPisInfinity(scip, -slackvarlb) )
    9543 *newrhs = SCIPinfinity(scip);
    9544 else
    9545 *newrhs = consdata->rhs - slackcoef * slackvarlb;
    9546 if( SCIPisInfinity(scip, slackvarub) )
    9547 *newlhs = -SCIPinfinity(scip);
    9548 else
    9549 *newlhs = consdata->lhs - slackcoef * slackvarub;
    9550 }
    9551 else
    9552 {
    9553 if( SCIPisInfinity(scip, -slackvarlb) )
    9554 *newlhs = -SCIPinfinity(scip);
    9555 else
    9556 *newlhs = consdata->rhs - slackcoef * slackvarlb;
    9557 if( SCIPisInfinity(scip, slackvarub) )
    9558 *newrhs = SCIPinfinity(scip);
    9559 else
    9560 *newrhs = consdata->lhs - slackcoef * slackvarub;
    9561 }
    9562 assert(SCIPisLE(scip, *newlhs, *newrhs));
    9563}
    9564
    9565/** processes equality with more than two variables by multi-aggregating one of the variables and converting the equality
    9566 * into an inequality; if multi-aggregation is not possible, tries to identify one continuous or integer variable that
    9567 * is implied integral by this constraint
    9568 *
    9569 * @todo Check whether a more clever way of avoiding aggregation of variables containing implied integral variables
    9570 * can help.
    9571 */
    9572static
    9574 SCIP* scip, /**< SCIP data structure */
    9575 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
    9576 SCIP_CONS* cons, /**< linear constraint */
    9577 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
    9578 int* naggrvars, /**< pointer to count number of aggregated variables */
    9579 int* ndelconss, /**< pointer to count number of deleted constraints */
    9580 int* nchgvartypes /**< pointer to count number of changed variable types */
    9581 )
    9582{
    9583 SCIP_CONSDATA* consdata;
    9584 SCIP_VAR** vars;
    9585 SCIP_Real* vals;
    9586 SCIP_VARTYPE bestslacktype;
    9587 SCIP_VARTYPE slacktype;
    9588 SCIP_IMPLINTTYPE impltype;
    9589 SCIP_Real lhs;
    9590 SCIP_Real rhs;
    9591 SCIP_Real bestslackdomrng;
    9592 SCIP_Real minabsval;
    9593 SCIP_Real maxabsval;
    9594 SCIP_Bool bestremovescons;
    9595 SCIP_Bool coefszeroone;
    9596 SCIP_Bool coefsintegral;
    9597 SCIP_Bool varsintegral;
    9598 SCIP_Bool infeasible;
    9599 int maxnlocksstay;
    9600 int maxnlocksremove;
    9601 int bestslackpos;
    9602 int bestnlocks;
    9603 int ncontvars;
    9604 int contvarpos;
    9605 int nintvars;
    9606 int nweakimplvars;
    9607 int nimplvars;
    9608 int intvarpos;
    9609 int v;
    9610
    9611 assert(scip != NULL);
    9612 assert(cons != NULL);
    9613 assert(cutoff != NULL);
    9614 assert(naggrvars != NULL);
    9615
    9616 consdata = SCIPconsGetData(cons);
    9617 assert(consdata != NULL);
    9618 assert(consdata->nvars > 2);
    9619 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
    9620
    9621 SCIPdebugMsg(scip, "linear constraint <%s>: try to multi-aggregate equality\n", SCIPconsGetName(cons));
    9622
    9623 /* We do not want to increase the total number of non-zeros due to the multi-aggregation.
    9624 * Therefore, we have to restrict the number of locks of a variable that is aggregated out.
    9625 * maxnlocksstay: maximal sum of lock numbers if the constraint does not become redundant after the aggregation
    9626 * maxnlocksremove: maximal sum of lock numbers if the constraint can be deleted after the aggregation
    9627 */
    9628 lhs = consdata->lhs;
    9629 rhs = consdata->rhs;
    9630 maxnlocksstay = 0;
    9631 if( consdata->nvars == 3 )
    9632 {
    9633 /* If the constraint becomes redundant, 3 non-zeros are removed, and we get 1 additional non-zero for each
    9634 * constraint the variable appears in. Thus, the variable must appear in at most 3 other constraints.
    9635 */
    9636 maxnlocksremove = 3;
    9637 }
    9638 else if( consdata->nvars == 4 )
    9639 {
    9640 /* If the constraint becomes redundant, 4 non-zeros are removed, and we get 2 additional non-zeros for each
    9641 * constraint the variable appears in. Thus, the variable must appear in at most 2 other constraints.
    9642 */
    9643 maxnlocksremove = 2;
    9644 }
    9645 else
    9646 {
    9647 /* If the constraint is redundant but has more than 4 variables, we can only accept one other constraint. */
    9648 maxnlocksremove = 1;
    9649 }
    9650
    9651 /* the locks on this constraint can be ignored */
    9652 if( SCIPconsIsChecked(cons) )
    9653 {
    9654 if( !SCIPisInfinity(scip, -lhs) )
    9655 {
    9656 maxnlocksstay++;
    9657 maxnlocksremove++;
    9658 }
    9659 if( !SCIPisInfinity(scip, rhs) )
    9660 {
    9661 maxnlocksstay++;
    9662 maxnlocksremove++;
    9663 }
    9664 }
    9665
    9666 /* look for a slack variable s to convert a*x + s == b into lhs <= a*x <= rhs */
    9667 vars = consdata->vars;
    9668 vals = consdata->vals;
    9669 bestslackpos = -1;
    9670 bestslacktype = SCIP_VARTYPE_BINARY;
    9671 bestnlocks = INT_MAX;
    9672 bestremovescons = FALSE;
    9673 bestslackdomrng = 0.0;
    9674 coefszeroone = TRUE;
    9675 coefsintegral = TRUE;
    9676 varsintegral = TRUE;
    9677 ncontvars = 0;
    9678 contvarpos = -1;
    9679 nintvars = 0;
    9680 nweakimplvars = 0;
    9681 nimplvars = 0;
    9682 intvarpos = -1;
    9683 minabsval = SCIPinfinity(scip);
    9684 maxabsval = -1.0;
    9685 for( v = 0; v < consdata->nvars; ++v )
    9686 {
    9687 SCIP_VAR* var;
    9688 SCIP_Real val;
    9689 SCIP_Real absval;
    9690 SCIP_Real varlb;
    9691 SCIP_Real varub;
    9692 SCIP_Bool iscont;
    9693 int nlocks;
    9694
    9695 assert(vars != NULL);
    9696 assert(vals != NULL);
    9697
    9698 var = vars[v];
    9699 assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= 1); /* because variable is locked in this equality */
    9701 varlb = SCIPvarGetLbGlobal(var);
    9702 varub = SCIPvarGetUbGlobal(var);
    9703
    9704 val = vals[v];
    9705 absval = REALABS(val);
    9706 assert(SCIPisPositive(scip, absval));
    9707
    9708 /* calculate minimal and maximal absolute value */
    9709 if( absval < minabsval )
    9710 minabsval = absval;
    9711 if( absval > maxabsval )
    9712 maxabsval = absval;
    9713
    9714 /** @todo Do not exit here, but continue if we may still detect implied integrality. */
    9715 /* do not try to multi aggregate, when numerical bad */
    9716 if( maxabsval / minabsval > conshdlrdata->maxmultaggrquot )
    9717 return SCIP_OKAY;
    9718
    9719 impltype = SCIPvarGetImplType(var);
    9721 coefszeroone = coefszeroone && SCIPisEQ(scip, absval, 1.0);
    9722 coefsintegral = coefsintegral && SCIPisIntegral(scip, val);
    9723 varsintegral = varsintegral && (slacktype != SCIP_VARTYPE_CONTINUOUS);
    9724 iscont = (slacktype == SCIP_VARTYPE_CONTINUOUS || slacktype == SCIP_DEPRECATED_VARTYPE_IMPLINT);
    9725
    9726 /* update candidates for continuous -> implint and integer -> implint conversion */
    9727 if( slacktype == SCIP_VARTYPE_CONTINUOUS )
    9728 {
    9729 ncontvars++;
    9730 contvarpos = v;
    9731 }
    9732 else if( slacktype == SCIP_DEPRECATED_VARTYPE_IMPLINT )
    9733 {
    9734 ++nimplvars;
    9735 assert(impltype != SCIP_IMPLINTTYPE_NONE);
    9736 if( impltype == SCIP_IMPLINTTYPE_WEAK )
    9737 ++nweakimplvars;
    9738 }
    9739 else if( slacktype == SCIP_VARTYPE_INTEGER )
    9740 {
    9741 nintvars++;
    9742 intvarpos = v;
    9743 }
    9744
    9745 /* check, if variable is already fixed or aggregated */
    9746 if( !SCIPvarIsActive(var) )
    9747 continue;
    9748
    9749 /* check, if variable is used in too many other constraints, even if this constraint could be deleted */
    9751
    9752 if( nlocks > maxnlocksremove )
    9753 continue;
    9754
    9755 /* check, if variable can be used as a slack variable */
    9756 if( (iscont || (coefsintegral && varsintegral && SCIPisEQ(scip, absval, 1.0))) &&
    9757 !SCIPdoNotMultaggrVar(scip, var) )
    9758 {
    9759 SCIP_Bool better;
    9760 SCIP_Bool equal;
    9761 SCIP_Real slackdomrng;
    9762
    9763 if( SCIPisInfinity(scip, varub) || SCIPisInfinity(scip, -varlb) )
    9764 slackdomrng = SCIPinfinity(scip);
    9765 /* we do not want to perform multi-aggregation due to numerics, if the bounds are huge */
    9766 else if( SCIPisHugeValue(scip, varub) || SCIPisHugeValue(scip, -varlb) )
    9767 return SCIP_OKAY;
    9768 else
    9769 {
    9770 slackdomrng = (varub - varlb)*absval;
    9771 assert(!SCIPisInfinity(scip, slackdomrng));
    9772 }
    9773 equal = FALSE;
    9774
    9775 /* continuous > implied > integer > binary */
    9776 better = (slacktype > bestslacktype) || (bestslackpos == -1);
    9777 if( !better && slacktype == bestslacktype )
    9778 {
    9779 better = (nlocks < bestnlocks);
    9780 if( nlocks == bestnlocks && !bestremovescons )
    9781 {
    9782 better = SCIPisGT(scip, slackdomrng, bestslackdomrng);
    9783 equal = !better && SCIPisGE(scip, slackdomrng, bestslackdomrng);
    9784 }
    9785 }
    9786
    9787 if( better || equal )
    9788 {
    9789 SCIP_Real minresactivity;
    9790 SCIP_Real maxresactivity;
    9791 SCIP_Real newlhs;
    9792 SCIP_Real newrhs;
    9793 SCIP_Bool removescons;
    9794 SCIP_Bool ismintight;
    9795 SCIP_Bool ismaxtight;
    9796 SCIP_Bool isminsettoinfinity;
    9797 SCIP_Bool ismaxsettoinfinity;
    9798
    9799 /* check if the constraint becomes redundant after multi-aggregation */
    9800 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
    9801 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
    9802
    9803 /* do not perform the multi-aggregation due to numerics, if we have huge contributions in the residual
    9804 * activity
    9805 */
    9806 if( !ismintight || !ismaxtight )
    9807 continue;
    9808
    9809 getNewSidesAfterAggregation(scip, consdata, var, val, &newlhs, &newrhs);
    9810 removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
    9811
    9812 /* check resactivities for reliability */
    9813 if( removescons )
    9814 {
    9815 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
    9816 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
    9817
    9818 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity)
    9819 && SCIPisFeasLE(scip, newlhs, minresactivity))
    9820 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
    9821
    9822 removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
    9823 }
    9824
    9825 /* if parameter multaggrremove is set to TRUE, only aggregate when this removes constraint */
    9826 if( conshdlrdata->multaggrremove && !removescons )
    9827 continue;
    9828
    9829 /* if the constraint does not become redundant, only accept the variable if it does not appear in
    9830 * other constraints
    9831 */
    9832 if( !removescons && nlocks > maxnlocksstay )
    9833 continue;
    9834
    9835 /* prefer variables that make the constraints redundant
    9836 * unless there is a continuous better slack
    9837 */
    9838 if( !bestremovescons && removescons )
    9839 better = TRUE;
    9840 else if( bestremovescons && !removescons && (bestslacktype > SCIP_VARTYPE_INTEGER || slacktype <= SCIP_VARTYPE_INTEGER) )
    9841 better = FALSE;
    9842 if( better )
    9843 {
    9844 bestslackpos = v;
    9845 bestslacktype = slacktype;
    9846 bestnlocks = nlocks;
    9847 bestslackdomrng = slackdomrng;
    9848 bestremovescons = removescons;
    9849 }
    9850 }
    9851 }
    9852 }
    9853
    9854 /* if all coefficients and variables are integral, the right hand side must also be integral */
    9855 if( coefsintegral && varsintegral && !SCIPisFeasIntegral(scip, consdata->rhs) )
    9856 {
    9857 SCIPdebugMsg(scip, "linear equality <%s> is integer infeasible\n", SCIPconsGetName(cons));
    9859 *cutoff = TRUE;
    9860 return SCIP_OKAY;
    9861 }
    9862
    9863 /* if the slack variable is of integer type, and the constraint itself may take fractional values,
    9864 * we cannot aggregate the variable, because the integrality condition would get lost
    9865 * Similarly, if there are implied integral variables, we cannot aggregate since we might
    9866 * loose the integrality condition for this variable.
    9867 */
    9868 if( bestslackpos >= 0
    9869 && (bestslacktype == SCIP_VARTYPE_CONTINUOUS || bestslacktype == SCIP_DEPRECATED_VARTYPE_IMPLINT
    9870 || (coefsintegral && varsintegral && nimplvars == 0)) )
    9871 {
    9872 SCIP_VAR** aggrvars;
    9873 SCIP_VAR* slackvar;
    9875 SCIP_Real slackcoef;
    9876 SCIP_Real aggrconst;
    9877 SCIP_Real newlhs;
    9878 SCIP_Real newrhs;
    9879 SCIP_Bool aggregated;
    9880
    9881 /* we found a slack variable that only occurs in at most one other constraint:
    9882 * a_1*x_1 + ... + a_k*x_k + a'*s == rhs -> s == rhs - a_1/a'*x_1 - ... - a_k/a'*x_k
    9883 */
    9884 assert(bestslackpos < consdata->nvars);
    9885
    9886 /* do not multi aggregate binary variables */
    9887 if( SCIPvarIsBinary(vars[bestslackpos]) )
    9888 return SCIP_OKAY;
    9889
    9890 /* convert equality into inequality by deleting the slack variable:
    9891 * x + a*s == b, l <= s <= u -> b - a*u <= x <= b - a*l
    9892 */
    9893 slackvar = vars[bestslackpos];
    9894 slackcoef = vals[bestslackpos];
    9895 assert(!SCIPisZero(scip, slackcoef));
    9896 aggrconst = consdata->rhs/slackcoef;
    9897
    9898 /* allocate temporary memory */
    9899 SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars - 1) );
    9900 SCIP_CALL( SCIPallocBufferArray(scip, &scalars, consdata->nvars - 1) );
    9901
    9902 /* set up the multi-aggregation */
    9903 SCIPdebugMsg(scip, "linear constraint <%s>: multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(slackvar));
    9904 for( v = 0; v < consdata->nvars - 1; ++v )
    9905 {
    9906 if( v == bestslackpos )
    9907 {
    9908 aggrvars[v] = vars[consdata->nvars - 1];
    9909 scalars[v] = -consdata->vals[consdata->nvars - 1] / slackcoef;
    9910 }
    9911 else
    9912 {
    9913 aggrvars[v] = vars[v];
    9914 scalars[v] = -consdata->vals[v] / slackcoef;
    9915 }
    9916 SCIPdebugMsgPrint(scip, " %+.15g<%s>", scalars[v], SCIPvarGetName(aggrvars[v]));
    9917 }
    9918 SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g], nlocks=%d, maxnlocks=%d, removescons=%u\n",
    9919 aggrconst, SCIPvarGetName(slackvar), SCIPvarGetLbGlobal(slackvar), SCIPvarGetUbGlobal(slackvar),
    9920 bestnlocks, bestremovescons ? maxnlocksremove : maxnlocksstay, bestremovescons);
    9921
    9922 /* perform the multi-aggregation */
    9923 SCIP_CALL( SCIPmultiaggregateVar(scip, slackvar, consdata->nvars - 1, aggrvars, scalars, aggrconst,
    9924 &infeasible, &aggregated) );
    9925
    9926 /* free temporary memory */
    9928 SCIPfreeBufferArray(scip, &aggrvars);
    9929
    9930 /* check for infeasible aggregation */
    9931 if( infeasible )
    9932 {
    9933 SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
    9934 *cutoff = TRUE;
    9935 return SCIP_OKAY;
    9936 }
    9937
    9938 /* check for applied aggregation */
    9939 if( !aggregated )
    9940 {
    9941 SCIPdebugMsg(scip, "linear constraint <%s>: multi-aggregation not applicable\n", SCIPconsGetName(cons));
    9942 return SCIP_OKAY;
    9943 }
    9944
    9945 ++(*naggrvars);
    9946
    9947 getNewSidesAfterAggregation(scip, consdata, slackvar, slackcoef, &newlhs, &newrhs);
    9948 assert(SCIPisLE(scip, newlhs, newrhs));
    9949 SCIP_CALL( chgLhs(scip, cons, newlhs) );
    9950 SCIP_CALL( chgRhs(scip, cons, newrhs) );
    9951 SCIP_CALL( delCoefPos(scip, cons, bestslackpos) );
    9952
    9953 /* delete the constraint if it became redundant */
    9954 if( bestremovescons )
    9955 {
    9956 SCIPdebugMsg(scip, "linear constraint <%s>: redundant after multi-aggregation\n", SCIPconsGetName(cons));
    9957 SCIP_CALL( SCIPdelCons(scip, cons) );
    9958
    9959 if( !consdata->upgraded )
    9960 (*ndelconss)++;
    9961 }
    9962 }
    9963 else if( ncontvars == 1 )
    9964 {
    9965 SCIP_VAR* var;
    9966
    9967 assert(0 <= contvarpos && contvarpos < consdata->nvars);
    9968 var = vars[contvarpos];
    9969 assert(!SCIPvarIsIntegral(var));
    9970
    9971 if( coefsintegral && SCIPisFeasIntegral(scip, consdata->rhs) )
    9972 {
    9973 /* upgrade continuous variable to an implied integral one, if the absolute value of the coefficient is one */
    9974 if( SCIPisEQ(scip, REALABS(vals[contvarpos]), 1.0) )
    9975 {
    9976 /* convert the continuous variable with coefficient 1.0 into an implied integral variable */
    9977 SCIPdebugMsg(scip, "linear constraint <%s>: converting continuous variable <%s> to implied integral variable\n",
    9978 SCIPconsGetName(cons), SCIPvarGetName(var));
    9979 /* if the integrality does not depend on weak implied integrality, the variable becomes strongly implied integral */
    9980 impltype = nweakimplvars == 0 ? SCIP_IMPLINTTYPE_STRONG : SCIP_IMPLINTTYPE_WEAK;
    9981 SCIP_CALL( SCIPchgVarImplType(scip, var, impltype, &infeasible) );
    9982 (*nchgvartypes)++;
    9983 if( infeasible )
    9984 {
    9985 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
    9986 *cutoff = TRUE;
    9987
    9988 return SCIP_OKAY;
    9989 }
    9990 }
    9991 /* aggregate continuous variable to an implied integral one if the absolute coefficient is unequal to one */
    9992 /* @todo check if the aggregation coefficient should be in some range(, which is not too big) */
    9993 else if( !SCIPdoNotAggr(scip) )
    9994 {
    9995 SCIP_VAR* newvar;
    9996 SCIP_Real absval;
    9997 char newvarname[SCIP_MAXSTRLEN];
    9998 SCIP_Bool redundant;
    9999 SCIP_Bool aggregated;
    10000
    10001 absval = REALABS(vals[contvarpos]);
    10002
    10003 (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_impl", SCIPvarGetName(var));
    10004
    10005 /* create new implied integral variable for aggregation */
    10006 SCIP_CALL( SCIPcreateVarImpl(scip, &newvar, newvarname, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0,
    10009
    10010 /* add new variable to problem */
    10011 SCIP_CALL( SCIPaddVar(scip, newvar) );
    10012
    10013#ifdef WITH_DEBUG_SOLUTION
    10014 if( SCIPdebugIsMainscip(scip) )
    10015 {
    10016 SCIP_Real varval;
    10017 SCIP_CALL( SCIPdebugGetSolVal(scip, var, &varval) );
    10018 SCIP_CALL( SCIPdebugAddSolVal(scip, newvar, absval * varval) );
    10019 }
    10020#endif
    10021
    10022 /* convert the continuous variable with coefficient 1.0 into an implied integral variable */
    10023 SCIPdebugMsg(scip, "linear constraint <%s>: aggregating continuous variable <%s> to newly created implied integral variable <%s>, aggregation factor = %g\n",
    10024 SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(newvar), absval);
    10025
    10026 /* aggregate continuous and implied integral variable */
    10027 SCIP_CALL( SCIPaggregateVars(scip, var, newvar, absval, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
    10028
    10029 if( infeasible )
    10030 {
    10031 SCIPdebugMsg(scip, "infeasible aggregation of variable <%s> to implied integral variable <%s>, domain is empty\n",
    10032 SCIPvarGetName(var), SCIPvarGetName(newvar));
    10033 *cutoff = TRUE;
    10034
    10035 /* release implied integral variable */
    10036 SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
    10037
    10038 return SCIP_OKAY;
    10039 }
    10040
    10041 /* release implied integral variable */
    10042 SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
    10043
    10044 if( aggregated )
    10045 (*naggrvars)++;
    10046 else
    10047 return SCIP_OKAY;
    10048 }
    10049
    10050 /* we do not have any event on vartype changes, so we need to manually force this constraint to be presolved
    10051 * again
    10052 */
    10053 consdata->boundstightened = 0;
    10054 consdata->rangedrowpropagated = 0;
    10055 consdata->presolved = FALSE;
    10056 }
    10057 }
    10058 else if( ncontvars == 0 && nimplvars == 0 && nintvars == 1 && !coefszeroone )
    10059 {
    10060 SCIP_VAR* var;
    10061
    10062 /* this seems to help for rococo instances, but does not for rout (where all coefficients are +/- 1.0)
    10063 * -> we don't convert integers into implints if the row is a 0/1-row
    10064 */
    10065 assert(varsintegral);
    10066 assert(0 <= intvarpos && intvarpos < consdata->nvars);
    10067 var = vars[intvarpos];
    10068 assert(SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER);
    10069
    10070 if( coefsintegral
    10071 && SCIPisEQ(scip, REALABS(vals[intvarpos]), 1.0)
    10072 && SCIPisFeasIntegral(scip, consdata->rhs) )
    10073 {
    10074 /* convert the integer variable with coefficient 1.0 into an implied integral variable */
    10075 SCIPdebugMsg(scip, "linear constraint <%s>: converting integer variable <%s> to implied integral variable\n",
    10076 SCIPconsGetName(cons), SCIPvarGetName(var));
    10078 (*nchgvartypes)++;
    10079 if( infeasible )
    10080 {
    10081 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
    10082 *cutoff = TRUE;
    10083
    10084 return SCIP_OKAY;
    10085 }
    10086 }
    10087 }
    10088
    10089 return SCIP_OKAY;
    10090}
    10091
    10092/** checks if the given variables and their coefficient are equal (w.r.t. scaling factor) to the objective function */
    10093static
    10095 SCIP* scip, /**< SCIP data structure */
    10096 SCIP_CONSDATA* consdata, /**< linear constraint data */
    10097 SCIP_Real* scale, /**< pointer to store the scaling factor between the constraint and the
    10098 * objective function */
    10099 SCIP_Real* offset /**< pointer to store the offset of the objective function resulting by
    10100 * this constraint */
    10101 )
    10102{
    10103 SCIP_VAR** vars;
    10104 SCIP_VAR* var;
    10105 SCIP_Real objval;
    10106 SCIP_Bool negated;
    10107 int nvars;
    10108 int v;
    10109
    10110 vars = consdata->vars;
    10111 nvars = consdata->nvars;
    10112
    10113 assert(vars != NULL);
    10114
    10115 for( v = 0; v < nvars; ++v )
    10116 {
    10117 negated = FALSE;
    10118 var = vars[v];
    10119 assert(var != NULL);
    10120
    10121 if( SCIPvarIsNegated(var) )
    10122 {
    10123 negated = TRUE;
    10124 var = SCIPvarGetNegatedVar(var);
    10125 assert(var != NULL);
    10126 }
    10127
    10128 objval = SCIPvarGetObj(var);
    10129
    10130 /* if a variable has a zero objective coefficient the linear constraint is not a subset of the objective
    10131 * function
    10132 */
    10133 if( SCIPisZero(scip, objval) )
    10134 return FALSE;
    10135 else
    10136 {
    10137 SCIP_Real val;
    10138
    10139 val = consdata->vals[v];
    10140
    10141 if( negated )
    10142 {
    10143 if( v == 0 )
    10144 {
    10145 /* the first variable defines the scale */
    10146 (*scale) = val / -objval;
    10147
    10148 (*offset) += val;
    10149 }
    10150 else if( SCIPisEQ(scip, -objval * (*scale), val) )
    10151 (*offset) += val;
    10152 else
    10153 return FALSE;
    10154 }
    10155 else if( v == 0 )
    10156 {
    10157 /* the first variable defines the scale */
    10158 (*scale) = val / objval;
    10159 }
    10160 else if( !SCIPisEQ(scip, objval * (*scale), val) )
    10161 return FALSE;
    10162 }
    10163 }
    10164
    10165 return TRUE;
    10166}
    10167
    10168/** check if the linear equality constraint is equal to a subset of the objective function; if so we can remove the
    10169 * objective coefficients and add an objective offset
    10170 */
    10171static
    10173 SCIP* scip, /**< SCIP data structure */
    10174 SCIP_CONS* cons, /**< linear equation constraint */
    10175 SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
    10176 )
    10177{
    10178 SCIP_CONSDATA* consdata;
    10179 SCIP_Real offset;
    10180 SCIP_Real scale;
    10181 SCIP_Bool applicable;
    10182 int nobjvars;
    10183 int nvars;
    10184 int v;
    10185
    10186 assert(scip != NULL);
    10187 assert(cons != NULL);
    10188 assert(conshdlrdata != NULL);
    10189
    10190 consdata = SCIPconsGetData(cons);
    10191 assert(consdata != NULL);
    10192 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
    10193
    10194 nvars = consdata->nvars;
    10195 nobjvars = SCIPgetNObjVars(scip);
    10196
    10197 /* check if the linear equality constraints does not have more variables than the objective function */
    10198 if( nvars > nobjvars || nvars == 0 )
    10199 return SCIP_OKAY;
    10200
    10201 /* check for allowance of algorithm */
    10202 if( (nvars < nobjvars && !conshdlrdata->detectpartialobjective) ||
    10203 (nvars == nobjvars && (!conshdlrdata->detectcutoffbound || !conshdlrdata->detectlowerbound)) )
    10204 return SCIP_OKAY;
    10205
    10206 offset = consdata->rhs;
    10207 scale = 1.0;
    10208
    10209 /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
    10210 applicable = checkEqualObjective(scip, consdata, &scale, &offset);
    10211
    10212 if( applicable )
    10213 {
    10214 SCIP_VAR** vars;
    10215
    10216 vars = consdata->vars;
    10217 assert(vars != NULL);
    10218
    10219 offset /= scale;
    10220
    10221 SCIPdebugMsg(scip, "linear equality constraint <%s> == %g (offset %g) is a subset of the objective function\n",
    10222 SCIPconsGetName(cons), consdata->rhs, offset);
    10223
    10224 /* make equality a model constraint to ensure optimality in this direction */
    10227
    10228 /* set all objective coefficient to zero */
    10229 for( v = 0; v < nvars; ++v )
    10230 {
    10231 SCIP_CALL( SCIPchgVarObj(scip, vars[v], 0.0) );
    10232 }
    10233
    10234 /* add an objective offset */
    10235 SCIP_CALL( SCIPaddObjoffset(scip, offset) );
    10236 }
    10237
    10238 return SCIP_OKAY;
    10239}
    10240
    10241/** updates the cutoff if the given primal bound (which is implied by the given constraint) is better */
    10242static
    10244 SCIP* scip, /**< SCIP data structure */
    10245 SCIP_CONS* cons, /**< constraint */
    10246 SCIP_Real primalbound /**< feasible primal bound */
    10247 )
    10248{
    10249 SCIP_Real cutoffbound;
    10250
    10251 /* increase the cutoff bound value by an epsilon to ensue that solution with the value of the cutoff bound are still
    10252 * accepted
    10253 */
    10254 cutoffbound = primalbound + SCIPcutoffbounddelta(scip);
    10255
    10256 if( cutoffbound < SCIPgetCutoffbound(scip) )
    10257 {
    10258 SCIPdebugMsg(scip, "update cutoff bound <%g>\n", cutoffbound);
    10259
    10260 SCIP_CALL( SCIPupdateCutoffbound(scip, cutoffbound) );
    10261 }
    10262 else
    10263 {
    10264 SCIP_CONSDATA* consdata;
    10265
    10266 consdata = SCIPconsGetData(cons);
    10267 assert(consdata != NULL);
    10268
    10269 /* we cannot disable the enforcement and propagation on ranged rows, because the cutoffbound could only have
    10270 * resulted from one side
    10271 */
    10272 if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
    10273 {
    10274 /* in case the cutoff bound is worse then the currently known one, we additionally avoid enforcement and
    10275 * propagation
    10276 */
    10279 }
    10280 }
    10281
    10282 return SCIP_OKAY;
    10283}
    10284
    10285/** check if the linear constraint is parallel to objective function; if so update the cutoff bound and avoid that the
    10286 * constraint enters the LP by setting the initial and separated flag to FALSE
    10287 */
    10288static
    10290 SCIP* scip, /**< SCIP data structure */
    10291 SCIP_CONS* cons, /**< linear constraint */
    10292 SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
    10293 )
    10294{
    10295 SCIP_CONSDATA* consdata;
    10296 SCIP_Real offset;
    10297 SCIP_Real scale;
    10298 SCIP_Bool applicable;
    10299 int nobjvars;
    10300 int nvars;
    10301
    10302 assert(scip != NULL);
    10303 assert(cons != NULL);
    10304 assert(conshdlrdata != NULL);
    10305
    10306 consdata = SCIPconsGetData(cons);
    10307 assert(consdata != NULL);
    10308
    10309 /* ignore equalities since these are covered by the method checkPartialObjective() */
    10310 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
    10311 return SCIP_OKAY;
    10312
    10313 nvars = consdata->nvars;
    10314 nobjvars = SCIPgetNObjVars(scip);
    10315
    10316 /* check if the linear inequality constraints has the same number of variables as the objective function and if the
    10317 * initial and/or separated flag is set to FALSE
    10318 */
    10319 if( nvars != nobjvars || (!SCIPconsIsInitial(cons) && !SCIPconsIsSeparated(cons)) )
    10320 return SCIP_OKAY;
    10321
    10322 offset = 0.0;
    10323 scale = 1.0;
    10324
    10325 /* There are no variables in the objective function and in the constraint. Thus, the constraint is redundant or proves
    10326 * infeasibility. Since we have a pure feasibility problem, we do not want to set a cutoff or lower bound.
    10327 */
    10328 if( nobjvars == 0 )
    10329 return SCIP_OKAY;
    10330
    10331 /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
    10332 applicable = checkEqualObjective(scip, consdata, &scale, &offset);
    10333
    10334 if( applicable )
    10335 {
    10336 SCIP_Bool rhsfinite = !SCIPisInfinity(scip, consdata->rhs);
    10337 SCIP_Bool lhsfinite = !SCIPisInfinity(scip, -consdata->lhs);
    10338
    10339 assert(scale != 0.0);
    10340
    10341 if( scale > 0.0 )
    10342 {
    10343 if( conshdlrdata->detectcutoffbound && rhsfinite )
    10344 {
    10345 SCIP_Real primalbound;
    10346
    10347 primalbound = (consdata->rhs - offset) / scale;
    10348
    10349 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
    10350 SCIPconsGetName(cons), primalbound);
    10351
    10352 SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
    10353 }
    10354
    10355 if( conshdlrdata->detectlowerbound && lhsfinite )
    10356 {
    10357 SCIP_Real lowerbound;
    10358
    10359 lowerbound = (consdata->lhs - offset) / scale;
    10360
    10361 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
    10362 SCIPconsGetName(cons), lowerbound);
    10363
    10365 }
    10366
    10367 if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !lhsfinite)) ||
    10368 (conshdlrdata->detectlowerbound && !rhsfinite) )
    10369 {
    10370 /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
    10373 }
    10374 }
    10375 else
    10376 {
    10377 if( conshdlrdata->detectlowerbound && rhsfinite )
    10378 {
    10379 SCIP_Real lowerbound;
    10380
    10381 lowerbound = (consdata->rhs - offset) / scale;
    10382
    10383 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
    10384 SCIPconsGetName(cons), lowerbound);
    10385
    10387 }
    10388
    10389 if( conshdlrdata->detectcutoffbound && lhsfinite )
    10390 {
    10391 SCIP_Real primalbound;
    10392
    10393 primalbound = (consdata->lhs - offset) / scale;
    10394
    10395 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
    10396 SCIPconsGetName(cons), primalbound);
    10397
    10398 SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
    10399 }
    10400
    10401 if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !rhsfinite)) ||
    10402 (conshdlrdata->detectlowerbound && !lhsfinite) )
    10403 {
    10404 /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
    10407 }
    10408 }
    10409 }
    10410
    10411 return SCIP_OKAY;
    10412}
    10413
    10414/** converts special equalities */
    10415static
    10417 SCIP* scip, /**< SCIP data structure */
    10418 SCIP_CONS* cons, /**< linear constraint */
    10419 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
    10420 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
    10421 int* nfixedvars, /**< pointer to count number of fixed variables */
    10422 int* naggrvars, /**< pointer to count number of aggregated variables */
    10423 int* ndelconss, /**< pointer to count number of deleted constraints */
    10424 int* nchgvartypes /**< pointer to count number of changed variable types */
    10425 )
    10426{
    10427 SCIP_CONSDATA* consdata;
    10428
    10429 assert(scip != NULL);
    10430 assert(cons != NULL);
    10431 assert(conshdlrdata != NULL);
    10432 assert(cutoff != NULL);
    10433 assert(nfixedvars != NULL);
    10434 assert(naggrvars != NULL);
    10435 assert(ndelconss != NULL);
    10436
    10437 consdata = SCIPconsGetData(cons);
    10438 assert(consdata != NULL);
    10439 assert(consdata->removedfixings);
    10440
    10441 /* do nothing on inequalities */
    10442 if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
    10443 return SCIP_OKAY;
    10444
    10445 /* depending on the number of variables, call a special conversion method */
    10446 if( consdata->nvars == 1 )
    10447 {
    10448 /* fix variable */
    10449 SCIP_CALL( convertUnaryEquality(scip, cons, cutoff, nfixedvars, ndelconss) );
    10450 }
    10451 else if( consdata->nvars == 2 )
    10452 {
    10453 /* aggregate one of the variables */
    10454 SCIP_CALL( convertBinaryEquality(scip, cons, cutoff, naggrvars, ndelconss) );
    10455 }
    10456 else
    10457 {
    10458 /* check if the equality is part of the objective function */
    10459 SCIP_CALL( checkPartialObjective(scip, cons, conshdlrdata) );
    10460
    10461 /* try to multi-aggregate one of the variables */
    10462 SCIP_CALL( convertLongEquality(scip, conshdlrdata, cons, cutoff, naggrvars, ndelconss, nchgvartypes) );
    10463 }
    10464
    10465 return SCIP_OKAY;
    10466}
    10467
    10468/** returns whether the linear sum of all variables/coefficients except the given one divided by the given value is always
    10469 * integral
    10470 */
    10471static
    10473 SCIP* scip, /**< SCIP data structure */
    10474 SCIP_CONSDATA* consdata, /**< linear constraint */
    10475 int pos, /**< position of variable to be left out */
    10476 SCIP_Real val /**< value to divide the coefficients by */
    10477 )
    10478{
    10479 int v;
    10480
    10481 assert(scip != NULL);
    10482 assert(consdata != NULL);
    10483 assert(0 <= pos && pos < consdata->nvars);
    10484
    10485 for( v = 0; v < consdata->nvars; ++v )
    10486 {
    10487 if( v != pos && (!SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v]/val)) )
    10488 return FALSE;
    10489 }
    10490
    10491 return TRUE;
    10492}
    10493
    10494/** check if \f$lhs/a_i - \sum_{j \neq i} a_j/a_i x_j\f$ is always inside the bounds of \f$x_i\f$,
    10495 * check if \f$rhs/a_i - \sum_{j \neq i} a_j/a_i x_j\f$ is always inside the bounds of \f$x_i\f$
    10496 */
    10497static
    10499 SCIP* scip, /**< SCIP data structure */
    10500 SCIP_Real side, /**< lhs or rhs */
    10501 SCIP_Real val, /**< coefficient */
    10502 SCIP_Real minresactivity, /**< minimal residual activity */
    10503 SCIP_Real maxresactivity, /**< maximal residual activity */
    10504 SCIP_Real* minval, /**< pointer to store calculated minval */
    10505 SCIP_Real* maxval /**< pointer to store calculated maxval */
    10506 )
    10507{
    10508 assert(scip != NULL);
    10509 assert(minval != NULL);
    10510 assert(maxval != NULL);
    10511
    10512 if( val > 0.0 )
    10513 {
    10514 if( SCIPisInfinity(scip, ABS(maxresactivity)) )
    10515 *minval = -maxresactivity;
    10516 else
    10517 *minval = (side - maxresactivity)/val;
    10518
    10519 if( SCIPisInfinity(scip, ABS(minresactivity)) )
    10520 *maxval = -minresactivity;
    10521 else
    10522 *maxval = (side - minresactivity)/val;
    10523 }
    10524 else
    10525 {
    10526 if( SCIPisInfinity(scip, ABS(minresactivity)) )
    10527 *minval = minresactivity;
    10528 else
    10529 *minval = (side - minresactivity)/val;
    10530
    10531 if( SCIPisInfinity(scip, ABS(maxresactivity)) )
    10532 *maxval = maxresactivity;
    10533 else
    10534 *maxval = (side - maxresactivity)/val;
    10535 }
    10536}
    10537
    10538
    10539/** applies dual presolving for variables that are locked only once in a direction, and this locking is due to a
    10540 * linear inequality
    10541 */
    10542static
    10544 SCIP* scip, /**< SCIP data structure */
    10545 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
    10546 SCIP_CONS* cons, /**< linear constraint */
    10547 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
    10548 int* nfixedvars, /**< pointer to count number of fixed variables */
    10549 int* naggrvars, /**< pointer to count number of aggregated variables */
    10550 int* ndelconss, /**< pointer to count number of deleted constraints */
    10551 int* nchgvartypes /**< pointer to count number of changed variable types */
    10552 )
    10553{
    10554 SCIP_CONSDATA* consdata;
    10555 SCIP_Bool lhsexists;
    10556 SCIP_Bool rhsexists;
    10557 SCIP_Bool bestisint;
    10558 SCIP_Bool bestislhs;
    10559 SCIP_Real minabsval;
    10560 SCIP_Real maxabsval;
    10561 int bestpos;
    10562 int i;
    10563 int maxotherlocks;
    10564
    10565 assert(scip != NULL);
    10566 assert(cons != NULL);
    10567 assert(cutoff != NULL);
    10568 assert(nfixedvars != NULL);
    10569 assert(naggrvars != NULL);
    10570 assert(ndelconss != NULL);
    10571
    10572 /* only process checked constraints (for which the locks are increased);
    10573 * otherwise we would have to check for variables with nlocks == 0, and these are already processed by the
    10574 * dualfix presolver
    10575 */
    10576 if( !SCIPconsIsChecked(cons) )
    10577 return SCIP_OKAY;
    10578
    10579 consdata = SCIPconsGetData(cons);
    10580 assert(consdata != NULL);
    10581
    10582 lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
    10583 rhsexists = !SCIPisInfinity(scip, consdata->rhs);
    10584
    10585 /* search for a single-locked variable which can be multi-aggregated; if a valid continuous variable was found, we
    10586 * can use it safely for aggregation and break the search loop
    10587 */
    10588 bestpos = -1;
    10589 bestisint = TRUE;
    10590 bestislhs = FALSE;
    10591
    10592 /* We only want to multi-aggregate variables, if they appear in maximal one additional constraint,
    10593 * everything else would produce fill-in. Exceptions:
    10594 * - If there are only two variables in the constraint from which the multi-aggregation arises, no fill-in will be
    10595 * produced.
    10596 * - If there are three variables in the constraint, multi-aggregation in three additional constraints will remove
    10597 * six nonzeros (three from the constraint and the three entries of the multi-aggregated variable) and add
    10598 * six nonzeros (two variables per substitution).
    10599 * - If there at most four variables in the constraint, multi-aggregation in two additional constraints will remove
    10600 * six nonzeros (four from the constraint and the two entries of the multi-aggregated variable) and add
    10601 * six nonzeros (three variables per substitution). God exists!
    10602 */
    10603 if( consdata->nvars <= 2 )
    10604 maxotherlocks = INT_MAX;
    10605 else if( consdata->nvars == 3 )
    10606 maxotherlocks = 3;
    10607 else if( consdata->nvars == 4 )
    10608 maxotherlocks = 2;
    10609 else
    10610 maxotherlocks = 1;
    10611
    10612 /* if this constraint has both sides, it also provides a lock for the other side and thus we can allow one more lock */
    10613 if( lhsexists && rhsexists && maxotherlocks < INT_MAX )
    10614 maxotherlocks++;
    10615
    10616 minabsval = SCIPinfinity(scip);
    10617 maxabsval = -1.0;
    10618 for( i = 0; i < consdata->nvars && bestisint; ++i )
    10619 {
    10620 SCIP_VAR* var;
    10621 SCIP_Bool isint;
    10622 SCIP_Real val;
    10623 SCIP_Real absval;
    10624 SCIP_Real obj;
    10625 SCIP_Real lb;
    10626 SCIP_Real ub;
    10627 SCIP_Bool agglhs;
    10628 SCIP_Bool aggrhs;
    10629
    10630 val = consdata->vals[i];
    10631 absval = REALABS(val);
    10632
    10633 /* calculate minimal and maximal absolute value */
    10634 if( absval < minabsval )
    10635 minabsval = absval;
    10636 if( absval > maxabsval )
    10637 maxabsval = absval;
    10638
    10639 /* do not try to multi aggregate, when numerical bad */
    10640 if( maxabsval / minabsval > conshdlrdata->maxdualmultaggrquot )
    10641 return SCIP_OKAY;
    10642
    10643 var = consdata->vars[i];
    10644 isint = SCIPvarIsNonimpliedIntegral(var);
    10645
    10646 /* if we already found a candidate, skip integers */
    10647 if( bestpos >= 0 && isint )
    10648 continue;
    10649
    10650 /* better do not multi-aggregate binary variables, since most plugins rely on their binary variables to be either
    10651 * active, fixed, or single-aggregated with another binary variable
    10652 */
    10653 if( SCIPvarIsBinary(var) && consdata->nvars > 2 )
    10654 continue;
    10655
    10656 if ( SCIPdoNotMultaggrVar(scip, var) )
    10657 continue;
    10658
    10659 val = consdata->vals[i];
    10660 obj = SCIPvarGetObj(var);
    10661 lb = SCIPvarGetLbGlobal(var);
    10662 ub = SCIPvarGetUbGlobal(var);
    10663
    10664 /* lhs <= a_0 * x_0 + a_1 * x_1 + ... + a_{n-1} * x_{n-1} <= rhs
    10665 *
    10666 * a_i >= 0, c_i >= 0, lhs exists, nlocksdown(x_i) == 1:
    10667 * - constraint is the only one that forbids fixing the variable to its lower bound
    10668 * - fix x_i to the smallest value for this constraint: x_i := lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j
    10669 *
    10670 * a_i <= 0, c_i <= 0, lhs exists, nlocksup(x_i) == 1:
    10671 * - constraint is the only one that forbids fixing the variable to its upper bound
    10672 * - fix x_i to the largest value for this constraint: x_i := lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j
    10673 *
    10674 * a_i >= 0, c_i <= 0, rhs exists, nlocksup(x_i) == 1:
    10675 * - constraint is the only one that forbids fixing the variable to its upper bound
    10676 * - fix x_i to the largest value for this constraint: x_i := rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j
    10677 *
    10678 * a_i <= 0, c_i >= 0, rhs exists, nlocksdown(x_i) == 1:
    10679 * - constraint is the only one that forbids fixing the variable to its lower bound
    10680 * - fix x_i to the smallest value for this constraint: x_i := rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j
    10681 *
    10682 * but: all this is only applicable, if the aggregated value is inside x_i's bounds for all possible values
    10683 * of all x_j
    10684 * furthermore: we only want to apply this, if no fill-in will be produced
    10685 */
    10686 agglhs = lhsexists
    10687 && ((val > 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1
    10688 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
    10689 || (val < 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
    10690 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
    10691 aggrhs = rhsexists
    10692 && ((val > 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
    10693 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
    10694 || (val < 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1
    10695 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
    10696 if( agglhs || aggrhs )
    10697 {
    10698 SCIP_Real minresactivity;
    10699 SCIP_Real maxresactivity;
    10700 SCIP_Real minval;
    10701 SCIP_Real maxval;
    10702 SCIP_Bool ismintight;
    10703 SCIP_Bool ismaxtight;
    10704 SCIP_Bool isminsettoinfinity;
    10705 SCIP_Bool ismaxsettoinfinity;
    10706
    10707 /* calculate bounds for \sum_{j \neq i} a_j * x_j */
    10708 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
    10709 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
    10710 assert(SCIPisLE(scip, minresactivity, maxresactivity));
    10711
    10712 /* We called consdataGetActivityResiduals() saying that we do not need a good relaxation,
    10713 * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
    10714 * This is needed, because we do not want to rely on relaxed finite resactivities.
    10715 */
    10716 assert((ismintight || isminsettoinfinity) && (ismaxtight || ismaxsettoinfinity));
    10717
    10718 if( agglhs )
    10719 {
    10720 /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
    10721 calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
    10722
    10723 assert(SCIPisLE(scip, minval, maxval));
    10724 if( !SCIPisInfinity(scip, -minval) && SCIPisGE(scip, minval, lb)
    10725 && !SCIPisInfinity(scip, maxval) && SCIPisLE(scip, maxval, ub) )
    10726 {
    10727 SCIP_Real oldmaxresactivity;
    10728 SCIP_Real oldminresactivity;
    10729 SCIP_Bool recalculated;
    10730
    10731 recalculated = FALSE;
    10732 oldmaxresactivity = maxresactivity;
    10733 oldminresactivity = minresactivity;
    10734
    10735 /* check minresactivity for reliability */
    10736 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
    10737 {
    10738 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
    10739 recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
    10740 isminsettoinfinity = TRUE; /* here it means only that it was even calculated */
    10741 }
    10742
    10743 /* check maxresactivity for reliability */
    10744 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
    10745 {
    10746 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
    10747 recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
    10748 ismaxsettoinfinity = TRUE; /* here it means only that it was even calculated */
    10749 }
    10750
    10751 /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
    10752 if( recalculated )
    10753 {
    10754 assert(SCIPisLE(scip, minresactivity, maxresactivity));
    10755
    10756 /* check again if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
    10757 calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
    10758
    10759 assert(SCIPisLE(scip, minval, maxval));
    10760 }
    10761
    10762 if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
    10763 {
    10764 /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
    10765 * in the multi-aggregation
    10766 */
    10767 if( !isint || (SCIPisIntegral(scip, consdata->lhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
    10768 {
    10769 bestpos = i;
    10770 bestisint = isint;
    10771 bestislhs = TRUE;
    10772 continue; /* no need to also look at the right hand side */
    10773 }
    10774 }
    10775 }
    10776 }
    10777
    10778 if( aggrhs )
    10779 {
    10780 /* check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
    10781 calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
    10782
    10783 assert(SCIPisLE(scip,minval,maxval));
    10784 if( !SCIPisInfinity(scip, -minval) && SCIPisGE(scip, minval, lb)
    10785 && !SCIPisInfinity(scip, maxval) && SCIPisLE(scip, maxval, ub) )
    10786 {
    10787 SCIP_Real oldmaxresactivity;
    10788 SCIP_Real oldminresactivity;
    10789 SCIP_Bool recalculated;
    10790
    10791 recalculated = FALSE;
    10792 oldmaxresactivity = maxresactivity;
    10793 oldminresactivity = minresactivity;
    10794
    10795 /* check minresactivity for reliability */
    10796 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
    10797 {
    10798 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
    10799 recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
    10800 }
    10801
    10802 /* check maxresactivity for reliability */
    10803 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
    10804 {
    10805 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
    10806 recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
    10807 }
    10808
    10809 /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
    10810 if( recalculated )
    10811 {
    10812 /* check again if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
    10813 calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
    10814 assert(SCIPisLE(scip,minval,maxval));
    10815 }
    10816
    10817 if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
    10818 {
    10819 /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
    10820 * in the multi-aggregation
    10821 */
    10822 if( !isint || (SCIPisIntegral(scip, consdata->rhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
    10823 {
    10824 bestpos = i;
    10825 bestisint = isint;
    10826 bestislhs = FALSE;
    10827 }
    10828 }
    10829 }
    10830 }
    10831 }
    10832 }
    10833
    10834 if( bestpos >= 0 )
    10835 {
    10836 SCIP_VAR** aggrvars;
    10837 SCIP_Real* aggrcoefs;
    10838 SCIP_Real aggrconst;
    10839 SCIP_VAR* bestvar;
    10840 SCIP_Real bestval;
    10841 int naggrs;
    10842 int j;
    10843 SCIP_Bool infeasible;
    10844 SCIP_Bool aggregated;
    10845
    10846 assert(!bestislhs || lhsexists);
    10847 assert(bestislhs || rhsexists);
    10848
    10849 bestvar = consdata->vars[bestpos];
    10850 bestval = consdata->vals[bestpos];
    10851 assert(bestisint == SCIPvarIsNonimpliedIntegral(bestvar));
    10852
    10853 /* allocate temporary memory */
    10854 SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars-1) );
    10855 SCIP_CALL( SCIPallocBufferArray(scip, &aggrcoefs, consdata->nvars-1) );
    10856
    10857 /* set up the multi-aggregation */
    10859 SCIPdebugMsg(scip, "linear constraint <%s> (dual): multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(bestvar));
    10860 naggrs = 0;
    10861
    10862 for( j = 0; j < consdata->nvars; ++j )
    10863 {
    10864 if( j != bestpos )
    10865 {
    10866 aggrvars[naggrs] = consdata->vars[j];
    10867 aggrcoefs[naggrs] = -consdata->vals[j]/consdata->vals[bestpos];
    10868
    10869 SCIPdebugMsgPrint(scip, " %+.15g<%s>", aggrcoefs[naggrs], SCIPvarGetName(aggrvars[naggrs]));
    10870
    10871 /* do not try to multi aggregate, when numerical bad */
    10872 if( SCIPisZero(scip, aggrcoefs[naggrs]) )
    10873 {
    10874 SCIPdebugMsg(scip, "do not perform multi-aggregation: too large aggregation coefficients\n");
    10875
    10876 /* free temporary memory */
    10877 SCIPfreeBufferArray(scip, &aggrcoefs);
    10878 SCIPfreeBufferArray(scip, &aggrvars);
    10879
    10880 return SCIP_OKAY;
    10881 }
    10882
    10883 if( bestisint )
    10884 {
    10885 /* coefficient must be integral: round it to exact integral value */
    10886 assert(SCIPisIntegral(scip, aggrcoefs[naggrs]));
    10887 aggrcoefs[naggrs] = SCIPfloor(scip, aggrcoefs[naggrs]+0.5);
    10888 }
    10889
    10890 naggrs++;
    10891 }
    10892 }
    10893
    10894 aggrconst = (bestislhs ? consdata->lhs/bestval : consdata->rhs/bestval);
    10895 SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g]\n", aggrconst, SCIPvarGetName(bestvar),
    10896 SCIPvarGetLbGlobal(bestvar), SCIPvarGetUbGlobal(bestvar));
    10897 assert(naggrs == consdata->nvars-1);
    10898
    10899 /* right hand side must be integral: round it to exact integral value */
    10900 if( bestisint )
    10901 {
    10902 assert(SCIPisIntegral(scip, aggrconst));
    10903 aggrconst = SCIPfloor(scip, aggrconst+0.5);
    10904 }
    10905
    10906 aggregated = FALSE;
    10907 infeasible = FALSE;
    10908
    10909 /* perform the multi-aggregation */
    10910 SCIP_CALL( SCIPmultiaggregateVar(scip, bestvar, naggrs, aggrvars, aggrcoefs, aggrconst, &infeasible, &aggregated) );
    10911
    10912 /** @todo handle this case properly with weak and strong implied integrality */
    10913 /* if the multi-aggregated bestvar is enforced but not strongly implied integral, we need to convert implied
    10914 * integral to integer variables because integrality of the multi-aggregated variable must hold
    10915 */
    10916 if( !infeasible && aggregated && SCIPvarGetType(bestvar) != SCIP_VARTYPE_CONTINUOUS && SCIPvarGetImplType(bestvar) != SCIP_IMPLINTTYPE_STRONG )
    10917 {
    10918 SCIP_Bool infeasiblevartypechg = FALSE;
    10919
    10920 for( j = 0; j < naggrs; ++j )
    10921 {
    10922 /* if the multi-aggregation was not infeasible, then setting implied integral to integer should not
    10923 * lead to infeasibility
    10924 */
    10926 {
    10927 if( SCIPvarGetType(aggrvars[j]) == SCIP_VARTYPE_CONTINUOUS )
    10928 {
    10929 SCIP_CALL( SCIPchgVarType(scip, aggrvars[j], SCIP_VARTYPE_INTEGER, &infeasiblevartypechg) );
    10930 assert(!infeasiblevartypechg);
    10931 }
    10932 SCIP_CALL( SCIPchgVarImplType(scip, aggrvars[j], SCIP_IMPLINTTYPE_NONE, &infeasiblevartypechg) );
    10933 assert(!infeasiblevartypechg);
    10934 (*nchgvartypes)++;
    10935 }
    10936 }
    10937 }
    10938
    10939 /* free temporary memory */
    10940 SCIPfreeBufferArray(scip, &aggrcoefs);
    10941 SCIPfreeBufferArray(scip, &aggrvars);
    10942
    10943 /* check for infeasible aggregation */
    10944 if( infeasible )
    10945 {
    10946 SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
    10947 *cutoff = TRUE;
    10948 return SCIP_OKAY;
    10949 }
    10950
    10951 /* delete the constraint, if the aggregation was successful */
    10952 if( aggregated )
    10953 {
    10954 SCIP_CALL( SCIPdelCons(scip, cons) );
    10955
    10956 if( !consdata->upgraded )
    10957 (*ndelconss)++;
    10958 (*naggrvars)++;
    10959 }
    10960 else
    10961 {
    10962 SCIPdebugMsg(scip, "aggregation non successful!\n");
    10963 }
    10964 }
    10965
    10966 return SCIP_OKAY;
    10967}
    10968
    10969#define BINWEIGHT 1
    10970#define INTWEIGHT 4
    10971#define CONTWEIGHT 8
    10972
    10973/** gets weight for variable in a "weighted number of variables" sum */
    10974static
    10976 SCIP_VAR* var /**< variable to get weight for */
    10977 )
    10978{
    10979 if( SCIPvarIsImpliedIntegral(var) )
    10980 return INTWEIGHT;
    10981
    10982 switch( SCIPvarGetType(var) )
    10983 {
    10985 return BINWEIGHT;
    10987 return INTWEIGHT;
    10989 return CONTWEIGHT;
    10990 default:
    10991 SCIPerrorMessage("unknown variable type\n");
    10992 SCIPABORT();
    10993 return 0; /*lint !e527*/
    10994 } /*lint !e788*/
    10995}
    10996
    10997/** tries to aggregate variables in equations a^Tx = lhs
    10998 * in case there are at most two binary variables with an odd coefficient and all other
    10999 * variables are not continuous and have an even coefficient then:
    11000 * - exactly one odd binary variables
    11001 * this binary variables y can be fixed to 0 if the lhs is even and to 1 if the lhs is odd
    11002 * - lhs is odd -> y = 1
    11003 * - lhs is even -> y = 0
    11004 * - exactly two odd binary variables
    11005 * aggregate the two binary variables with odd coefficient
    11006 * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
    11007 * - lhs is even -> both have to take the same value -> var1 - var2 = 0
    11008 */
    11009static
    11011 SCIP* scip, /**< SCIP data structure */
    11012 SCIP_CONS* cons, /**< linear constraint */
    11013 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
    11014 int* nfixedvars, /**< pointer to count number of fixed variables */
    11015 int* naggrvars /**< pointer to count number of aggregated variables */
    11016 )
    11017{ /*lint --e{715}*/
    11018 SCIP_CONSDATA* consdata;
    11019 SCIP_Bool success;
    11020
    11021 assert( scip != NULL );
    11022 assert( cons != NULL );
    11023
    11024 consdata = SCIPconsGetData(cons);
    11025 assert( consdata != NULL );
    11026
    11027 /* check if the linear constraint is an equation with integral right hand side */
    11028 if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) || !SCIPisIntegral(scip, consdata->lhs) )
    11029 return SCIP_OKAY;
    11030
    11031 /* try to fix and aggregated variables until nothing is possible anymore */
    11032 do
    11033 {
    11034 int v;
    11035 int nvars;
    11036 SCIP_VAR** vars;
    11037 SCIP_Real* vals;
    11038 SCIP_Real lhs;
    11039 SCIP_Bool lhsodd;
    11040
    11041 SCIP_Bool infeasible;
    11042 SCIP_Bool fixed;
    11043 SCIP_Bool aggregated;
    11044 SCIP_Bool redundant;
    11045
    11046 SCIP_VAR* var1;
    11047 SCIP_VAR* var2;
    11048 int noddvars;
    11049
    11050 success = FALSE;
    11051
    11052 lhs = consdata->lhs;
    11053 vars = consdata->vars;
    11054 vals = consdata->vals;
    11055 nvars = consdata->nvars;
    11056
    11057 assert( !SCIPisInfinity(scip, ABS(lhs)) );
    11058
    11059 var1 = NULL;
    11060 var2 = NULL;
    11061 noddvars = 0;
    11062
    11063 /* search for binary variables with an odd coefficient */
    11064 for( v = 0; v < nvars && noddvars < 3; ++v )
    11065 {
    11066 SCIP_Longint val;
    11067
    11068 /* all coefficients and variables have to be integral */
    11069 if( !SCIPvarIsIntegral(vars[v]) || !SCIPisIntegral(scip, vals[v]) )
    11070 return SCIP_OKAY;
    11071
    11072 val = (SCIP_Longint)SCIPfeasFloor(scip, vals[v]);
    11073 if( val % 2 != 0 )
    11074 {
    11075 /* the odd values have to belong to binary variables */
    11076 if( !SCIPvarIsBinary(vars[v]) )
    11077 return SCIP_OKAY;
    11078
    11079 if( noddvars == 0 )
    11080 var1 = vars[v];
    11081 else
    11082 var2 = vars[v];
    11083
    11084 noddvars++;
    11085 }
    11086 }
    11087
    11088 /* check lhs is odd or even */
    11089 lhsodd = (((SCIP_Longint)SCIPfeasFloor(scip, lhs)) % 2 != 0);
    11090
    11091 if( noddvars == 1 )
    11092 {
    11093 assert( var1 != NULL );
    11094
    11095 SCIPdebugMsg(scip, "linear constraint <%s>: try fixing variable <%s> to <%g>\n",
    11096 SCIPconsGetName(cons), SCIPvarGetName(var1), lhsodd ? 1.0 : 0.0);
    11097
    11098 SCIP_CALL( SCIPfixVar(scip, var1, lhsodd? 1.0 : 0.0, &infeasible, &fixed) );
    11099
    11100 /* check for infeasibility of fixing */
    11101 if( infeasible )
    11102 {
    11103 SCIPdebugMsg(scip, " -> infeasible fixing\n");
    11104 *cutoff = TRUE;
    11105 return SCIP_OKAY;
    11106 }
    11107
    11108 if( fixed )
    11109 {
    11110 SCIPdebugMsg(scip, " -> feasible fixing\n");
    11111 (*nfixedvars)++;
    11112 success = TRUE;
    11113 }
    11114 }
    11115 else if( noddvars == 2 )
    11116 {
    11117 assert( var1 != NULL );
    11118 assert( var2 != NULL );
    11119
    11120 /* aggregate the two variables with odd coefficient
    11121 * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
    11122 * - lhs is even -> both have to take the same value -> var1 - var2 = 0
    11123 */
    11124 SCIPdebugMsg(scip, "linear constraint <%s>: try aggregation of variables <%s> and <%s>\n",
    11125 SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
    11126
    11127 SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, lhsodd ? 1.0 : -1.0,
    11128 lhsodd ? 1.0 : 0.0, &infeasible, &redundant, &aggregated) );
    11129
    11130 /* check for infeasibility of aggregation */
    11131 if( infeasible )
    11132 {
    11133 SCIPdebugMsg(scip, " -> infeasible aggregation\n");
    11134 *cutoff = TRUE;
    11135 return SCIP_OKAY;
    11136 }
    11137
    11138 /* count the aggregation */
    11139 if( aggregated )
    11140 {
    11141 SCIPdebugMsg(scip, " -> feasible aggregation\n");
    11142 (*naggrvars)++;
    11143 success = TRUE;
    11144 }
    11145 }
    11146
    11147 if( success )
    11148 {
    11149 /* apply fixings and aggregation to successfully rerun this presolving step */
    11150 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
    11151
    11152 if( infeasible )
    11153 {
    11154 SCIPdebugMsg(scip, " -> infeasible fixing\n");
    11155 *cutoff = TRUE;
    11156 return SCIP_OKAY;
    11157 }
    11158
    11159 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
    11160
    11161 if( infeasible )
    11162 {
    11163 SCIPdebugMsg(scip, " -> infeasible normalization\n");
    11164 *cutoff = TRUE;
    11165 return SCIP_OKAY;
    11166 }
    11167 }
    11168 }
    11169 while( success && consdata->nvars >= 1 );
    11170
    11171 return SCIP_OKAY;
    11172}
    11173
    11174
    11175
    11176/** sorting method for constraint data, compares two variables on given indices, continuous variables will be sorted to
    11177 * the end and for all other variables the sortation will be in non-increasing order of their absolute value of the
    11178 * coefficients
    11179 */
    11180static
    11182{ /*lint --e{715}*/
    11183 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
    11184 SCIP_Real value;
    11185
    11186 assert(consdata != NULL);
    11187 assert(0 <= ind1 && ind1 < consdata->nvars);
    11188 assert(0 <= ind2 && ind2 < consdata->nvars);
    11189
    11190 SCIP_Bool varcont1 = !SCIPvarIsIntegral(consdata->vars[ind1]);
    11191 SCIP_Bool varcont2 = !SCIPvarIsIntegral(consdata->vars[ind2]);
    11192
    11193 if( varcont1 )
    11194 {
    11195 /* continuous variables will be sorted to the back */
    11196 if( varcont1 != varcont2 )
    11197 return +1;
    11198 /* both variables are continuous */
    11199 else
    11200 return 0;
    11201 }
    11202 /* continuous variables will be sorted to the back */
    11203 else if( varcont2 )
    11204 return -1;
    11205
    11206 value = REALABS(consdata->vals[ind2]) - REALABS(consdata->vals[ind1]);
    11207
    11208 /* for all non-continuous variables, the variables are sorted after decreasing absolute coefficients */
    11209 return (value > 0 ? +1 : (value < 0 ? -1 : 0));
    11210}
    11211
    11212/** tries to simplify coefficients in ranged row of the form lhs <= a^Tx <= rhs
    11213 *
    11214 * 1. lhs <= a^Tx <= rhs, x binary, lhs > 0, forall a_i >= lhs, a_i <= rhs, and forall pairs a_i + a_j > rhs,
    11215 * then we can change this constraint to 1^Tx = 1
    11216 */
    11217static
    11219 SCIP* scip, /**< SCIP data structure */
    11220 SCIP_CONS* cons, /**< linear constraint */
    11221 int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
    11222 int* nchgsides /**< pointer to store the amount of changed sides */
    11223 )
    11224{
    11225 SCIP_CONSDATA* consdata;
    11226 SCIP_VAR** vars;
    11227 SCIP_Real* vals;
    11228 SCIP_Real minval;
    11229 SCIP_Real secondminval;
    11230 SCIP_Real maxval;
    11231 SCIP_Real lhs;
    11232 SCIP_Real rhs;
    11233 int nvars;
    11234 int v;
    11235
    11236 /* we must not change a modifiable constraint in any way */
    11237 if( SCIPconsIsModifiable(cons) )
    11238 return SCIP_OKAY;
    11239
    11240 if( SCIPconsIsDeleted(cons) )
    11241 return SCIP_OKAY;
    11242
    11243 consdata = SCIPconsGetData(cons);
    11244 assert(consdata != NULL);
    11245
    11246 nvars = consdata->nvars;
    11247
    11248 /* do not check empty or bound-constraints */
    11249 if( nvars < 2 )
    11250 return SCIP_OKAY;
    11251
    11252 lhs = consdata->lhs;
    11253 rhs = consdata->rhs;
    11254 assert(!SCIPisInfinity(scip, -lhs));
    11255 assert(!SCIPisInfinity(scip, rhs));
    11256 assert(!SCIPisNegative(scip, rhs));
    11257
    11258 /* sides must be positive and different to detect set partition */
    11259 if( !SCIPisPositive(scip, lhs) || !SCIPisLT(scip, lhs, rhs) )
    11260 return SCIP_OKAY;
    11261
    11262 vals = consdata->vals;
    11263 vars = consdata->vars;
    11264 assert(vars != NULL);
    11265 assert(vals != NULL);
    11266
    11267 minval = SCIP_INVALID;
    11268 secondminval = SCIP_INVALID;
    11269 maxval = -SCIP_INVALID;
    11270
    11271 for( v = nvars - 1; v >= 0; --v )
    11272 {
    11273 if( SCIPvarIsBinary(vars[v]) )
    11274 {
    11275 if( minval > vals[v] || minval == SCIP_INVALID ) /*lint !e777*/
    11276 {
    11277 secondminval = minval;
    11278 minval = vals[v];
    11279 }
    11280 else if( secondminval > vals[v] || secondminval == SCIP_INVALID ) /*lint !e777*/
    11281 secondminval = vals[v];
    11282
    11283 if( maxval < vals[v] || maxval == -SCIP_INVALID ) /*lint !e777*/
    11284 maxval = vals[v];
    11285 }
    11286 else
    11287 break;
    11288 }
    11289
    11290 /* check if all variables are binary, we can choose one, and need to choose at most one */
    11291 if( v == -1 && SCIPisGE(scip, minval, lhs) && SCIPisLE(scip, maxval, rhs)
    11292 && SCIPisGT(scip, minval + secondminval, rhs) )
    11293 {
    11294 /* change all coefficients to 1.0 */
    11295 for( v = nvars - 1; v >= 0; --v )
    11296 {
    11297 SCIP_CALL( chgCoefPos(scip, cons, v, 1.0) );
    11298 }
    11299 (*nchgcoefs) += nvars;
    11300
    11301 /* replace old right and left hand side with 1.0 */
    11302 SCIP_CALL( chgRhs(scip, cons, 1.0) );
    11303 SCIP_CALL( chgLhs(scip, cons, 1.0) );
    11304 (*nchgsides) += 2;
    11305 }
    11306
    11307 return SCIP_OKAY;
    11308}
    11309
    11310/** tries to simplify coefficients and delete variables in constraints of the form lhs <= a^Tx <= rhs
    11311 *
    11312 * for both-sided constraints only @see rangedRowSimplify() will be called
    11313 *
    11314 * for one-sided constraints there are several different coefficient reduction steps which will be applied
    11315 *
    11316 * 1. We try to determine parts of the constraint which will not change anything on (in-)feasibility of the constraint
    11317 *
    11318 * e.g. 5x1 + 5x2 + 3z1 <= 8 => 3z1 is redundant if all x are binary and -2 < 3z1 <= 3
    11319 *
    11320 * 2. We try to remove redundant fractional parts in a constraint
    11321 *
    11322 * e.g. 5.2x1 + 5.1x2 + 3x3 <= 8.3 => will be changed to 5x1 + 5x2 + 3x3 <= 8 if all x are binary
    11323 *
    11324 * 3. We are using the greatest common divisor for further reductions
    11325 *
    11326 * e.g. 10x1 + 5y2 + 5x3 + 3x4 <= 15 => will be changed to 2x1 + y2 + x3 + x4 <= 3 if all xi are binary and y2 is
    11327 * integral
    11328 */
    11329static
    11331 SCIP* scip, /**< SCIP data structure */
    11332 SCIP_CONS* cons, /**< linear constraint */
    11333 int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
    11334 int* nchgsides, /**< pointer to store the amount of changed sides */
    11335 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
    11336 )
    11337{
    11338 SCIP_CONSDATA* consdata;
    11339 SCIP_VAR** vars;
    11340 SCIP_Real* vals;
    11341 int* perm;
    11342 SCIP_Real minactsub;
    11343 SCIP_Real maxactsub;
    11344 SCIP_Real siderest;
    11345 SCIP_Real feastol;
    11346 SCIP_Real newcoef;
    11347 SCIP_Real absval;
    11348 SCIP_Real minact;
    11349 SCIP_Real maxact;
    11350 SCIP_Real side;
    11351 SCIP_Real lhs;
    11352 SCIP_Real rhs;
    11353 SCIP_Real lb;
    11354 SCIP_Real ub;
    11355 SCIP_Longint restcoef;
    11356 SCIP_Longint oldgcd;
    11357 SCIP_Longint rest;
    11358 SCIP_Longint gcd;
    11359 SCIP_Bool isminsettoinfinity;
    11360 SCIP_Bool ismaxsettoinfinity;
    11361 SCIP_Bool ismintight;
    11362 SCIP_Bool ismaxtight;
    11363 SCIP_Bool allcoefintegral;
    11364 SCIP_Bool onlybin;
    11365 SCIP_Bool hasrhs;
    11366 SCIP_Bool haslhs;
    11367 int oldnchgcoefs; /* cppcheck-suppress unassignedVariable */
    11368 int oldnchgsides; /* cppcheck-suppress unassignedVariable */
    11369 int foundbin;
    11370 int candpos;
    11371 int candpos2;
    11372 int offsetv;
    11373 int nvars;
    11374 int v;
    11375 int w;
    11376
    11377 assert(scip != NULL);
    11378 assert(cons != NULL);
    11379 assert(nchgcoefs != NULL);
    11380 assert(nchgsides != NULL);
    11381
    11382 *infeasible = FALSE;
    11383
    11384 /* we must not change a modifiable constraint in any way */
    11385 if( SCIPconsIsModifiable(cons) )
    11386 return SCIP_OKAY;
    11387
    11388 if( SCIPconsIsDeleted(cons) )
    11389 return SCIP_OKAY;
    11390
    11391 consdata = SCIPconsGetData(cons);
    11392 assert(consdata != NULL);
    11393
    11394 nvars = consdata->nvars;
    11395
    11396 /* do not check empty or bound-constraints */
    11397 if( nvars <= 2 )
    11398 return SCIP_OKAY;
    11399
    11400 /* update maximal activity delta if necessary */
    11401 if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
    11403
    11404 assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
    11405 assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
    11406 checkMaxActivityDelta(scip, consdata);
    11407
    11408 /* @todo the following might be too hard, check which steps can be applied and what code must be corrected
    11409 * accordingly
    11410 */
    11411 /* can only work with valid non-infinity activities per variable */
    11412 if( SCIPisInfinity(scip, consdata->maxactdelta) )
    11413 return SCIP_OKAY;
    11414
    11415 /* @todo: change the following: due to vartype changes, the status of the normalization can be wrong, need an event
    11416 * but the eventsystem seems to be full
    11417 */
    11418 consdata->normalized = FALSE;
    11419
    11420 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
    11421 assert(nvars == consdata->nvars);
    11422
    11423 if( *infeasible )
    11424 return SCIP_OKAY;
    11425
    11426 if( !consdata->normalized )
    11427 return SCIP_OKAY;
    11428
    11429 lhs = consdata->lhs;
    11430 rhs = consdata->rhs;
    11431 assert(!SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs));
    11432 assert(!SCIPisNegative(scip, rhs));
    11433
    11434 if( !SCIPisInfinity(scip, -lhs) )
    11435 haslhs = TRUE;
    11436 else
    11437 haslhs = FALSE;
    11438
    11439 if( !SCIPisInfinity(scip, rhs) )
    11440 hasrhs = TRUE;
    11441 else
    11442 hasrhs = FALSE;
    11443
    11444 /* @todo extend both-sided simplification */
    11445 if( haslhs && hasrhs )
    11446 {
    11447 SCIP_CALL( rangedRowSimplify(scip, cons, nchgcoefs, nchgsides ) );
    11448
    11449 return SCIP_OKAY;
    11450 }
    11451 assert(haslhs != hasrhs);
    11452
    11453 /* if we have a normalized inequality (not ranged) the one side should be positive, @see normalizeCons() */
    11454 assert(!hasrhs || !SCIPisNegative(scip, rhs));
    11455 assert(!haslhs || !SCIPisNegative(scip, lhs));
    11456
    11457 /* get temporary memory to store the sorted permutation */
    11458 SCIP_CALL( SCIPallocBufferArray(scip, &perm, nvars) );
    11459
    11460 /* call sorting method, order continuous variables to the end and all other variables after non-increasing absolute
    11461 * value of their coefficients
    11462 */
    11463 SCIPsort(perm, consdataCompSim, (void*)consdata, nvars);
    11464
    11465 /* perform sorting after permutation array */
    11466 permSortConsdata(consdata, perm, nvars);
    11467 consdata->indexsorted = FALSE;
    11468 consdata->coefsorted = FALSE;
    11469
    11470 vars = consdata->vars;
    11471 vals = consdata->vals;
    11472 assert(vars != NULL);
    11473 assert(vals != NULL);
    11474 assert(!consdata->validmaxabsval || SCIPisFeasEQ(scip, consdata->maxabsval, REALABS(vals[0])) || !SCIPvarIsIntegral(vars[nvars - 1]));
    11475
    11476 /* free temporary memory */
    11477 SCIPfreeBufferArray(scip, &perm);
    11478
    11479 /* only check constraints with at least two non continuous variables */
    11480 if( !SCIPvarIsIntegral(vars[1]) )
    11481 return SCIP_OKAY;
    11482
    11483 /* do not process constraints when all coefficients are 1.0 */
    11484 if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) && ((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs))) )
    11485 return SCIP_OKAY;
    11486
    11487 feastol = SCIPfeastol(scip);
    11488
    11489 SCIPdebugMsg(scip, "starting simplification of coefficients\n");
    11491
    11492 /* get global activities */
    11493 consdataGetGlbActivityBounds(scip, consdata, FALSE, &minact, &maxact,
    11494 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
    11495
    11496 /* cannot work with infinite activities */
    11497 if( isminsettoinfinity || ismaxsettoinfinity )
    11498 return SCIP_OKAY;
    11499
    11500 assert(ismintight);
    11501 assert(ismaxtight);
    11502 assert(maxact > minact);
    11503 assert(!SCIPisInfinity(scip, -minact));
    11504 assert(!SCIPisInfinity(scip, maxact));
    11505
    11506 v = 0;
    11507 offsetv = -1;
    11508 side = haslhs ? lhs : rhs;
    11509 minactsub = minact;
    11510 maxactsub = maxact;
    11511
    11512 /* we now determine coefficients as large as the side of the constraint to retrieve a better reduction where we
    11513 * do not need to look at the large coefficients
    11514 *
    11515 * e.g. all x are binary, z are positive integer
    11516 * c1: +5x1 + 5x2 + 3x3 + 3x4 + x5 >= 5 (x5 is redundant and does not change (in-)feasibility of this constraint)
    11517 * c2: +4x1 + 4x2 + 3x3 + 3x4 + x5 >= 4 (gcd (without the coefficient of x5) after the large coefficients is 3
    11518 * c3: +30x1 + 29x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 30 (gcd (without the coefficient of x2) after the large coefficients is 7
    11519 *
    11520 * can be changed to
    11521 *
    11522 * c1: +6x1 + 6x2 + 3x3 + 3x4 >= 6 (will be changed to c1: +2x1 + 2x2 + x3 + x4 >= 2)
    11523 * c2: +6x1 + 6x2 + 3x3 + 3x4 + 3x5 >= 6 (will be changed to c2: +2x1 + 2x2 + x3 + x4 + x5 >= 2)
    11524 * c3: +28x1 + 28x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 28 (will be changed to c3: +4x1 + 4x2 + 2x3 + 2z1 + x5 + x6 <= 4)
    11525 */
    11526
    11527 /* if the minimal activity is negative and we found more than one variable with a coefficient bigger than the left
    11528 * hand side, we cannot apply the extra reduction step and need to reset v
    11529 *
    11530 * e.g. 7x1 + 7x2 - 4x3 - 4x4 >= 7 => xi = 1 for all i is not a solution, but if we would do a change on the
    11531 * coefficients due to the gcd on the "small" coefficients we would get 8x1 + 8x2 - 4x3 - 4x4 >= 8 were xi = 1
    11532 * for all i is a solution
    11533 *
    11534 * also redundancy of variables would not be correctly determined in such a case
    11535 */
    11536 if( nvars > 2 && SCIPisEQ(scip, vals[0], side) && !SCIPisNegative(scip, minactsub) )
    11537 {
    11538 v = 1;
    11539
    11540 while( v < nvars && SCIPisEQ(scip, side, vals[v]) )
    11541 {
    11542 /* if we have integer variable with "side"-coefficients but also with a lower bound greater than 0 we stop this
    11543 * extra step, which might have worked
    11544 */
    11545 if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
    11546 {
    11547 v = 0;
    11548 break;
    11549 }
    11550
    11551 ++v;
    11552 }
    11553
    11554 /* easy and quick fix: if all coefficients were equal to the side, we cannot apply further simplifications */
    11555 /* todo find numerically stable normalization conditions to scale this cons to have coefficients almost equal to 1 */
    11556 if( v == nvars )
    11557 return SCIP_OKAY;
    11558
    11559 /* cannot work with continuous variables which have a big coefficient */
    11560 if( v > 0 && !SCIPvarIsIntegral(vars[v - 1]) )
    11561 return SCIP_OKAY;
    11562
    11563 /* big negative coefficient, do not try to use the extra coefficient reduction step */
    11564 if( SCIPisEQ(scip, side, -vals[v]) )
    11565 v = 0;
    11566
    11567 /* all but one variable are processed or the next variable is continuous we cannot perform the extra coefficient
    11568 * reduction
    11569 */
    11570 if( v == nvars - 1 || !SCIPvarIsIntegral(vars[v]) )
    11571 v = 0;
    11572
    11573 if( v > 0 )
    11574 {
    11575 assert(v < nvars);
    11576
    11577 offsetv = v - 1;
    11578
    11579 for( w = 0; w < v; ++w )
    11580 {
    11581 lb = SCIPvarGetLbGlobal(vars[w]);
    11582 ub = SCIPvarGetUbGlobal(vars[w]);
    11583
    11584 assert(vals[w] > 0);
    11585
    11586 /* update residual activities */
    11587 maxactsub -= ub * vals[w];
    11588 minactsub -= lb * vals[w];
    11589 assert(maxactsub > minactsub);
    11590 }
    11591 }
    11592 }
    11593
    11594 /* find and remove redundant variables which do not interact with the (in-)feasibility of this constraint
    11595 *
    11596 * e.g. let all x are binary and y1 is continuous with bounds [-3,1] then we can reduce
    11597 *
    11598 * 15x1 + 15x2 + 7x3 + 3x4 + y1 <= 26
    11599 * to
    11600 * 15x1 + 15x2 <= 26 <=> x1 + x2 <= 1
    11601 */
    11602 if( nvars > 2 && SCIPisIntegral(scip, vals[v]) )
    11603 {
    11604 SCIP_Bool redundant = FALSE;
    11605 SCIP_Bool numericsok;
    11606 SCIP_Bool rredundant;
    11607 SCIP_Bool lredundant;
    11608
    11609 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
    11610 assert(gcd >= 1);
    11611
    11612 if( v == 0 )
    11613 {
    11614 lb = SCIPvarGetLbGlobal(vars[0]);
    11615 ub = SCIPvarGetUbGlobal(vars[0]);
    11616
    11617 /* update residual activities */
    11618 if( vals[0] > 0 )
    11619 {
    11620 maxactsub -= ub * vals[0];
    11621 minactsub -= lb * vals[0];
    11622 }
    11623 else
    11624 {
    11625 maxactsub -= lb * vals[0];
    11626 minactsub -= ub * vals[0];
    11627 }
    11628 assert(maxactsub > minactsub);
    11629 ++v;
    11630 }
    11631
    11632 siderest = -SCIP_INVALID;
    11633 allcoefintegral = TRUE;
    11634
    11635 /* check if some variables always fit into the given constraint */
    11636 for( ; v < nvars - 1; ++v )
    11637 {
    11638 if( !SCIPvarIsIntegral(vars[v]) )
    11639 break;
    11640
    11641 if( !SCIPisIntegral(scip, vals[v]) )
    11642 {
    11643 allcoefintegral = FALSE;
    11644 break;
    11645 }
    11646
    11647 /* calculate greatest common divisor for all general and binary variables */
    11648 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
    11649
    11650 if( gcd == 1 )
    11651 break;
    11652
    11653 lb = SCIPvarGetLbGlobal(vars[v]);
    11654 ub = SCIPvarGetUbGlobal(vars[v]);
    11655
    11656 assert(!SCIPisInfinity(scip, -lb));
    11657 assert(!SCIPisInfinity(scip, ub));
    11658
    11659 /* update residual activities */
    11660 if( vals[v] > 0 )
    11661 {
    11662 maxactsub -= ub * vals[v];
    11663 minactsub -= lb * vals[v];
    11664 }
    11665 else
    11666 {
    11667 maxactsub -= lb * vals[v];
    11668 minactsub -= ub * vals[v];
    11669 }
    11670 assert(SCIPisGE(scip, maxactsub, minactsub));
    11671
    11672 if( hasrhs )
    11673 {
    11674 /* determine the remainder of the right hand side and the gcd */
    11675 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
    11676 }
    11677 else
    11678 {
    11679 /* determine the remainder of the left hand side and the gcd */
    11680 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
    11681 if( SCIPisZero(scip, siderest) )
    11682 siderest = gcd;
    11683 }
    11684
    11685 rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
    11686 lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
    11687
    11688 /* early termination if the activities deceed the gcd */
    11689 if( offsetv == -1 && (rredundant || lredundant) )
    11690 {
    11691 redundant = TRUE;
    11692 break;
    11693 }
    11694 }
    11695 assert(v < nvars || (offsetv >= 0 && gcd > 1));
    11696
    11697 if( !redundant )
    11698 {
    11699 if( hasrhs )
    11700 {
    11701 /* determine the remainder of the right hand side and the gcd */
    11702 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
    11703 }
    11704 else
    11705 {
    11706 /* determine the remainder of the left hand side and the gcd */
    11707 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
    11708 if( SCIPisZero(scip, siderest) )
    11709 siderest = gcd;
    11710 }
    11711 }
    11712 else
    11713 ++v;
    11714
    11715 SCIPdebugMsg(scip, "stopped at pos %d (of %d), subactivities [%g, %g], redundant = %u, hasrhs = %u, siderest = %g, gcd = %" SCIP_LONGINT_FORMAT ", offset position for 'side' coefficients = %d\n",
    11716 v, nvars, minactsub, maxactsub, redundant, hasrhs, siderest, gcd, offsetv);
    11717
    11718 /* to avoid inconsistencies due to numerics, check that the full and partial activities have
    11719 * reasonable absolute values */
    11720 numericsok = REALABS(maxact) < MAXACTVAL && REALABS(maxactsub) < MAXACTVAL && REALABS(minact) < MAXACTVAL &&
    11721 REALABS(minactsub) < MAXACTVAL;
    11722
    11723 rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
    11724 lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
    11725
    11726 /* check if we can remove redundant variables */
    11727 if( v < nvars && numericsok && (redundant || (offsetv == -1 && (rredundant || lredundant))) )
    11728 {
    11729 SCIP_Real oldcoef;
    11730
    11731 /* double check the redundancy */
    11732#ifndef NDEBUG
    11733 SCIP_Real tmpminactsub = 0.0;
    11734 SCIP_Real tmpmaxactsub = 0.0;
    11735
    11736 /* recompute residual activities */
    11737 for( w = v; w < nvars; ++w )
    11738 {
    11739 lb = SCIPvarGetLbGlobal(vars[w]);
    11740 ub = SCIPvarGetUbGlobal(vars[w]);
    11741
    11742 assert(!SCIPisInfinity(scip, -lb));
    11743 assert(!SCIPisInfinity(scip, ub));
    11744
    11745 /* update residual activities */
    11746 if( vals[w] > 0 )
    11747 {
    11748 tmpmaxactsub += ub * vals[w];
    11749 tmpminactsub += lb * vals[w];
    11750 }
    11751 else
    11752 {
    11753 tmpmaxactsub += lb * vals[w];
    11754 tmpminactsub += ub * vals[w];
    11755 }
    11756 assert(tmpmaxactsub >= tmpminactsub);
    11757 }
    11758
    11759 if( hasrhs )
    11760 {
    11761 assert(offsetv == -1);
    11762
    11763 /* determine the remainder of the right hand side and the gcd */
    11764 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
    11765 }
    11766 else
    11767 {
    11768 /* determine the remainder of the left hand side and the gcd */
    11769 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
    11770 if( SCIPisZero(scip, siderest) )
    11771 siderest = gcd;
    11772 }
    11773
    11774 /* is the redundancy really fulfilled */
    11775 assert((hasrhs && SCIPisFeasLE(scip, tmpmaxactsub, siderest) && tmpminactsub > siderest - gcd) ||
    11776 (haslhs && tmpmaxactsub < siderest && SCIPisFeasGE(scip, tmpminactsub, siderest - gcd)));
    11777#endif
    11778
    11779 SCIPdebugMsg(scip, "removing %d last variables from constraint <%s>, because they never change anything on the feasibility of this constraint\n",
    11780 nvars - v, SCIPconsGetName(cons));
    11781
    11782 /* remove redundant variables */
    11783 for( w = nvars - 1; w >= v; --w )
    11784 {
    11785 SCIP_CALL( delCoefPos(scip, cons, w) );
    11786 }
    11787 (*nchgcoefs) += (nvars - v);
    11788
    11789 assert(w >= 0);
    11790
    11791 oldcoef = vals[w];
    11792
    11793 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
    11794 assert(vars == consdata->vars);
    11795 assert(vals == consdata->vals);
    11796 assert(w < consdata->nvars);
    11797
    11798 if( *infeasible )
    11799 return SCIP_OKAY;
    11800
    11801 /* compute new greatest common divisor due to normalization */
    11802 gcd = (SCIP_Longint)(gcd / (oldcoef/vals[w]) + feastol);
    11803 assert(gcd >= 1);
    11804
    11805 /* update side */
    11806 if( hasrhs )
    11807 {
    11808 /* replace old with new right hand side */
    11809 SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
    11810 rhs = consdata->rhs;
    11811 }
    11812 else
    11813 {
    11814 if( SCIPisFeasGT(scip, oldcoef/vals[w], 1.0) )
    11815 {
    11816 SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
    11817 lhs = consdata->lhs;
    11818 }
    11819 else
    11820 assert(offsetv == -1 || SCIPisEQ(scip, vals[offsetv], consdata->lhs));
    11821 }
    11822 ++(*nchgsides);
    11823
    11824 assert(!hasrhs || !SCIPisNegative(scip, rhs));
    11825 assert(!haslhs || !SCIPisNegative(scip, lhs));
    11826
    11827 /* get new constraint data */
    11828 nvars = consdata->nvars;
    11829 assert(nvars > 0);
    11830
    11831 allcoefintegral = TRUE;
    11832
    11833#ifndef NDEBUG
    11834 /* check integrality */
    11835 for( w = offsetv + 1; w < nvars; ++w )
    11836 {
    11837 assert(SCIPisIntegral(scip, vals[w]));
    11838 }
    11839#endif
    11841 }
    11842
    11843 /* try to find a better gcd, when having large coefficients */
    11844 if( offsetv >= 0 && gcd == 1 )
    11845 {
    11846 /* calculate greatest common divisor for all general variables */
    11847 gcd = (SCIP_Longint)(REALABS(vals[nvars - 1]) + feastol);
    11848
    11849 if( gcd > 1 )
    11850 {
    11851 gcd = -1;
    11852 candpos = -1;
    11853
    11854 for( v = nvars - 1; v > offsetv; --v )
    11855 {
    11856 assert(!SCIPisZero(scip, vals[v]));
    11857 if( !SCIPvarIsIntegral(vars[v]) )
    11858 break;
    11859
    11860 if( !SCIPisIntegral(scip, vals[v]) )
    11861 {
    11862 allcoefintegral = FALSE;
    11863 break;
    11864 }
    11865
    11866 oldgcd = gcd;
    11867
    11868 if( gcd == -1 )
    11869 {
    11870 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
    11871 assert(gcd >= 1);
    11872 }
    11873 else
    11874 {
    11875 /* calculate greatest common divisor for all general and binary variables */
    11876 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
    11877 }
    11878
    11879 /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
    11880 * can stop searching
    11881 */
    11882 if( gcd == 1 )
    11883 {
    11884 if( !SCIPvarIsBinary(vars[v]) )
    11885 break;
    11886
    11887 /* found candidate */
    11888 if( candpos == -1 )
    11889 {
    11890 gcd = oldgcd;
    11891 candpos = v;
    11892 }
    11893 /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
    11894 else
    11895 break;
    11896 }
    11897 }
    11898 assert(v > offsetv || candpos > offsetv);
    11899 }
    11900 else
    11901 candpos = -1;
    11902 }
    11903 else
    11904 candpos = nvars - 1;
    11905
    11906 /* check last coefficient for integrality */
    11907 if( gcd > 1 && allcoefintegral && !redundant )
    11908 {
    11909 if( !SCIPisIntegral(scip, vals[nvars - 1]) )
    11910 allcoefintegral = FALSE;
    11911 }
    11912
    11913 /* check for further necessary coefficient adjustments */
    11914 if( offsetv >= 0 && gcd > 1 && allcoefintegral )
    11915 {
    11916 assert(offsetv + 1 < nvars);
    11917 assert(0 <= candpos && candpos < nvars);
    11918
    11919 if( SCIPvarIsIntegral(vars[candpos]) )
    11920 {
    11921 SCIP_Bool notchangable = FALSE;
    11922
    11923#ifndef NDEBUG
    11924 /* check integrality */
    11925 for( w = offsetv + 1; w < nvars; ++w )
    11926 {
    11927 assert(SCIPisIntegral(scip, vals[w]));
    11928 }
    11929#endif
    11930
    11931 if( vals[candpos] > 0 && SCIPvarIsBinary(vars[candpos]) &&
    11932 SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) < gcd )
    11933 {
    11934 /* determine the remainder of the side and the gcd */
    11935 if( hasrhs )
    11936 rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
    11937 else
    11938 rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
    11939 assert(rest >= 0);
    11940 assert(rest < gcd);
    11941
    11942 /* determine the remainder of the coefficient candidate and the gcd */
    11943 restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
    11944 assert(restcoef >= 1);
    11945 assert(restcoef < gcd);
    11946
    11947 if( hasrhs )
    11948 {
    11949 /* calculate new coefficient */
    11950 if( restcoef > rest )
    11951 newcoef = vals[candpos] - restcoef + gcd;
    11952 else
    11953 newcoef = vals[candpos] - restcoef;
    11954 }
    11955 else
    11956 {
    11957 /* calculate new coefficient */
    11958 if( rest == 0 || restcoef < rest )
    11959 newcoef = vals[candpos] - restcoef;
    11960 else
    11961 newcoef = vals[candpos] - restcoef + gcd;
    11962 }
    11963
    11964 /* done */
    11965
    11966 /* new coeffcient must not be zero if we would loose the implication that a variable needs to be 0 if
    11967 * another with the big coefficient was set to 1
    11968 */
    11969 if( hasrhs && SCIPisZero(scip, newcoef) )
    11970 {
    11971 notchangable = TRUE;
    11972 }
    11973 else if( SCIPisZero(scip, newcoef) )
    11974 {
    11975 /* delete old redundant coefficient */
    11976 SCIP_CALL( delCoefPos(scip, cons, candpos) );
    11977 ++(*nchgcoefs);
    11978 }
    11979 else
    11980 {
    11981 /* replace old with new coefficient */
    11982 SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
    11983 ++(*nchgcoefs);
    11984 }
    11985 }
    11986 else if( vals[candpos] < 0 || !SCIPvarIsBinary(vars[candpos]) )
    11987 {
    11988 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol));
    11989 }
    11990
    11991 /* correct side and big coefficients */
    11992 if( (!notchangable && hasrhs && ((!SCIPisFeasIntegral(scip, rhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(rhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd))) ||
    11993 ( haslhs && (!SCIPisFeasIntegral(scip, lhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(lhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd)) )
    11994 {
    11995 if( haslhs )
    11996 {
    11997 newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasCeil(scip, lhs/gcd) * gcd + feastol));
    11998
    11999 SCIP_CALL( chgLhs(scip, cons, newcoef) );
    12000 ++(*nchgsides);
    12001 }
    12002 else
    12003 {
    12004 assert(hasrhs);
    12005 newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasFloor(scip, rhs/gcd) * gcd + feastol));
    12006
    12007 SCIP_CALL( chgRhs(scip, cons, newcoef) );
    12008 ++(*nchgsides);
    12009 }
    12010
    12011 /* correct coefficients up front */
    12012 for( w = offsetv; w >= 0; --w )
    12013 {
    12014 assert(vals[w] > 0);
    12015
    12016 SCIP_CALL( chgCoefPos(scip, cons, w, newcoef) );
    12017 }
    12018 (*nchgcoefs) += (offsetv + 1);
    12019 }
    12020
    12021 if( !notchangable )
    12022 {
    12023 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
    12024 assert(vars == consdata->vars);
    12025 assert(vals == consdata->vals);
    12026
    12027 if( *infeasible )
    12028 return SCIP_OKAY;
    12029
    12030 /* get new constraint data */
    12031 nvars = consdata->nvars;
    12032 assert(nvars >= 2);
    12033
    12035
    12036 lhs = consdata->lhs;
    12037 rhs = consdata->rhs;
    12038 assert(!hasrhs || !SCIPisNegative(scip, rhs));
    12039 assert(!haslhs || !SCIPisNegative(scip, lhs));
    12040 }
    12041 }
    12042 }
    12043 }
    12044
    12045 /* @todo we still can remove continuous variables if they are redundant due to the non-integrality argument */
    12046 /* no continuous variables are left over */
    12047 if( !SCIPvarIsIntegral(vars[nvars - 1]) )
    12048 return SCIP_OKAY;
    12049
    12050 onlybin = TRUE;
    12051 allcoefintegral = TRUE;
    12052 /* check if all variables are of binary type */
    12053 for( v = nvars - 1; v >= 0; --v )
    12054 {
    12055 if( !SCIPvarIsBinary(vars[v]) )
    12056 onlybin = FALSE;
    12057 if( !SCIPisIntegral(scip, vals[v]) )
    12058 allcoefintegral = FALSE;
    12059 }
    12060
    12061 /* check if the non-integrality part of all integral variables is smaller than the non-inegrality part of the right
    12062 * hand side or bigger than the left hand side respectively, so we can make all of them integral
    12063 *
    12064 * @todo there are some steps missing ....
    12065 */
    12066 if( (hasrhs && !SCIPisFeasIntegral(scip, rhs)) || (haslhs && !SCIPisFeasIntegral(scip, lhs)) )
    12067 {
    12068 SCIP_Real val;
    12069 SCIP_Real newval;
    12070 SCIP_Real frac = 0.0;
    12071 SCIP_Bool found = FALSE;
    12072
    12073 if( hasrhs )
    12074 {
    12075 if( allcoefintegral )
    12076 {
    12077 /* replace old with new right hand side */
    12078 SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
    12079 ++(*nchgsides);
    12080 }
    12081 else
    12082 {
    12083 siderest = rhs - SCIPfloor(scip, rhs);
    12084
    12085 /* try to round down all non-integral coefficients */
    12086 for( v = nvars - 1; v >= 0; --v )
    12087 {
    12088 val = vals[v];
    12089
    12090 /* add up all possible fractional parts */
    12091 if( !SCIPisIntegral(scip, val) )
    12092 {
    12093 lb = SCIPvarGetLbGlobal(vars[v]);
    12094 ub = SCIPvarGetUbGlobal(vars[v]);
    12095
    12096 /* at least one bound need to be at zero */
    12097 if( !onlybin && !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
    12098 return SCIP_OKAY;
    12099
    12100 /* swap bounds for 'standard' form */
    12101 if( !SCIPisFeasZero(scip, lb) )
    12102 {
    12103 ub = -lb;
    12104 val *= -1;
    12105 }
    12106
    12107 found = TRUE;
    12108
    12109 frac += (val - SCIPfloor(scip, val)) * ub;
    12110
    12111 /* if we exceed the fractional part of the right hand side, we cannot tighten the coefficients
    12112 *
    12113 * e.g. 1.1x1 + 1.1x2 + 1.4x3 + 1.02x4 <= 2.4, here we cannot floor all fractionals because
    12114 * x3, x4 set to 1 would be infeasible but feasible after flooring
    12115 */
    12116 if( SCIPisGT(scip, frac, siderest) )
    12117 return SCIP_OKAY;
    12118 }
    12119 }
    12120 assert(v == -1);
    12121
    12122 SCIPdebugMsg(scip, "rounding all non-integral coefficients and the right hand side down\n");
    12123
    12124 /* round rhs and coefficients to integral values */
    12125 if( found )
    12126 {
    12127 for( v = nvars - 1; v >= 0; --v )
    12128 {
    12129 val = vals[v];
    12130
    12131 /* add the whole fractional part */
    12132 if( !SCIPisIntegral(scip, val) )
    12133 {
    12134 lb = SCIPvarGetLbGlobal(vars[v]);
    12135
    12136 if( SCIPisFeasZero(scip, lb) )
    12137 newval = SCIPfloor(scip, val);
    12138 else
    12139 newval = SCIPceil(scip, val);
    12140
    12141 if( SCIPisZero(scip, newval) )
    12142 {
    12143 /* delete old redundant coefficient */
    12144 SCIP_CALL( delCoefPos(scip, cons, v) );
    12145 ++(*nchgcoefs);
    12146 }
    12147 else
    12148 {
    12149 /* replace old with new coefficient */
    12150 SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
    12151 ++(*nchgcoefs);
    12152 }
    12153 }
    12154 }
    12155 }
    12156
    12157 /* replace old with new right hand side */
    12158 SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
    12159 ++(*nchgsides);
    12160 }
    12161 }
    12162 else
    12163 {
    12164 if( allcoefintegral )
    12165 {
    12166 /* replace old with new left hand side */
    12167 SCIP_CALL( chgLhs(scip, cons, SCIPceil(scip, lhs)) );
    12168 ++(*nchgsides);
    12169 }
    12170 else
    12171 {
    12172 /* cannot floor left hand side to zero */
    12173 if( SCIPisLT(scip, lhs, 1.0) )
    12174 return SCIP_OKAY;
    12175
    12176 siderest = lhs - SCIPfloor(scip, lhs);
    12177
    12178 /* try to round down all non-integral coefficients */
    12179 for( v = nvars - 1; v >= 0; --v )
    12180 {
    12181 val = vals[v];
    12182
    12183 /* add up all possible fractional parts */
    12184 if( !SCIPisIntegral(scip, val) )
    12185 {
    12186 lb = SCIPvarGetLbGlobal(vars[v]);
    12187 ub = SCIPvarGetUbGlobal(vars[v]);
    12188
    12189 /* at least one bound need to be at zero */
    12190 if( !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
    12191 return SCIP_OKAY;
    12192
    12193 /* swap bounds for 'standard' form */
    12194 if( !SCIPisFeasZero(scip, lb) )
    12195 {
    12196 ub = -lb;
    12197 val *= -1;
    12198 }
    12199
    12200 /* cannot floor to zero */
    12201 if( SCIPisLT(scip, val, 1.0) )
    12202 return SCIP_OKAY;
    12203
    12204 /* the fractional part on each variable need to exceed the fractional part on the left hand side */
    12205 if( SCIPisLT(scip, val - SCIPfloor(scip, val), siderest) )
    12206 return SCIP_OKAY;
    12207
    12208 found = TRUE;
    12209
    12210 frac += (val - SCIPfloor(scip, val)) * ub;
    12211
    12212 /* if we exceed the fractional part of the left hand side plus one by summing up all maximal
    12213 * fractional parts of the variables, we cannot tighten the coefficients
    12214 *
    12215 * e.g. 4.3x1 + 1.3x2 + 1.3x3 + 1.6x4 >= 4.2, here we cannot floor all fractionals because
    12216 * x2-x4 set to 1 would be feasible but not after flooring
    12217 */
    12218 if( SCIPisGE(scip, frac, 1 + siderest) )
    12219 return SCIP_OKAY;
    12220 }
    12221 /* all coefficients need to be integral, otherwise we might do an invalid reduction */
    12222 else
    12223 return SCIP_OKAY;
    12224 }
    12225 assert(v == -1);
    12226
    12227 SCIPdebugMsg(scip, "rounding all non-integral coefficients and the left hand side down\n");
    12228
    12229 /* round lhs and coefficients to integral values */
    12230 if( found )
    12231 {
    12232 for( v = nvars - 1; v >= 0; --v )
    12233 {
    12234 val = vals[v];
    12235
    12236 /* add the whole fractional part */
    12237 if( !SCIPisIntegral(scip, val) )
    12238 {
    12239 lb = SCIPvarGetLbGlobal(vars[v]);
    12240
    12241 if( SCIPisFeasZero(scip, lb) )
    12242 newval = SCIPfloor(scip, val);
    12243 else
    12244 newval = SCIPceil(scip, val);
    12245
    12246 if( SCIPisZero(scip, newval) )
    12247 {
    12248 /* delete old redundant coefficient */
    12249 SCIP_CALL( delCoefPos(scip, cons, v) );
    12250 ++(*nchgcoefs);
    12251 }
    12252 else
    12253 {
    12254 /* replace old with new coefficient */
    12255 SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
    12256 ++(*nchgcoefs);
    12257 }
    12258 }
    12259 }
    12260 }
    12261
    12262 /* replace old with new left hand side */
    12263 SCIP_CALL( chgLhs(scip, cons, SCIPfloor(scip, lhs)) );
    12264 ++(*nchgsides);
    12265 }
    12266 }
    12267
    12268 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
    12269 assert(vars == consdata->vars);
    12270 assert(vals == consdata->vals);
    12271
    12272 if( *infeasible )
    12273 return SCIP_OKAY;
    12274
    12275 rhs = consdata->rhs;
    12276 lhs = consdata->lhs;
    12277
    12278 assert(!hasrhs || !SCIPisNegative(scip, rhs));
    12279 assert(!haslhs || !SCIPisNegative(scip, lhs));
    12280
    12282
    12283 nvars = consdata->nvars;
    12284 if( nvars < 2 )
    12285 return SCIP_OKAY;
    12286
    12287 allcoefintegral = TRUE;
    12288#ifndef NDEBUG
    12289 /* debug check if all coefficients are really integral */
    12290 for( v = nvars - 1; v >= 0; --v )
    12291 assert(SCIPisIntegral(scip, vals[v]));
    12292#endif
    12293 }
    12294
    12295 /* @todo following can also work on non integral coefficients, need more investigation */
    12296 /* only check constraints with integral coefficients on all integral variables */
    12297 if( !allcoefintegral )
    12298 return SCIP_OKAY;
    12299
    12300 /* we want to avoid numerical troubles, therefore we do not change non-integral sides */
    12301 if( (hasrhs && !SCIPisIntegral(scip, rhs)) || (haslhs && !SCIPisIntegral(scip, lhs)) )
    12302 return SCIP_OKAY;
    12303
    12304 /* maximal absolute value of coefficients in constraint is one, so we cannot tighten it further */
    12305 if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) )
    12306 return SCIP_OKAY;
    12307
    12308 /* stop if the last coeffcients is one in absolute value and the variable is not binary */
    12309 if( !SCIPvarIsBinary(vars[nvars - 1]) && SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) )
    12310 return SCIP_OKAY;
    12311
    12312 assert(nvars >= 2);
    12313
    12314 /* start gcd procedure for all variables */
    12315 do
    12316 {
    12317 SCIPdebug( oldnchgcoefs = *nchgcoefs; )
    12318 SCIPdebug( oldnchgsides = *nchgsides; )
    12319
    12320 /* stop if we have two coeffcients which are one in absolute value */
    12321 if( SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) && SCIPisEQ(scip, REALABS(vals[nvars - 2]), 1.0) )
    12322 return SCIP_OKAY;
    12323
    12324 gcd = -1;
    12325
    12326 /* calculate greatest common divisor over all integer variables; note that the onlybin flag needs to be recomputed
    12327 * because coefficients of non-binary variables might have changed to zero */
    12328 if( !onlybin )
    12329 {
    12330 foundbin = -1;
    12331 onlybin = TRUE;
    12332
    12333 for( v = nvars - 1; v >= 0; --v )
    12334 {
    12335 assert(!SCIPisZero(scip, vals[v]));
    12336 assert(SCIPvarIsIntegral(vars[v]));
    12337
    12338 if( SCIPvarIsBinary(vars[v]) )
    12339 {
    12340 if( foundbin == -1 )
    12341 foundbin = v;
    12342 continue;
    12343 }
    12344 else
    12345 onlybin = FALSE;
    12346
    12347 absval = REALABS(vals[v]);
    12348 /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
    12349 * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
    12350 */
    12351 assert(SCIPisFeasIntegral(scip, absval));
    12352
    12353 if( gcd == -1 )
    12354 {
    12355 gcd = (SCIP_Longint)(absval + feastol);
    12356 assert(gcd >= 1);
    12357 }
    12358 else
    12359 {
    12360 /* calculate greatest common divisor for all general variables */
    12361 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(absval + feastol));
    12362 }
    12363 if( gcd == 1 )
    12364 break;
    12365 }
    12366 }
    12367 else
    12368 foundbin = nvars - 1;
    12369
    12370 /* we need at least one binary variable and a gcd greater than 1 to try to perform further coefficient changes */
    12371 if( gcd == 1 || foundbin == -1)
    12372 return SCIP_OKAY;
    12373
    12374 assert((onlybin && gcd == -1) || (!onlybin && gcd > 1));
    12375
    12376 candpos = -1;
    12377 candpos2 = -1;
    12378
    12379 /* calculate greatest common divisor over all integer and binary variables and determine the candidate where we might
    12380 * change the coefficient
    12381 */
    12382 for( v = foundbin; v >= 0; --v )
    12383 {
    12384 if( onlybin || SCIPvarIsBinary(vars[v]) )
    12385 {
    12386 absval = REALABS(vals[v]);
    12387 /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
    12388 * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
    12389 */
    12390 assert(SCIPisFeasIntegral(scip, absval));
    12391
    12392 oldgcd = gcd;
    12393
    12394 if( gcd == -1 )
    12395 {
    12396 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
    12397 assert(gcd >= 1);
    12398 }
    12399 else
    12400 {
    12401 /* calculate greatest common divisor for all general and binary variables */
    12402 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
    12403 }
    12404
    12405 /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
    12406 * can terminate
    12407 */
    12408 if( gcd == 1 )
    12409 {
    12410 /* found candidate */
    12411 if( candpos == -1 )
    12412 {
    12413 gcd = oldgcd;
    12414 candpos = v;
    12415
    12416 /* if we have only binary variables and both first coefficients have a gcd of 1, both are candidates for
    12417 * the coefficient change
    12418 */
    12419 if( onlybin && v == foundbin - 1 )
    12420 candpos2 = foundbin;
    12421 }
    12422 /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
    12423 else
    12424 {
    12425 if( onlybin && candpos == v + 1 && candpos2 == v + 2 )
    12426 {
    12427 assert(candpos2 == nvars - 1);
    12428
    12429 /* take new candidates */
    12430 candpos = candpos2;
    12431
    12432 /* recalculate gcd from scratch */
    12433 gcd = (SCIP_Longint)(REALABS(vals[v+1]) + feastol);
    12434 assert(gcd >= 1);
    12435
    12436 /* calculate greatest common divisor for all general and binary variables */
    12437 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
    12438 if( gcd == 1 )
    12439 return SCIP_OKAY;
    12440 }
    12441 else
    12442 /* cannot determine a possible coefficient for reduction */
    12443 return SCIP_OKAY;
    12444 }
    12445 }
    12446 }
    12447 }
    12448 assert(gcd >= 2);
    12449
    12450 /* we should have found one coefficient, that led to a gcd of 1, otherwise we could normalize the constraint
    12451 * further
    12452 */
    12453 assert(candpos >= 0 && candpos < nvars);
    12454
    12455 /* all variables and all coefficients are integral, so the side should be too */
    12456 assert((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs)));
    12457
    12458 /* check again, if we have a normalized inequality (not ranged) the one side should be positive,
    12459 * @see normalizeCons()
    12460 */
    12461 assert(!hasrhs || !SCIPisNegative(scip, rhs));
    12462 assert(!haslhs || !SCIPisNegative(scip, lhs));
    12463
    12464 /* determine the remainder of the side and the gcd */
    12465 if( hasrhs )
    12466 rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
    12467 else
    12468 rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
    12469 assert(rest >= 0);
    12470 assert(rest < gcd);
    12471
    12472 /* determine the remainder of the coefficient candidate and the gcd */
    12473 if( vals[candpos] < 0 )
    12474 {
    12475 restcoef = ((SCIP_Longint)(vals[candpos] - feastol)) % gcd;
    12476 assert(restcoef <= -1);
    12477 restcoef += gcd;
    12478 }
    12479 else
    12480 restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
    12481 assert(restcoef >= 1);
    12482 assert(restcoef < gcd);
    12483
    12484 if( hasrhs )
    12485 {
    12486 if( rest > 0 )
    12487 {
    12488 /* replace old with new right hand side */
    12489 SCIP_CALL( chgRhs(scip, cons, rhs - rest) );
    12490 ++(*nchgsides);
    12491 }
    12492
    12493 /* calculate new coefficient */
    12494 if( restcoef > rest )
    12495 newcoef = vals[candpos] - restcoef + gcd;
    12496 else
    12497 newcoef = vals[candpos] - restcoef;
    12498 }
    12499 else
    12500 {
    12501 if( rest > 0 )
    12502 {
    12503 /* replace old with new left hand side */
    12504 SCIP_CALL( chgLhs(scip, cons, lhs - rest + gcd) );
    12505 ++(*nchgsides);
    12506 }
    12507
    12508 /* calculate new coefficient */
    12509 if( rest == 0 || restcoef < rest )
    12510 newcoef = vals[candpos] - restcoef;
    12511 else
    12512 newcoef = vals[candpos] - restcoef + gcd;
    12513 }
    12514 assert(SCIPisZero(scip, newcoef) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(newcoef) + feastol)) == gcd);
    12515
    12516 SCIPdebugMsg(scip, "gcd = %" SCIP_LONGINT_FORMAT ", rest = %" SCIP_LONGINT_FORMAT ", restcoef = %" SCIP_LONGINT_FORMAT "; changing coef of variable <%s> to %g and %s by %" SCIP_LONGINT_FORMAT "\n", gcd, rest, restcoef, SCIPvarGetName(vars[candpos]), newcoef, hasrhs ? "reduced rhs" : "increased lhs", hasrhs ? rest : (rest > 0 ? gcd - rest : 0));
    12517
    12518 if( SCIPisZero(scip, newcoef) )
    12519 {
    12520 /* delete redundant coefficient */
    12521 SCIP_CALL( delCoefPos(scip, cons, candpos) );
    12522 }
    12523 else
    12524 {
    12525 /* replace old with new coefficient */
    12526 SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
    12527 }
    12528 ++(*nchgcoefs);
    12529
    12530 /* now constraint can be normalized, might be directly done by dividing it by the gcd */
    12531 SCIP_CALL( normalizeCons(scip, cons, infeasible) );
    12532 assert(vars == consdata->vars);
    12533 assert(vals == consdata->vals);
    12534
    12535 if( *infeasible )
    12536 return SCIP_OKAY;
    12537
    12539
    12540 rhs = consdata->rhs;
    12541 lhs = consdata->lhs;
    12542 assert(!hasrhs || !SCIPisNegative(scip, rhs));
    12543 assert(!haslhs || !SCIPisNegative(scip, lhs));
    12544
    12545 nvars = consdata->nvars;
    12546
    12547 SCIPdebugMsg(scip, "we did %d coefficient changes and %d side changes on constraint %s when applying one round of the gcd algorithm\n", *nchgcoefs - oldnchgcoefs, *nchgsides - oldnchgsides, SCIPconsGetName(cons));
    12548 }
    12549 while( nvars >= 2 );
    12550
    12551 return SCIP_OKAY;
    12552}
    12553
    12554
    12555/** tries to aggregate an (in)equality and an equality in order to decrease the number of variables in the (in)equality:
    12556 * cons0 := a * cons0 + b * cons1,
    12557 * where a = val1[v] and b = -val0[v] for common variable v which removes most variable weight;
    12558 * for numerical stability, we will only accept integral a and b;
    12559 * the variable weight is a weighted sum over all included variables, where each binary variable weighs BINWEIGHT,
    12560 * each integer or implied integral variable weighs INTWEIGHT and each continuous variable weighs CONTWEIGHT
    12561 */
    12562static
    12564 SCIP* scip, /**< SCIP data structure */
    12565 SCIP_CONS* cons0, /**< (in)equality to modify */
    12566 SCIP_CONS* cons1, /**< equality to use for aggregation of cons0 */
    12567 int* commonidx0, /**< array with indices of variables in cons0, that appear also in cons1 */
    12568 int* commonidx1, /**< array with indices of variables in cons1, that appear also in cons0 */
    12569 int* diffidx0minus1, /**< array with indices of variables in cons0, that don't appear in cons1 */
    12570 int* diffidx1minus0, /**< array with indices of variables in cons1, that don't appear in cons0 */
    12571 int nvarscommon, /**< number of variables, that appear in both constraints */
    12572 int commonidxweight, /**< variable weight sum of common variables */
    12573 int diffidx0minus1weight, /**< variable weight sum of variables in cons0, that don't appear in cons1 */
    12574 int diffidx1minus0weight, /**< variable weight sum of variables in cons1, that don't appear in cons0 */
    12575 SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
    12576 int* nchgcoefs, /**< pointer to count the number of changed coefficients */
    12577 SCIP_Bool* aggregated, /**< pointer to store whether an aggregation was made */
    12578 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
    12579 )
    12580{
    12581 SCIP_CONSDATA* consdata0;
    12582 SCIP_CONSDATA* consdata1;
    12583 SCIP_Real a;
    12584 SCIP_Real b;
    12585 SCIP_Real aggrcoef;
    12586 SCIP_Real scalarsum;
    12587 SCIP_Real bestscalarsum;
    12588 SCIP_Bool betterscalarsum;
    12589 SCIP_Bool commonvarlindependent; /* indicates whether coefficient vector of common variables in linearly dependent */
    12590 int varweight;
    12591 int nvars;
    12592 int bestvarweight;
    12593 int bestnvars;
    12594 int bestv;
    12595 int v;
    12596 int i;
    12597
    12598 assert(scip != NULL);
    12599 assert(cons0 != NULL);
    12600 assert(cons1 != NULL);
    12601 assert(commonidx0 != NULL);
    12602 assert(commonidx1 != NULL);
    12603 assert(diffidx0minus1 != NULL);
    12604 assert(diffidx1minus0 != NULL);
    12605 assert(nvarscommon >= 1);
    12606 assert(commonidxweight >= nvarscommon);
    12607 assert(nchgcoefs != NULL);
    12608 assert(aggregated != NULL);
    12609
    12610 assert(SCIPconsIsActive(cons0));
    12611 assert(SCIPconsIsActive(cons1));
    12612
    12613 *infeasible = FALSE;
    12614
    12615 SCIPdebugMsg(scip, "try aggregation of <%s> and <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
    12616
    12617 /* cons0 is an (in)equality */
    12618 consdata0 = SCIPconsGetData(cons0);
    12619 assert(consdata0 != NULL);
    12620 assert(consdata0->nvars >= 1);
    12621 assert(SCIPisLE(scip, consdata0->lhs, consdata0->rhs));
    12622 assert(diffidx0minus1weight >= consdata0->nvars - nvarscommon);
    12623
    12624 /* cons1 is an equality */
    12625 consdata1 = SCIPconsGetData(cons1);
    12626 assert(consdata1 != NULL);
    12627 assert(consdata1->nvars >= 1);
    12628 assert(SCIPisEQ(scip, consdata1->lhs, consdata1->rhs));
    12629 assert(diffidx1minus0weight >= consdata1->nvars - nvarscommon);
    12630
    12631 *aggregated = FALSE;
    12632
    12633 /* search for the best common variable such that
    12634 * val1[var] * consdata0 - val0[var] * consdata1
    12635 * has least weighted number of variables
    12636 */
    12637 bestvarweight = commonidxweight + diffidx0minus1weight;
    12638 bestnvars = consdata0->nvars;
    12639 bestv = -1;
    12640 bestscalarsum = 0.0;
    12641 commonvarlindependent = TRUE;
    12642 for( v = 0; v < nvarscommon; ++v )
    12643 {
    12644 assert(consdata0->vars[commonidx0[v]] == consdata1->vars[commonidx1[v]]);
    12645 a = consdata1->vals[commonidx1[v]];
    12646 b = -consdata0->vals[commonidx0[v]];
    12647
    12648 /* only try aggregation, if coefficients are integral (numerical stability) */
    12650 {
    12651 /* count the number of variables in the potential new constraint a * consdata0 + b * consdata1 */
    12652 varweight = diffidx0minus1weight + diffidx1minus0weight;
    12653 nvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
    12654 scalarsum = REALABS(a) + REALABS(b);
    12655 betterscalarsum = (scalarsum < bestscalarsum);
    12656 for( i = 0; i < nvarscommon
    12657 && (varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum)); ++i )
    12658 {
    12659 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
    12660 if( !SCIPisZero(scip, aggrcoef) )
    12661 {
    12662 varweight += getVarWeight(consdata0->vars[commonidx0[i]]);
    12663 nvars++;
    12664 }
    12665 }
    12666 if( varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum) )
    12667 {
    12668 bestv = v;
    12669 bestvarweight = varweight;
    12670 bestnvars = nvars;
    12671 bestscalarsum = scalarsum;
    12672 }
    12673 }
    12674
    12675 /* update commonvarlindependent flag, if still TRUE:
    12676 * v's common coefficient in cons1 / v's common coefficient in cons0 should be constant, i.e., equal 0's common coefficient in cons1 / 0's common coefficient in cons0
    12677 */
    12678 if( commonvarlindependent && v > 0 )
    12679 commonvarlindependent = SCIPisEQ(scip,
    12680 consdata1->vals[commonidx1[v]] * consdata0->vals[commonidx0[0]],
    12681 consdata1->vals[commonidx1[0]] * consdata0->vals[commonidx0[v]]);
    12682 }
    12683
    12684 /* if better aggregation was found, create new constraint and delete old one */
    12685 if( (bestv != -1 || commonvarlindependent) && SCIPconsGetNUpgradeLocks(cons0) == 0 )
    12686 {
    12687 SCIP_CONS* newcons;
    12688 SCIP_CONSDATA* newconsdata;
    12689 SCIP_VAR** newvars;
    12690 SCIP_Real* newvals;
    12691 SCIP_Real newlhs;
    12692 SCIP_Real newrhs;
    12693 int newnvars;
    12694
    12695 if( bestv != -1 )
    12696 {
    12697 /* choose multipliers such that the multiplier for the (in)equality cons0 is positive */
    12698 if( consdata1->vals[commonidx1[bestv]] > 0.0 )
    12699 {
    12700 a = consdata1->vals[commonidx1[bestv]];
    12701 b = -consdata0->vals[commonidx0[bestv]];
    12702 }
    12703 else
    12704 {
    12705 a = -consdata1->vals[commonidx1[bestv]];
    12706 b = consdata0->vals[commonidx0[bestv]];
    12707 }
    12708 assert(SCIPisIntegral(scip, a));
    12709 assert(SCIPisPositive(scip, a));
    12710 assert(SCIPisIntegral(scip, b));
    12711 assert(!SCIPisZero(scip, b));
    12712 }
    12713 else
    12714 {
    12715 assert(commonvarlindependent);
    12716 if( consdata1->vals[commonidx1[0]] > 0.0 )
    12717 {
    12718 a = consdata1->vals[commonidx1[0]];
    12719 b = -consdata0->vals[commonidx0[0]];
    12720 }
    12721 else
    12722 {
    12723 a = -consdata1->vals[commonidx1[0]];
    12724 b = consdata0->vals[commonidx0[0]];
    12725 }
    12726 assert(SCIPisPositive(scip, a));
    12727 assert(!SCIPisZero(scip, b));
    12728
    12729 /* if a/b is integral, then we can easily choose integer multipliers */
    12730 if( SCIPisIntegral(scip, a/b) )
    12731 {
    12732 if( a/b > 0 )
    12733 {
    12734 a /= b;
    12735 b = 1.0;
    12736 }
    12737 else
    12738 {
    12739 a /= -b;
    12740 b = -1.0;
    12741 }
    12742 }
    12743
    12744 /* setup best* variables that were not setup above because we are in the commonvarlindependent case */
    12745 SCIPdebug( bestvarweight = diffidx0minus1weight + diffidx1minus0weight; )
    12746 bestnvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
    12747 }
    12748
    12749 SCIPdebugMsg(scip, "aggregate linear constraints <%s> := %.15g*<%s> + %.15g*<%s> -> nvars: %d -> %d, weight: %d -> %d\n",
    12750 SCIPconsGetName(cons0), a, SCIPconsGetName(cons0), b, SCIPconsGetName(cons1),
    12751 consdata0->nvars, bestnvars, commonidxweight + diffidx0minus1weight, bestvarweight);
    12752 SCIPdebugPrintCons(scip, cons0, NULL);
    12753 SCIPdebugPrintCons(scip, cons1, NULL);
    12754
    12755 /* get temporary memory for creating the new linear constraint */
    12756 SCIP_CALL( SCIPallocBufferArray(scip, &newvars, bestnvars) );
    12757 SCIP_CALL( SCIPallocBufferArray(scip, &newvals, bestnvars) );
    12758
    12759 /* calculate the common coefficients, if we have not recognized linear dependency */
    12760 newnvars = 0;
    12761 if( !commonvarlindependent )
    12762 {
    12763 for( i = 0; i < nvarscommon; ++i )
    12764 {
    12765 assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
    12766 assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
    12767
    12768 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
    12769 if( !SCIPisZero(scip, aggrcoef) )
    12770 {
    12771 assert(newnvars < bestnvars);
    12772 newvars[newnvars] = consdata0->vars[commonidx0[i]];
    12773 newvals[newnvars] = aggrcoef;
    12774 newnvars++;
    12775 }
    12776 }
    12777 }
    12778 else
    12779 {
    12780 /* if we recognized linear dependency of the common coefficients, then the aggregation coefficient should be 0.0 for every common variable */
    12781#ifndef NDEBUG
    12782 for( i = 0; i < nvarscommon; ++i )
    12783 {
    12784 assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
    12785 assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
    12786
    12787 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
    12788 assert(SCIPisZero(scip, aggrcoef));
    12789 }
    12790#endif
    12791 }
    12792
    12793 /* calculate the coefficients appearing in cons0 but not in cons1 */
    12794 for( i = 0; i < consdata0->nvars - nvarscommon; ++i )
    12795 {
    12796 assert(0 <= diffidx0minus1[i] && diffidx0minus1[i] < consdata0->nvars);
    12797
    12798 aggrcoef = a * consdata0->vals[diffidx0minus1[i]];
    12799 assert(!SCIPisZero(scip, aggrcoef));
    12800 assert(newnvars < bestnvars);
    12801 newvars[newnvars] = consdata0->vars[diffidx0minus1[i]];
    12802 newvals[newnvars] = aggrcoef;
    12803 newnvars++;
    12804 }
    12805
    12806 /* calculate the coefficients appearing in cons1 but not in cons0 */
    12807 for( i = 0; i < consdata1->nvars - nvarscommon; ++i )
    12808 {
    12809 assert(0 <= diffidx1minus0[i] && diffidx1minus0[i] < consdata1->nvars);
    12810
    12811 aggrcoef = b * consdata1->vals[diffidx1minus0[i]];
    12812 assert(!SCIPisZero(scip, aggrcoef));
    12813 assert(newnvars < bestnvars);
    12814 newvars[newnvars] = consdata1->vars[diffidx1minus0[i]];
    12815 newvals[newnvars] = aggrcoef;
    12816 newnvars++;
    12817 }
    12818 assert(newnvars == bestnvars);
    12819
    12820 /* calculate the new left and right hand side of the (in)equality */
    12821 assert(!SCIPisInfinity(scip, -consdata1->lhs));
    12822 assert(!SCIPisInfinity(scip, consdata1->rhs));
    12823 if( SCIPisInfinity(scip, -consdata0->lhs) )
    12824 newlhs = -SCIPinfinity(scip);
    12825 else
    12826 newlhs = a * consdata0->lhs + b * consdata1->lhs;
    12827 if( SCIPisInfinity(scip, consdata0->rhs) )
    12828 newrhs = SCIPinfinity(scip);
    12829 else
    12830 newrhs = a * consdata0->rhs + b * consdata1->rhs;
    12831
    12832 /* create the new linear constraint */
    12833 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, SCIPconsGetName(cons0), newnvars, newvars, newvals, newlhs, newrhs,
    12838
    12839 newconsdata = SCIPconsGetData(newcons);
    12840 assert(newconsdata != NULL);
    12841
    12842 /* copy the upgraded flag from the old cons0 to the new constraint */
    12843 newconsdata->upgraded = consdata0->upgraded;
    12844
    12845 SCIP_CALL( normalizeCons(scip, newcons, infeasible) );
    12846
    12847 /* check, if we really want to use the new constraint instead of the old one:
    12848 * use the new one, if the maximum norm doesn't grow too much
    12849 */
    12850 if( !(*infeasible) && consdataGetMaxAbsval(SCIPconsGetData(newcons)) <= maxaggrnormscale * consdataGetMaxAbsval(consdata0) )
    12851 {
    12852 SCIPdebugMsg(scip, " -> aggregated to <%s>\n", SCIPconsGetName(newcons));
    12853 SCIPdebugPrintCons(scip, newcons, NULL);
    12854
    12855 /* update the statistics: we changed all coefficients */
    12856 if( !consdata0->upgraded )
    12857 (*nchgcoefs) += consdata0->nvars + consdata1->nvars - nvarscommon;
    12858 *aggregated = TRUE;
    12859
    12860 /* add the new linear constraint to the problem and delete the old constraint */
    12861 SCIP_CALL( SCIPaddConsUpgrade(scip, cons0, &newcons) );
    12862 SCIP_CALL( SCIPdelCons(scip, cons0) );
    12863 }
    12864 else
    12865 {
    12866 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    12867 }
    12868
    12869 /* free temporary memory */
    12870 SCIPfreeBufferArray(scip, &newvals);
    12871 SCIPfreeBufferArray(scip, &newvars);
    12872 }
    12873
    12874 return SCIP_OKAY;
    12875}
    12876
    12877/** gets the key of the given element */
    12878static
    12879SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
    12880{ /*lint --e{715}*/
    12881 /* the key is the element itself */
    12882 return elem;
    12883}
    12884
    12885/** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables and the
    12886 * coefficients are either equal or negated
    12887 */
    12888static
    12889SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
    12890{
    12891 SCIP* scip;
    12892 SCIP_CONSDATA* consdata1;
    12893 SCIP_CONSDATA* consdata2;
    12894 SCIP_Real minscale;
    12895 SCIP_Real maxscale;
    12896 int i;
    12897
    12898 assert(key1 != NULL);
    12899 assert(key2 != NULL);
    12900 consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
    12901 consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
    12902 assert(consdata1->indexsorted);
    12903 assert(consdata2->indexsorted);
    12904
    12905 scip = (SCIP*)userptr;
    12906 assert(scip != NULL);
    12907
    12908 /* if it is the same constraint we dont need to check anything */
    12909 if( key1 == key2 )
    12910 return TRUE;
    12911
    12912 /* checks trivial case */
    12913 if( consdata1->nvars != consdata2->nvars )
    12914 return FALSE;
    12915
    12916 /* tests if variables are equal */
    12917 for( i = 0; i < consdata1->nvars; ++i )
    12918 {
    12919 if( consdata1->vars[i] != consdata2->vars[i] )
    12920 {
    12921 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
    12922 SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
    12923 return FALSE;
    12924 }
    12925 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
    12926 }
    12927
    12928 /* order by maxabsval */
    12929 if( consdataGetMaxAbsval(consdata1) > consdataGetMaxAbsval(consdata2) )
    12930 SCIPswapPointers((void**)&consdata1, (void**)&consdata2);
    12931
    12932 /* initialize extremal scales */
    12933 minscale = SCIPinfinity(scip);
    12934 maxscale = -SCIPinfinity(scip);
    12935
    12936 /* test if coefficient scales are equal */
    12937 for( i = 0; i < consdata1->nvars; ++i )
    12938 {
    12939 SCIP_Real scale = consdata2->vals[i] / consdata1->vals[i];
    12940
    12941 if( minscale > scale )
    12942 {
    12943 minscale = scale;
    12944
    12945 if( SCIPisLT(scip, minscale, maxscale) )
    12946 return FALSE;
    12947 }
    12948
    12949 if( maxscale < scale )
    12950 {
    12951 maxscale = scale;
    12952
    12953 if( SCIPisLT(scip, minscale, maxscale) )
    12954 return FALSE;
    12955 }
    12956 }
    12957
    12958 return TRUE;
    12959}
    12960
    12961/** returns the hash value of the key */
    12962static
    12963SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
    12964{
    12965 SCIP_CONSDATA* consdata;
    12966 int minidx;
    12967 int mididx;
    12968 int maxidx;
    12969#ifndef NDEBUG
    12970 SCIP* scip;
    12971
    12972 scip = (SCIP*)userptr;
    12973 assert(scip != NULL);
    12974#endif
    12975
    12976 assert(key != NULL);
    12977 consdata = SCIPconsGetData((SCIP_CONS*)key);
    12978 assert(consdata != NULL);
    12979 assert(consdata->nvars > 0);
    12980
    12981 assert(consdata->indexsorted);
    12982
    12983 minidx = SCIPvarGetIndex(consdata->vars[0]);
    12984 mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
    12985 maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
    12986
    12987 /* using only the variable indices as hash, since the values are compared by epsilon */
    12988 return SCIPhashFour(consdata->nvars, minidx, mididx, maxidx);
    12989}
    12990
    12991/** returns the key for deciding which of two parallel constraints should be kept (smaller key should be kept);
    12992 * prefers non-upgraded constraints and as second criterion the constraint with the smallest position
    12993 */
    12994static
    12996 SCIP_CONS* cons /**< linear constraint */
    12997 )
    12998{
    12999 SCIP_CONSDATA* consdata;
    13000
    13001 assert(cons != NULL);
    13002
    13003 consdata = SCIPconsGetData(cons);
    13004 assert(consdata != NULL);
    13005
    13006 return (((unsigned int)consdata->upgraded)<<31) + (unsigned int)SCIPconsGetPos(cons); /*lint !e571*/
    13007}
    13008
    13009/** updates the hashtable such that out of all constraints in the hashtable that are detected
    13010 * to be parallel to *querycons, only one is kept in the hashtable and stored into *querycons,
    13011 * and all others are removed from the hashtable and stored in the given array
    13012 */
    13013static
    13015 SCIP_HASHTABLE* hashtable, /**< hashtable containing linear constraints */
    13016 SCIP_CONS** querycons, /**< pointer to linear constraint used to look for duplicates in the hash table;
    13017 * upon return will contain the constraint that should be kept */
    13018 SCIP_CONS** parallelconss, /**< array to return constraints that are parallel to the given;
    13019 * these constraints where removed from the hashtable */
    13020 int* nparallelconss /**< pointer to return number of parallel constraints */
    13021 )
    13022{
    13023 SCIP_CONS* parallelcons;
    13024 unsigned int querykey;
    13025
    13026 *nparallelconss = 0;
    13027 querykey = getParallelConsKey(*querycons);
    13028
    13029 while( (parallelcons = (SCIP_CONS*)SCIPhashtableRetrieve(hashtable, (void*)(*querycons))) != NULL )
    13030 {
    13031 unsigned int conskey = getParallelConsKey(parallelcons);
    13032
    13033 if( conskey < querykey )
    13034 {
    13035 parallelconss[(*nparallelconss)++] = *querycons;
    13036 *querycons = parallelcons;
    13037 querykey = conskey;
    13038 }
    13039 else
    13040 {
    13041 parallelconss[(*nparallelconss)++] = parallelcons;
    13042 }
    13043
    13044 /* if the constraint that just came out of the hash table is the one that is kept,
    13045 * we do not need to look into the hashtable again, since the invariant is that
    13046 * in the hashtable only pair-wise non-parallel constraints are contained.
    13047 * For the original querycons, however, multiple constraints that compare equal (=parallel)
    13048 * could be contained due to non-transitivity of the equality comparison.
    13049 * Also we can return immediately, since parallelcons is already contained in the
    13050 * hashtable and we do not need to remove and reinsert it.
    13051 */
    13052 if( *querycons == parallelcons )
    13053 return SCIP_OKAY;
    13054
    13055 /* remove parallelcons from the hashtable, since it will be replaced by querycons */
    13056 SCIP_CALL( SCIPhashtableRemove(hashtable, (void*) parallelcons) );
    13057 }
    13058
    13059 /* in debug mode we make sure, that the hashtable cannot contain a constraint that
    13060 * comnpares equal to querycons at this point
    13061 */
    13062#ifndef NDEBUG
    13063 SCIP_CALL_ABORT( SCIPhashtableSafeInsert(hashtable, *querycons) );
    13064#else
    13065 SCIP_CALL( SCIPhashtableInsert(hashtable, *querycons) );
    13066#endif
    13067
    13068 return SCIP_OKAY;
    13069}
    13070
    13071/** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
    13072 * accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
    13073 */
    13074static
    13076 SCIP* scip, /**< SCIP data structure */
    13077 BMS_BLKMEM* blkmem, /**< block memory */
    13078 SCIP_CONS** conss, /**< constraint set */
    13079 int nconss, /**< number of constraints in constraint set */
    13080 int* firstchange, /**< pointer to store first changed constraint */
    13081 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
    13082 int* ndelconss, /**< pointer to count number of deleted constraints */
    13083 int* nchgsides /**< pointer to count number of changed left/right hand sides */
    13084 )
    13085{
    13086 SCIP_HASHTABLE* hashtable;
    13087 SCIP_CONS** parallelconss;
    13088 int nparallelconss;
    13089 int hashtablesize;
    13090 int c;
    13091
    13092 assert(scip != NULL);
    13093 assert(blkmem != NULL);
    13094 assert(conss != NULL);
    13095 assert(firstchange != NULL);
    13096 assert(cutoff != NULL);
    13097 assert(ndelconss != NULL);
    13098 assert(nchgsides != NULL);
    13099
    13100 /* create a hash table for the constraint set */
    13101 hashtablesize = nconss;
    13102 SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
    13103 hashGetKeyLinearcons, hashKeyEqLinearcons, hashKeyValLinearcons, (void*) scip) );
    13104
    13105 SCIP_CALL( SCIPallocBufferArray(scip, &parallelconss, nconss) );
    13106
    13107 /* check all constraints in the given set for redundancy */
    13108 for( c = 0; c < nconss; ++c )
    13109 {
    13110 SCIP_CONS* cons0;
    13111 SCIP_CONSDATA* consdata0;
    13112
    13113 cons0 = conss[c];
    13114
    13115 if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
    13116 continue;
    13117
    13118 /* do not check for parallel constraints if they should not be upgraded */
    13119 if ( SCIPconsGetNUpgradeLocks(cons0) > 0 )
    13120 continue;
    13121
    13122 /* check for interuption */
    13123 if( c % 1000 == 0 && SCIPisStopped(scip) )
    13124 break;
    13125
    13126 /* sorts the constraint */
    13127 consdata0 = SCIPconsGetData(cons0);
    13128 assert(consdata0 != NULL);
    13129 SCIP_CALL( consdataSort(scip, consdata0) );
    13130 assert(consdata0->indexsorted);
    13131
    13132 /* get constraints from current hash table with same variables as cons0 and with coefficients equal
    13133 * to the ones of cons0 when both are scaled such that maxabsval is 1.0 and the coefficient of the
    13134 * first variable is positive
    13135 * Also inserts cons0 into the hashtable.
    13136 */
    13137 SCIP_CALL( retrieveParallelConstraints(hashtable, &cons0, parallelconss, &nparallelconss) );
    13138
    13139 if( nparallelconss != 0 )
    13140 {
    13141 SCIP_Real lhs;
    13142 SCIP_Real rhs;
    13143
    13144 int i;
    13145
    13146 /* cons0 may have been changed in retrieveParallelConstraints() */
    13147 consdata0 = SCIPconsGetData(cons0);
    13148
    13149 lhs = consdata0->lhs;
    13150 rhs = consdata0->rhs;
    13151
    13152 for( i = 0; i < nparallelconss; ++i )
    13153 {
    13154 SCIP_CONS* consdel;
    13155 SCIP_CONSDATA* consdatadel;
    13156 SCIP_Real scale;
    13157
    13158 consdel = parallelconss[i];
    13159 consdatadel = SCIPconsGetData(consdel);
    13160
    13161 /* do not delete constraint if it should not be upgraded */
    13162 if ( SCIPconsGetNUpgradeLocks(consdel) > 0 )
    13163 continue;
    13164
    13165 assert(SCIPconsIsActive(consdel));
    13166 assert(!SCIPconsIsModifiable(consdel));
    13167
    13168 /* constraint found: create a new constraint with same coefficients and best left and right hand side;
    13169 * delete old constraints afterwards
    13170 */
    13171 assert(consdatadel != NULL);
    13172 assert(consdata0->nvars >= 1 && consdata0->nvars == consdatadel->nvars);
    13173
    13174 assert(consdatadel->indexsorted);
    13175 assert(consdata0->vars[0] == consdatadel->vars[0]);
    13176
    13177 scale = consdata0->vals[0] / consdatadel->vals[0];
    13178 assert(scale != 0.0);
    13179
    13180 /* in debug mode, check that all coefficients are equal with respect to epsilon
    13181 * if the constraints are in equilibrium scale
    13182 */
    13183#ifndef NDEBUG
    13184 {
    13185 assert(consdata0->validmaxabsval);
    13186 assert(consdatadel->validmaxabsval);
    13187 int k;
    13188 SCIP_Real scale0 = 1.0 / consdata0->maxabsval;
    13189 SCIP_Real scaledel = COPYSIGN(1.0 / consdatadel->maxabsval, scale);
    13190
    13191 for( k = 0; k < consdata0->nvars; ++k )
    13192 {
    13193 assert(SCIPisEQ(scip, scale0 * consdata0->vals[k], scaledel * consdatadel->vals[k]));
    13194 }
    13195 }
    13196#endif
    13197
    13198 if( scale > 0.0 )
    13199 {
    13200 /* the coefficients of both constraints are parallel with a positive scale */
    13201 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with equal coefficients into single ranged row\n",
    13202 SCIPconsGetName(cons0), SCIPconsGetName(consdel));
    13203 SCIPdebugPrintCons(scip, cons0, NULL);
    13204 SCIPdebugPrintCons(scip, consdel, NULL);
    13205
    13206 if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
    13207 lhs = MAX(scale * consdatadel->lhs, lhs);
    13208
    13209 if( ! SCIPisInfinity(scip, consdatadel->rhs) )
    13210 rhs = MIN(scale * consdatadel->rhs, rhs);
    13211 }
    13212 else
    13213 {
    13214 /* the coefficients of both rows are negations */
    13215 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with negated coefficients into single ranged row\n",
    13216 SCIPconsGetName(cons0), SCIPconsGetName(consdel));
    13217 SCIPdebugPrintCons(scip, cons0, NULL);
    13218 SCIPdebugPrintCons(scip, consdel, NULL);
    13219
    13220 if( ! SCIPisInfinity(scip, consdatadel->rhs) )
    13221 lhs = MAX(scale * consdatadel->rhs, lhs);
    13222
    13223 if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
    13224 rhs = MIN(scale * consdatadel->lhs, rhs);
    13225 }
    13226
    13227 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
    13228 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, consdel) );
    13229
    13230 /* delete consdel */
    13231 assert( ! consdata0->upgraded || consdatadel->upgraded );
    13232 SCIP_CALL( SCIPdelCons(scip, consdel) );
    13233 if( !consdatadel->upgraded )
    13234 (*ndelconss)++;
    13235 }
    13236
    13237 if( SCIPisFeasLT(scip, rhs, lhs) )
    13238 {
    13239 SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
    13240 *cutoff = TRUE;
    13241 break;
    13242 }
    13243
    13244 /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
    13245 if( lhs > rhs )
    13246 {
    13247 rhs = (lhs + rhs)/2;
    13248 lhs = rhs;
    13249 }
    13250
    13251 /* update lhs and rhs of cons0 */
    13252 SCIP_CALL( chgLhs(scip, cons0, lhs) );
    13253 SCIP_CALL( chgRhs(scip, cons0, rhs) );
    13254
    13255 /* update the first changed constraint to begin the next aggregation round with */
    13256 if( consdata0->changed && SCIPconsGetPos(cons0) < *firstchange )
    13257 *firstchange = SCIPconsGetPos(cons0);
    13258
    13259 assert(SCIPconsIsActive(cons0));
    13260 }
    13261 }
    13262#ifdef SCIP_MORE_DEBUG
    13263 SCIPinfoMessage(scip, NULL, "linear pairwise comparison hashtable statistics:\n");
    13265#endif
    13266
    13267 SCIPfreeBufferArray(scip, &parallelconss);
    13268
    13269 /* free hash table */
    13270 SCIPhashtableFree(&hashtable);
    13271
    13272 return SCIP_OKAY;
    13273}
    13274
    13275/** compares constraint with all prior constraints for possible redundancy or aggregation,
    13276 * and removes or changes constraint accordingly
    13277 */
    13278static
    13280 SCIP* scip, /**< SCIP data structure */
    13281 SCIP_CONS** conss, /**< constraint set */
    13282 int firstchange, /**< first constraint that changed since last pair preprocessing round */
    13283 int chkind, /**< index of constraint to check against all prior indices upto startind */
    13284 SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
    13285 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
    13286 int* ndelconss, /**< pointer to count number of deleted constraints */
    13287 int* nchgsides, /**< pointer to count number of changed left/right hand sides */
    13288 int* nchgcoefs /**< pointer to count number of changed coefficients */
    13289 )
    13290{
    13291 SCIP_CONS* cons0;
    13292 SCIP_CONSDATA* consdata0;
    13293 int* commonidx0;
    13294 int* commonidx1;
    13295 int* diffidx0minus1;
    13296 int* diffidx1minus0;
    13297 uint64_t possignature0;
    13298 uint64_t negsignature0;
    13299 SCIP_Bool cons0changed;
    13300 SCIP_Bool cons0isequality;
    13301 int diffidx1minus0size;
    13302 int c;
    13303 SCIP_Real cons0lhs;
    13304 SCIP_Real cons0rhs;
    13305 SCIP_Bool cons0upgraded;
    13306
    13307 assert(scip != NULL);
    13308 assert(conss != NULL);
    13309 assert(firstchange <= chkind);
    13310 assert(cutoff != NULL);
    13311 assert(ndelconss != NULL);
    13312 assert(nchgsides != NULL);
    13313 assert(nchgcoefs != NULL);
    13314
    13315 /* get the constraint to be checked against all prior constraints */
    13316 cons0 = conss[chkind];
    13317 assert(cons0 != NULL);
    13318 assert(SCIPconsIsActive(cons0));
    13319 assert(!SCIPconsIsModifiable(cons0));
    13320
    13321 consdata0 = SCIPconsGetData(cons0);
    13322 assert(consdata0 != NULL);
    13323 assert(consdata0->nvars >= 1);
    13324 cons0isequality = SCIPisEQ(scip, consdata0->lhs, consdata0->rhs);
    13325
    13326 /* sort the constraint */
    13327 SCIP_CALL( consdataSort(scip, consdata0) );
    13328
    13329 /* calculate bit signatures of cons0 for potentially positive and negative coefficients */
    13330 consdataCalcSignatures(consdata0);
    13331 possignature0 = consdata0->possignature;
    13332 negsignature0 = consdata0->negsignature;
    13333
    13334 /* get temporary memory for indices of common variables */
    13335 SCIP_CALL( SCIPallocBufferArray(scip, &commonidx0, consdata0->nvars) );
    13336 SCIP_CALL( SCIPallocBufferArray(scip, &commonidx1, consdata0->nvars) );
    13337 SCIP_CALL( SCIPallocBufferArray(scip, &diffidx0minus1, consdata0->nvars) );
    13338 SCIP_CALL( SCIPallocBufferArray(scip, &diffidx1minus0, consdata0->nvars) );
    13339 diffidx1minus0size = consdata0->nvars;
    13340
    13341 cons0lhs = consdata0->lhs;
    13342 cons0rhs = consdata0->rhs;
    13343 cons0upgraded = consdata0->upgraded;
    13344
    13345 /* check constraint against all prior constraints */
    13346 cons0changed = consdata0->changed;
    13347 consdata0->changed = FALSE;
    13348 for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && conss[chkind] != NULL; ++c )
    13349 {
    13350 SCIP_CONS* cons1;
    13351 SCIP_CONSDATA* consdata1;
    13352 uint64_t possignature1;
    13353 uint64_t negsignature1;
    13354 SCIP_Bool cons0dominateslhs;
    13355 SCIP_Bool cons1dominateslhs;
    13356 SCIP_Bool cons0dominatesrhs;
    13357 SCIP_Bool cons1dominatesrhs;
    13358 SCIP_Bool cons1isequality;
    13359 SCIP_Bool coefsequal;
    13360 SCIP_Bool coefsnegated;
    13361 SCIP_Bool tryaggregation;
    13362 int nvarscommon;
    13363 int nvars0minus1;
    13364 int nvars1minus0;
    13365 int commonidxweight;
    13366 int diffidx0minus1weight;
    13367 int diffidx1minus0weight;
    13368 int v0;
    13369 int v1;
    13370
    13371 assert(cons0lhs == consdata0->lhs); /*lint !e777*/
    13372 assert(cons0rhs == consdata0->rhs); /*lint !e777*/
    13373 assert(cons0upgraded == consdata0->upgraded);
    13374
    13375 cons1 = conss[c];
    13376
    13377 /* cons1 has become inactive during presolving of constraint pairs */
    13378 if( cons1 == NULL )
    13379 continue;
    13380
    13381 assert(SCIPconsIsActive(cons0) && !SCIPconsIsModifiable(cons0));
    13382 assert(SCIPconsIsActive(cons1) && !SCIPconsIsModifiable(cons1));
    13383
    13384 consdata1 = SCIPconsGetData(cons1);
    13385 assert(consdata1 != NULL);
    13386
    13387 /* SCIPdebugMsg(scip, "preprocess linear constraint pair <%s>[chgd:%d, upgd:%d] and <%s>[chgd:%d, upgd:%d]\n",
    13388 SCIPconsGetName(cons0), cons0changed, cons0upgraded,
    13389 SCIPconsGetName(cons1), consdata1->changed, consdata1->upgraded); */
    13390
    13391 /* if both constraints didn't change since last pair processing, we can ignore the pair */
    13392 if( !cons0changed && !consdata1->changed )
    13393 continue;
    13394
    13395 /* if both constraints are already upgraded, skip the pair;
    13396 * because changes on these constraints cannot be applied to the instance anymore */
    13397 if( cons0upgraded && consdata1->upgraded )
    13398 continue;
    13399
    13400 assert(consdata1->nvars >= 1);
    13401
    13402 /* sort the constraint */
    13403 SCIP_CALL( consdataSort(scip, consdata1) );
    13404
    13405 /* calculate bit signatures of cons1 for potentially positive and negative coefficients */
    13406 consdataCalcSignatures(consdata1);
    13407 possignature1 = consdata1->possignature;
    13408 negsignature1 = consdata1->negsignature;
    13409
    13410 /* the signatures give a quick test to check for domination and equality of coefficients */
    13411 coefsequal = (possignature0 == possignature1) && (negsignature0 == negsignature1);
    13412 coefsnegated = (possignature0 == negsignature1) && (negsignature0 == possignature1);
    13413 cons0dominateslhs = SCIPisGE(scip, cons0lhs, consdata1->lhs)
    13414 && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
    13415 && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
    13416 cons1dominateslhs = SCIPisGE(scip, consdata1->lhs, cons0lhs)
    13417 && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
    13418 && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
    13419 cons0dominatesrhs = SCIPisLE(scip, cons0rhs, consdata1->rhs)
    13420 && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
    13421 && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
    13422 cons1dominatesrhs = SCIPisLE(scip, consdata1->rhs, cons0rhs)
    13423 && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
    13424 && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
    13425 cons1isequality = SCIPisEQ(scip, consdata1->lhs, consdata1->rhs);
    13426 tryaggregation = (cons0isequality || cons1isequality) && (maxaggrnormscale > 0.0);
    13427 if( !cons0dominateslhs && !cons1dominateslhs && !cons0dominatesrhs && !cons1dominatesrhs
    13428 && !coefsequal && !coefsnegated && !tryaggregation )
    13429 continue;
    13430
    13431 /* make sure, we have enough memory for the index set of V_1 \ V_0 */
    13432 if( tryaggregation && consdata1->nvars > diffidx1minus0size )
    13433 {
    13434 SCIP_CALL( SCIPreallocBufferArray(scip, &diffidx1minus0, consdata1->nvars) );
    13435 diffidx1minus0size = consdata1->nvars;
    13436 }
    13437
    13438 /* check consdata0 against consdata1:
    13439 * - if lhs0 >= lhs1 and for each variable v and each solution value x_v val0[v]*x_v <= val1[v]*x_v,
    13440 * consdata0 dominates consdata1 w.r.t. left hand side
    13441 * - if rhs0 <= rhs1 and for each variable v and each solution value x_v val0[v]*x_v >= val1[v]*x_v,
    13442 * consdata0 dominates consdata1 w.r.t. right hand side
    13443 * - if val0[v] == -val1[v] for all variables v, the two inequalities can be replaced by a single
    13444 * ranged row (or equality)
    13445 * - if at least one constraint is an equality, count the weighted number of common variables W_c
    13446 * and the weighted number of variable in the difference sets W_0 = w(V_0 \ V_1), W_1 = w(V_1 \ V_0),
    13447 * where the weight of each variable depends on its type, such that aggregations in order to remove the
    13448 * number of continuous and integer variables are preferred:
    13449 * - if W_c > W_1, try to aggregate consdata0 := a * consdata0 + b * consdata1 in order to decrease the
    13450 * variable weight in consdata0, where a = +/- val1[v] and b = -/+ val0[v] for common v which leads to
    13451 * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
    13452 * to be positive to not switch the sense of the (in)equality cons0
    13453 * - if W_c > W_0, try to aggregate consdata1 := a * consdata1 + b * consdata0 in order to decrease the
    13454 * variable weight in consdata1, where a = +/- val0[v] and b = -/+ val1[v] for common v which leads to
    13455 * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
    13456 * to be positive to not switch the sense of the (in)equality cons1
    13457 */
    13458
    13459 /* check consdata0 against consdata1 for redundancy, or ranged row accumulation */
    13460 nvarscommon = 0;
    13461 commonidxweight = 0;
    13462 nvars0minus1 = 0;
    13463 diffidx0minus1weight = 0;
    13464 nvars1minus0 = 0;
    13465 diffidx1minus0weight = 0;
    13466 v0 = 0;
    13467 v1 = 0;
    13468 while( (v0 < consdata0->nvars || v1 < consdata1->nvars)
    13469 && (cons0dominateslhs || cons1dominateslhs || cons0dominatesrhs || cons1dominatesrhs
    13470 || coefsequal || coefsnegated || tryaggregation) )
    13471 {
    13472 SCIP_VAR* var;
    13473 SCIP_Real val0;
    13474 SCIP_Real val1;
    13475 int varcmp;
    13476
    13477 /* test, if variable appears in only one or in both constraints */
    13478 if( v0 < consdata0->nvars && v1 < consdata1->nvars )
    13479 varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
    13480 else if( v0 < consdata0->nvars )
    13481 varcmp = -1;
    13482 else
    13483 varcmp = +1;
    13484
    13485 switch( varcmp )
    13486 {
    13487 case -1:
    13488 /* variable doesn't appear in consdata1 */
    13489 var = consdata0->vars[v0];
    13490 val0 = consdata0->vals[v0];
    13491 val1 = 0.0;
    13492 if( tryaggregation )
    13493 {
    13494 diffidx0minus1[nvars0minus1] = v0;
    13495 nvars0minus1++;
    13496 diffidx0minus1weight += getVarWeight(var);
    13497 }
    13498 v0++;
    13499 coefsequal = FALSE;
    13500 coefsnegated = FALSE;
    13501 break;
    13502
    13503 case +1:
    13504 /* variable doesn't appear in consdata0 */
    13505 var = consdata1->vars[v1];
    13506 val0 = 0.0;
    13507 val1 = consdata1->vals[v1];
    13508 if( tryaggregation )
    13509 {
    13510 diffidx1minus0[nvars1minus0] = v1;
    13511 nvars1minus0++;
    13512 diffidx1minus0weight += getVarWeight(var);
    13513 }
    13514 v1++;
    13515 coefsequal = FALSE;
    13516 coefsnegated = FALSE;
    13517 break;
    13518
    13519 case 0:
    13520 /* variable appears in both constraints */
    13521 assert(consdata0->vars[v0] == consdata1->vars[v1]);
    13522 var = consdata0->vars[v0];
    13523 val0 = consdata0->vals[v0];
    13524 val1 = consdata1->vals[v1];
    13525 if( tryaggregation )
    13526 {
    13527 commonidx0[nvarscommon] = v0;
    13528 commonidx1[nvarscommon] = v1;
    13529 nvarscommon++;
    13530 commonidxweight += getVarWeight(var);
    13531 }
    13532 v0++;
    13533 v1++;
    13534 coefsequal = coefsequal && (SCIPisEQ(scip, val0, val1));
    13535 coefsnegated = coefsnegated && (SCIPisEQ(scip, val0, -val1));
    13536 break;
    13537
    13538 default:
    13539 SCIPerrorMessage("invalid comparison result\n");
    13540 SCIPABORT();
    13541 var = NULL;
    13542 val0 = 0.0;
    13543 val1 = 0.0;
    13544 }
    13545 assert(var != NULL);
    13546
    13547 /* update domination criteria w.r.t. the coefficient and the variable's bounds */
    13548 if( SCIPisGT(scip, val0, val1) )
    13549 {
    13551 {
    13552 cons0dominatesrhs = FALSE;
    13553 cons1dominateslhs = FALSE;
    13554 }
    13556 {
    13557 cons0dominateslhs = FALSE;
    13558 cons1dominatesrhs = FALSE;
    13559 }
    13560 }
    13561 else if( SCIPisLT(scip, val0, val1) )
    13562 {
    13564 {
    13565 cons0dominateslhs = FALSE;
    13566 cons1dominatesrhs = FALSE;
    13567 }
    13569 {
    13570 cons0dominatesrhs = FALSE;
    13571 cons1dominateslhs = FALSE;
    13572 }
    13573 }
    13574 }
    13575
    13576 /* check for disaggregated ranged rows */
    13577 if( coefsequal || coefsnegated )
    13578 {
    13579 SCIP_CONS* consstay;
    13580 SCIP_CONS* consdel;
    13581#ifndef NDEBUG
    13582 SCIP_CONSDATA* consdatastay;
    13583#endif
    13584 SCIP_CONSDATA* consdatadel;
    13585 SCIP_Real lhs;
    13586 SCIP_Real rhs;
    13587 int consinddel;
    13588
    13589 /* the coefficients in both rows are either equal or negated: create a new constraint with same coefficients and
    13590 * best left and right hand sides; delete the old constraints afterwards
    13591 */
    13592 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with %s coefficients into single ranged row\n",
    13593 SCIPconsGetName(cons0), SCIPconsGetName(cons1), coefsequal ? "equal" : "negated");
    13594 SCIPdebugPrintCons(scip, cons0, NULL);
    13595 SCIPdebugPrintCons(scip, cons1, NULL);
    13596
    13597 if( coefsequal )
    13598 {
    13599 /* the coefficients of both rows are equal */
    13600 lhs = MAX(consdata0->lhs, consdata1->lhs);
    13601 rhs = MIN(consdata0->rhs, consdata1->rhs);
    13602 }
    13603 else
    13604 {
    13605 /* the coefficients of both rows are negations */
    13606 lhs = MAX(consdata0->lhs, -consdata1->rhs);
    13607 rhs = MIN(consdata0->rhs, -consdata1->lhs);
    13608 }
    13609 if( SCIPisFeasLT(scip, rhs, lhs) )
    13610 {
    13611 SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
    13612 *cutoff = TRUE;
    13613 break;
    13614 }
    13615
    13616 /* check which constraint has to stay;
    13617 * changes applied to an upgraded constraint will not be considered in the instance */
    13618 if( consdata0->upgraded )
    13619 {
    13620 assert(!consdata1->upgraded);
    13621 consstay = cons1;
    13622#ifndef NDEBUG
    13623 consdatastay = consdata1;
    13624#endif
    13625
    13626 consdel = cons0;
    13627 consdatadel = consdata0;
    13628 consinddel = chkind;
    13629 }
    13630 else
    13631 {
    13632 consstay = cons0;
    13633#ifndef NDEBUG
    13634 consdatastay = consdata0;
    13635#endif
    13636
    13637 consdel = cons1;
    13638 consdatadel = consdata1;
    13639 consinddel = c;
    13640 }
    13641
    13642 /* update the sides of consstay */
    13643 SCIP_CALL( chgLhs(scip, consstay, lhs) );
    13644 SCIP_CALL( chgRhs(scip, consstay, rhs) );
    13645 if( !consdata0->upgraded )
    13646 {
    13647 assert(consstay == cons0);
    13648 cons0lhs = consdata0->lhs;
    13649 cons0rhs = consdata0->rhs;
    13650 }
    13651
    13652 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
    13653 SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) );
    13654
    13655 assert( !consdatastay->upgraded );
    13656 /* delete consdel */
    13657 SCIP_CALL( SCIPdelCons(scip, consdel) );
    13658 conss[consinddel] = NULL;
    13659 if( !consdatadel->upgraded )
    13660 (*ndelconss)++;
    13661 continue;
    13662 }
    13663
    13664 /* check for domination: remove dominated sides, but don't touch equalities as long as they are not totally
    13665 * redundant
    13666 */
    13667 if( cons1dominateslhs && (!cons0isequality || cons1dominatesrhs || SCIPisInfinity(scip, consdata0->rhs) ) )
    13668 {
    13669 /* left hand side is dominated by consdata1: delete left hand side of consdata0 */
    13670 SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
    13671 SCIPconsGetName(cons0), SCIPconsGetName(cons1));
    13672 SCIPdebugPrintCons(scip, cons0, NULL);
    13673 SCIPdebugPrintCons(scip, cons1, NULL);
    13674
    13675 /* check for infeasibility */
    13676 if( SCIPisFeasGT(scip, consdata1->lhs, consdata0->rhs) )
    13677 {
    13678 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
    13679 *cutoff = TRUE;
    13680 break;
    13681 }
    13682
    13683 /* remove redundant left hand side */
    13684 if( !SCIPisInfinity(scip, -consdata0->lhs) )
    13685 {
    13686 SCIP_CALL( chgLhs(scip, cons0, -SCIPinfinity(scip)) );
    13687 cons0lhs = consdata0->lhs;
    13688 cons0isequality = FALSE;
    13689 if( !consdata0->upgraded )
    13690 {
    13691 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
    13692 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
    13693
    13694 (*nchgsides)++;
    13695 }
    13696 }
    13697 }
    13698 else if( cons0dominateslhs && (!cons1isequality || cons0dominatesrhs || SCIPisInfinity(scip, consdata1->rhs)) )
    13699 {
    13700 /* left hand side is dominated by consdata0: delete left hand side of consdata1 */
    13701 SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
    13702 SCIPconsGetName(cons1), SCIPconsGetName(cons0));
    13703 SCIPdebugPrintCons(scip, cons1, NULL);
    13704 SCIPdebugPrintCons(scip, cons0, NULL);
    13705
    13706 /* check for infeasibility */
    13707 if( SCIPisFeasGT(scip, consdata0->lhs, consdata1->rhs) )
    13708 {
    13709 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
    13710 *cutoff = TRUE;
    13711 break;
    13712 }
    13713
    13714 /* remove redundant left hand side */
    13715 if( !SCIPisInfinity(scip, -consdata1->lhs) )
    13716 {
    13717 SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
    13718 cons1isequality = FALSE;
    13719 if( !consdata1->upgraded )
    13720 {
    13721 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
    13722 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
    13723
    13724 (*nchgsides)++;
    13725 }
    13726 }
    13727 }
    13728 if( cons1dominatesrhs && (!cons0isequality || cons1dominateslhs || SCIPisInfinity(scip, -consdata0->lhs)) )
    13729 {
    13730 /* right hand side is dominated by consdata1: delete right hand side of consdata0 */
    13731 SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
    13732 SCIPconsGetName(cons0), SCIPconsGetName(cons1));
    13733 SCIPdebugPrintCons(scip, cons0, NULL);
    13734 SCIPdebugPrintCons(scip, cons1, NULL);
    13735
    13736 /* check for infeasibility */
    13737 if( SCIPisFeasLT(scip, consdata1->rhs, consdata0->lhs) )
    13738 {
    13739 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
    13740 *cutoff = TRUE;
    13741 break;
    13742 }
    13743
    13744 /* remove redundant right hand side */
    13745 if( !SCIPisInfinity(scip, consdata0->rhs) )
    13746 {
    13747 SCIP_CALL( chgRhs(scip, cons0, SCIPinfinity(scip)) );
    13748 cons0rhs = consdata0->rhs;
    13749 cons0isequality = FALSE;
    13750 if( !consdata0->upgraded )
    13751 {
    13752 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
    13753 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
    13754
    13755 (*nchgsides)++;
    13756 }
    13757 }
    13758 }
    13759 else if( cons0dominatesrhs && (!cons1isequality || cons0dominateslhs || SCIPisInfinity(scip, -consdata1->lhs)) )
    13760 {
    13761 /* right hand side is dominated by consdata0: delete right hand side of consdata1 */
    13762 SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
    13763 SCIPconsGetName(cons1), SCIPconsGetName(cons0));
    13764 SCIPdebugPrintCons(scip, cons1, NULL);
    13765 SCIPdebugPrintCons(scip, cons0, NULL);
    13766
    13767 /* check for infeasibility */
    13768 if( SCIPisFeasLT(scip, consdata0->rhs, consdata1->lhs) )
    13769 {
    13770 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
    13771 *cutoff = TRUE;
    13772 break;
    13773 }
    13774
    13775 /* remove redundant right hand side */
    13776 if( !SCIPisInfinity(scip, consdata1->rhs) )
    13777 {
    13778 SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
    13779 cons1isequality = FALSE;
    13780 if( !consdata1->upgraded )
    13781 {
    13782 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
    13783 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
    13784
    13785 (*nchgsides)++;
    13786 }
    13787 }
    13788 }
    13789
    13790 /* check for now redundant constraints */
    13791 if( SCIPisInfinity(scip, -consdata0->lhs) && SCIPisInfinity(scip, consdata0->rhs) )
    13792 {
    13793 /* consdata0 became redundant */
    13794 SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons0));
    13795 SCIP_CALL( SCIPdelCons(scip, cons0) );
    13796 conss[chkind] = NULL;
    13797 if( !consdata0->upgraded )
    13798 {
    13799 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
    13800 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
    13801
    13802 (*ndelconss)++;
    13803 }
    13804 continue;
    13805 }
    13806 if( SCIPisInfinity(scip, -consdata1->lhs) && SCIPisInfinity(scip, consdata1->rhs) )
    13807 {
    13808 /* consdata1 became redundant */
    13809 SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons1));
    13810 SCIP_CALL( SCIPdelCons(scip, cons1) );
    13811 conss[c] = NULL;
    13812 if( !consdata1->upgraded )
    13813 {
    13814 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
    13815 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
    13816
    13817 (*ndelconss)++;
    13818 }
    13819 continue;
    13820 }
    13821
    13822 /* check, if we want to aggregate an (in)equality with an equality:
    13823 * consdata0 := a * consdata0 + b * consdata1 or consdata1 := a * consdata1 + b * consdata0
    13824 */
    13825 if( tryaggregation )
    13826 {
    13827 SCIP_Bool aggregated;
    13828
    13829 assert(consdata0->nvars == nvarscommon + nvars0minus1);
    13830 assert(consdata1->nvars == nvarscommon + nvars1minus0);
    13831
    13832 aggregated = FALSE;
    13833 if( cons1isequality && !consdata0->upgraded && commonidxweight > diffidx1minus0weight )
    13834 {
    13835 /* W_c > W_1: try to aggregate consdata0 := a * consdata0 + b * consdata1 */
    13836 SCIP_CALL( aggregateConstraints(scip, cons0, cons1, commonidx0, commonidx1, diffidx0minus1, diffidx1minus0,
    13837 nvarscommon, commonidxweight, diffidx0minus1weight, diffidx1minus0weight, maxaggrnormscale,
    13838 nchgcoefs, &aggregated, cutoff) );
    13839
    13840 if( *cutoff )
    13841 break;
    13842
    13843 /* update array of active constraints */
    13844 if( aggregated )
    13845 {
    13846 assert(!SCIPconsIsActive(cons0));
    13847 assert(SCIPconsIsActive(cons1));
    13848 conss[chkind] = NULL;
    13849 }
    13850 }
    13851 if( !aggregated && cons0isequality && !consdata1->upgraded && commonidxweight > diffidx0minus1weight )
    13852 {
    13853 /* W_c > W_0: try to aggregate consdata1 := a * consdata1 + b * consdata0 */
    13854 SCIP_CALL( aggregateConstraints(scip, cons1, cons0, commonidx1, commonidx0, diffidx1minus0, diffidx0minus1,
    13855 nvarscommon, commonidxweight, diffidx1minus0weight, diffidx0minus1weight, maxaggrnormscale,
    13856 nchgcoefs, &aggregated, cutoff) );
    13857
    13858 if( *cutoff )
    13859 break;
    13860
    13861 /* update array of active constraints */
    13862 if( aggregated )
    13863 {
    13864 assert(!SCIPconsIsActive(cons1));
    13865 assert(SCIPconsIsActive(cons0));
    13866 conss[c] = NULL;
    13867 }
    13868 }
    13869 }
    13870 }
    13871
    13872 /* free temporary memory */
    13873 SCIPfreeBufferArray(scip, &diffidx1minus0);
    13874 SCIPfreeBufferArray(scip, &diffidx0minus1);
    13875 SCIPfreeBufferArray(scip, &commonidx1);
    13876 SCIPfreeBufferArray(scip, &commonidx0);
    13877
    13878 return SCIP_OKAY;
    13879}
    13880
    13881/** do stuffing presolving on a single constraint */
    13882static
    13884 SCIP* scip, /**< SCIP data structure */
    13885 SCIP_CONS* cons, /**< linear constraint */
    13886 SCIP_Bool singletonstuffing, /**< should stuffing of singleton continuous variables be performed? */
    13887 SCIP_Bool singlevarstuffing, /**< should single variable stuffing be performed, which tries to fulfill
    13888 * constraints using the cheapest variable? */
    13889 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
    13890 int* nfixedvars, /**< pointer to count the total number of fixed variables */
    13891 int* nchgbds /**< pointer to count the total number of tightened bounds */
    13892 )
    13893{
    13894 SCIP_CONSDATA* consdata;
    13895 SCIP_Real* ratios;
    13896 int* varpos;
    13897 SCIP_Bool* swapped;
    13898 SCIP_VAR** vars;
    13899 SCIP_Real* vals;
    13900 SCIP_VAR* var;
    13901 SCIP_Real lb;
    13902 SCIP_Real ub;
    13903 SCIP_Real minactivity;
    13904 SCIP_Real maxactivity;
    13905 SCIP_Real maxcondactivity;
    13906 SCIP_Real mincondactivity;
    13907 SCIP_Real rhs;
    13908 SCIP_Real val;
    13909 SCIP_Real obj;
    13910 SCIP_Real factor;
    13911 SCIP_Bool isminacttight;
    13912 SCIP_Bool ismaxacttight;
    13913 SCIP_Bool isminsettoinfinity;
    13914 SCIP_Bool ismaxsettoinfinity;
    13915 SCIP_Bool tryfixing;
    13916 int nsingletons;
    13917 int idx;
    13918 int v;
    13919 int nvars;
    13920
    13921 assert(scip != NULL);
    13922 assert(cons != NULL);
    13923 assert(nfixedvars != NULL);
    13924
    13925 consdata = SCIPconsGetData(cons);
    13926
    13927 /* we only want to run for inequalities */
    13928 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->lhs) )
    13929 return SCIP_OKAY;
    13930
    13931 if( singlevarstuffing )
    13932 {
    13933 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
    13934 &isminsettoinfinity, &ismaxsettoinfinity);
    13935 }
    13936 else
    13937 {
    13938 minactivity = SCIP_INVALID;
    13939 maxactivity = SCIP_INVALID;
    13940 isminsettoinfinity = FALSE;
    13941 ismaxsettoinfinity = FALSE;
    13942 }
    13943
    13944 /* we want to have a <= constraint, if the rhs is infinite, we implicitly multiply the constraint by -1,
    13945 * the new maxactivity is minus the old minactivity then
    13946 */
    13947 if( SCIPisInfinity(scip, consdata->rhs) )
    13948 {
    13949 rhs = -consdata->lhs;
    13950 factor = -1.0;
    13951 maxactivity = -minactivity;
    13952 ismaxsettoinfinity = isminsettoinfinity;
    13953 }
    13954 else
    13955 {
    13956 assert(SCIPisInfinity(scip, -consdata->lhs));
    13957 rhs = consdata->rhs;
    13958 factor = 1.0;
    13959 }
    13960
    13961 nvars = consdata->nvars;
    13962 vars = consdata->vars;
    13963 vals = consdata->vals;
    13964
    13965 /* check for continuous singletons */
    13966 if( singletonstuffing )
    13967 {
    13968 for( v = 0; v < nvars; ++v )
    13969 {
    13970 var = vars[v];
    13971
    13972 if( !SCIPvarIsIntegral(var)
    13974 break;
    13975 }
    13976 }
    13977 else
    13978 /* we don't want to go into the next block */
    13979 v = nvars;
    13980
    13981 /* a singleton was found -> perform singleton variable stuffing */
    13982 if( v < nvars )
    13983 {
    13984 assert(singletonstuffing);
    13985
    13986 SCIP_CALL( SCIPallocBufferArray(scip, &varpos, nvars) );
    13987 SCIP_CALL( SCIPallocBufferArray(scip, &ratios, nvars) );
    13988 SCIP_CALL( SCIPallocBufferArray(scip, &swapped, nvars) );
    13989
    13990 tryfixing = TRUE;
    13991 nsingletons = 0;
    13992 mincondactivity = 0.0;
    13993 maxcondactivity = 0.0;
    13994
    13995 for( v = 0; v < nvars; ++v )
    13996 {
    13997 var = vars[v];
    13998 lb = SCIPvarGetLbGlobal(var);
    13999 ub = SCIPvarGetUbGlobal(var);
    14000 obj = SCIPvarGetObj(var);
    14001 val = factor * vals[v];
    14002
    14003 assert(!SCIPisZero(scip, val));
    14004
    14005 /* the variable is a singleton and continuous */
    14006 if( !SCIPvarIsIntegral(var)
    14008 {
    14009 if( SCIPisNegative(scip, obj) && val > 0 )
    14010 {
    14011 /* case 1: obj < 0 and coef > 0 */
    14012 if( SCIPisInfinity(scip, -lb) )
    14013 {
    14014 tryfixing = FALSE;
    14015 break;
    14016 }
    14017
    14018 maxcondactivity += val * lb;
    14019 mincondactivity += val * lb;
    14020 swapped[v] = FALSE;
    14021 ratios[nsingletons] = obj / val;
    14022 varpos[nsingletons] = v;
    14023 nsingletons++;
    14024 }
    14025 else if( SCIPisPositive(scip, obj) && val < 0 )
    14026 {
    14027 /* case 2: obj > 0 and coef < 0 */
    14028 if( SCIPisInfinity(scip, ub) )
    14029 {
    14030 tryfixing = FALSE;
    14031 break;
    14032 }
    14033 /* multiply column by (-1) to become case 1.
    14034 * now bounds are swapped: ub := -lb, lb := -ub
    14035 */
    14036
    14037 maxcondactivity += val * ub;
    14038 mincondactivity += val * ub;
    14039 swapped[v] = TRUE;
    14040 ratios[nsingletons] = obj / val;
    14041 varpos[nsingletons] = v;
    14042 nsingletons++;
    14043 }
    14044 else if( val > 0 )
    14045 {
    14046 /* case 3: obj >= 0 and coef >= 0 is handled by duality fixing.
    14047 * we only consider the lower bound for the constants
    14048 */
    14049 assert(!SCIPisNegative(scip, obj));
    14050
    14051 if( SCIPisInfinity(scip, -lb) )
    14052 {
    14053 /* maybe unbounded */
    14054 tryfixing = FALSE;
    14055 break;
    14056 }
    14057
    14058 maxcondactivity += val * lb;
    14059 mincondactivity += val * lb;
    14060 }
    14061 else
    14062 {
    14063 /* case 4: obj <= 0 and coef <= 0 is also handled by duality fixing.
    14064 * we only consider the upper bound for the constants
    14065 */
    14066 assert(!SCIPisPositive(scip, obj));
    14067 assert(val < 0);
    14068
    14069 if( SCIPisInfinity(scip, ub) )
    14070 {
    14071 /* maybe unbounded */
    14072 tryfixing = FALSE;
    14073 break;
    14074 }
    14075
    14076 maxcondactivity += val * ub;
    14077 mincondactivity += val * ub;
    14078 }
    14079 }
    14080 else
    14081 {
    14082 /* consider contribution of discrete variables, non-singleton
    14083 * continuous variables and variables with more than one lock
    14084 */
    14085 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
    14086 {
    14087 tryfixing = FALSE;
    14088 break;
    14089 }
    14090
    14091 if( val > 0 )
    14092 {
    14093 maxcondactivity += val * ub;
    14094 mincondactivity += val * lb;
    14095 }
    14096 else
    14097 {
    14098 maxcondactivity += val * lb;
    14099 mincondactivity += val * ub;
    14100 }
    14101 }
    14102 }
    14103 if( tryfixing && nsingletons > 0 && (SCIPisGT(scip, rhs, maxcondactivity) || SCIPisLE(scip, rhs, mincondactivity)) )
    14104 {
    14105 SCIP_Real delta;
    14106 SCIP_Bool tightened;
    14107#ifdef SCIP_DEBUG
    14108 int oldnfixedvars = *nfixedvars;
    14109#endif
    14110
    14111 SCIPsortRealInt(ratios, varpos, nsingletons);
    14112
    14113 /* verify which singleton continuous variables can be fixed */
    14114 for( v = 0; v < nsingletons; ++v )
    14115 {
    14116 idx = varpos[v];
    14117 var = vars[idx];
    14118 val = factor * vals[idx];
    14119 lb = SCIPvarGetLbGlobal(var);
    14120 ub = SCIPvarGetUbGlobal(var);
    14121
    14122 assert(val > 0 || SCIPisPositive(scip, SCIPvarGetObj(var)));
    14123 assert((val < 0) == swapped[idx]);
    14124 val = REALABS(val);
    14125
    14126 /* stop fixing if variable bounds are not finite */
    14127 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
    14128 break;
    14129
    14132 assert(!SCIPvarIsIntegral(var));
    14133
    14134 /* calculate the change in the row activities if this variable changes
    14135 * its value from its worst to its best bound
    14136 */
    14137 if( swapped[idx] )
    14138 delta = -(lb - ub) * val;
    14139 else
    14140 delta = (ub - lb) * val;
    14141
    14142 assert(!SCIPisNegative(scip, delta));
    14143
    14144 if( SCIPisLE(scip, delta, rhs - maxcondactivity) )
    14145 {
    14146 if( swapped[idx] )
    14147 {
    14148 SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
    14149 SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
    14150 }
    14151 else
    14152 {
    14153 SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
    14154 SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
    14155 }
    14156
    14157 if( *cutoff )
    14158 break;
    14159 if( tightened )
    14160 {
    14161 (*nfixedvars)++;
    14162 }
    14163 }
    14164 /* @note: we could in theory tighten the bound of the first singleton variable which does not fall into the above case,
    14165 * since it cannot be fully fixed. However, this is not needed and should be done by activity-based bound tightening
    14166 * anyway after all other continuous singleton columns were fixed; doing it here may introduce numerical
    14167 * troubles in case of large bounds.
    14168 */
    14169 else if( SCIPisLE(scip, rhs, mincondactivity) )
    14170 {
    14171 if( swapped[idx] )
    14172 {
    14173 SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
    14174 SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
    14175 }
    14176 else
    14177 {
    14178 SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
    14179 SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
    14180 }
    14181
    14182 if( *cutoff )
    14183 break;
    14184 if( tightened )
    14185 {
    14186 (*nfixedvars)++;
    14187 }
    14188 }
    14189
    14190 maxcondactivity += delta;
    14191 mincondactivity += delta;
    14192 }
    14193
    14194#ifdef SCIP_DEBUG
    14195 if( *nfixedvars - oldnfixedvars > 0 )
    14196 {
    14197 SCIPdebugMsg(scip, "### stuffing fixed %d variables\n", *nfixedvars - oldnfixedvars);
    14198 }
    14199#endif
    14200 }
    14201
    14202 SCIPfreeBufferArray(scip, &swapped);
    14203 SCIPfreeBufferArray(scip, &ratios);
    14204 SCIPfreeBufferArray(scip, &varpos);
    14205 }
    14206
    14207 /* perform single-variable stuffing:
    14208 * for a linear inequality
    14209 * a_1 x_1 + a_2 x_2 + ... + a_n x_n <= b
    14210 * with a_i > 0 and objective coefficients c_i < 0,
    14211 * setting all variables to their upper bound (giving us the maximal activity of the constraint) is worst w.r.t.
    14212 * feasibility of the constraint. On the other hand, this gives the best objective function contribution of the
    14213 * variables contained in the constraint. The maximal activity should be larger than the rhs, otherwise the constraint
    14214 * is redundant.
    14215 * Now we are searching for a variable x_k with maximal ratio c_k / a_k (note that all these ratios are negative), so
    14216 * that by reducing the value of this variable we reduce the activity of the constraint while having the smallest
    14217 * objective deterioration per activity unit. If x_k has no downlocks, is continuous, and can be reduced enough to
    14218 * render the constraint feasible, and ALL other variables have only the one uplock installed by the current constraint,
    14219 * we can reduce the upper bound of x_k such that the maxactivity equals the rhs and fix all other variables to their
    14220 * upper bound.
    14221 * Note that the others variables may have downlocks from other constraints, which we do not need to care
    14222 * about since we are setting them to the highest possible value. Also, they may be integer or binary, because the
    14223 * computed ratio is still a lower bound on the change in the objective caused by reducing those variable to reach
    14224 * constraint feasibility. On the other hand, uplocks on x_k from other constraint do no interfer with the method.
    14225 * With a slight adjustment, the procedure even works for integral x_k. If (maxactivity - rhs)/val is integral,
    14226 * the variable gets an integral value in order to fulfill the constraint tightly, and we can just apply the procedure.
    14227 * If (maxactivity - rhs)/val is fractional, we need to check, if overfulfilling the constraint by setting x_k to
    14228 * ceil((maxactivity - rhs)/val) is still better than setting x_k to ceil((maxactivity - rhs)/val) - 1 and
    14229 * filling the remaining gap in the constraint with the next-best variable. For this, we check that
    14230 * c_k * ceil((maxactivity - rhs)/val) is still better than
    14231 * c_k * floor((maxactivity - rhs)/val) + c_j * ((maxactivity - rhs) - (floor((maxactivity - rhs)/val) * val))/a_j.
    14232 * In this case, the upper bound of x_k is decreased to ub_k - ceil(maxactivity - rhs).
    14233 * If there are variables with a_i < 0 and c_i > 0, they are negated to obtain the above form, variables with same
    14234 * sign of coefficients in constraint and objective prevent the use of this method.
    14235 */
    14236 if( singlevarstuffing && !ismaxsettoinfinity )
    14237 {
    14238 SCIP_Real bestratio = -SCIPinfinity(scip);
    14239 SCIP_Real secondbestratio = -SCIPinfinity(scip);
    14240 SCIP_Real ratio;
    14241 int bestindex = -1;
    14242 int bestuplocks = 0;
    14243 int bestdownlocks = 1;
    14244 int downlocks;
    14245 int uplocks;
    14246 SCIPdebug( int oldnfixedvars = *nfixedvars; )
    14247 SCIPdebug( int oldnchgbds = *nchgbds; )
    14248
    14249 /* loop over all variables to identify the best and second-best ratio */
    14250 for( v = 0; v < nvars; ++v )
    14251 {
    14252 var = vars[v];
    14253 obj = SCIPvarGetObj(var);
    14254 val = factor * vals[v];
    14255
    14256 assert(!SCIPisZero(scip, val));
    14257
    14258 ratio = obj / val;
    14259
    14260 /* if both objective and constraint push the variable to the same direction, we can do nothing here */
    14261 if( !SCIPisNegative(scip, ratio) )
    14262 {
    14263 bestindex = -1;
    14264 break;
    14265 }
    14266
    14267 if( val > 0 )
    14268 {
    14271 }
    14272 else
    14273 {
    14276 }
    14277
    14278 /* better ratio, update best candidate
    14279 * @todo use some tolerance
    14280 * @todo check size of domain and updated ratio for integer variables already?
    14281 */
    14282 if( ratio > bestratio || ( downlocks == 0 && ratio == bestratio && ( bestdownlocks > 0 /*lint !e777*/
    14283 || ( !SCIPvarIsIntegral(var) && SCIPvarIsIntegral(vars[bestindex]) ) ) ) )
    14284 {
    14285 /* best index becomes second-best*/
    14286 if( bestindex != -1 )
    14287 {
    14288 /* second-best index must not have more than 1 uplock */
    14289 if( bestuplocks > 1 )
    14290 {
    14291 bestindex = -1;
    14292 break;
    14293 }
    14294 else
    14295 {
    14296 secondbestratio = bestratio;
    14297 }
    14298 }
    14299 bestdownlocks = downlocks;
    14300 bestuplocks = uplocks;
    14301 bestratio = ratio;
    14302 bestindex = v;
    14303
    14304 /* if this variable is the best in the end, we cannot do reductions since it has a downlocks,
    14305 * if it is not the best, it has too many uplocks -> not applicable
    14306 */
    14307 if( bestdownlocks > 0 && bestuplocks > 1 )
    14308 {
    14309 bestindex = -1;
    14310 break;
    14311 }
    14312 }
    14313 else
    14314 {
    14315 /* non-best index must not have more than 1 uplock */
    14316 if( uplocks > 1 )
    14317 {
    14318 bestindex = -1;
    14319 break;
    14320 }
    14321 /* update second-best ratio */
    14322 if( ratio > secondbestratio )
    14323 {
    14324 secondbestratio = ratio;
    14325 }
    14326 }
    14327 }
    14328
    14329 /* check if we can apply single variable stuffing */
    14330 if( bestindex != -1 && bestdownlocks == 0 )
    14331 {
    14332 SCIP_Bool tightened = FALSE;
    14333 SCIP_Real bounddelta;
    14334
    14335 var = vars[bestindex];
    14336 obj = SCIPvarGetObj(var);
    14337 val = factor * vals[bestindex];
    14338 lb = SCIPvarGetLbGlobal(var);
    14339 ub = SCIPvarGetUbGlobal(var);
    14340 tryfixing = TRUE;
    14341
    14342 if( val < 0 )
    14343 {
    14344 assert(!SCIPisNegative(scip, obj));
    14345
    14346 /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
    14347 if( SCIPvarIsIntegral(var) && !SCIPisIntegral(scip, (maxactivity - rhs) / val) )
    14348 {
    14349 SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/-val);
    14350 SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * -val);
    14351 assert(SCIPisPositive(scip, activitydelta));
    14352
    14353 tryfixing = SCIPisLE(scip, obj, -activitydelta * secondbestratio);
    14354
    14355 bounddelta = SCIPceil(scip, (maxactivity - rhs)/-val);
    14356 assert(SCIPisPositive(scip, bounddelta));
    14357 }
    14358 else
    14359 bounddelta = (maxactivity - rhs)/-val;
    14360
    14361 tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
    14362
    14363 if( tryfixing )
    14364 {
    14366
    14367 if( SCIPisEQ(scip, lb + bounddelta, ub) )
    14368 {
    14369 SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), lb + bounddelta);
    14370 SCIP_CALL( SCIPfixVar(scip, var, lb + bounddelta, cutoff, &tightened) );
    14371 }
    14372 else
    14373 {
    14374 SCIPdebugMsg(scip, "tighten the lower bound of <%s> from %g to %g (ub=%g)\n", SCIPvarGetName(var), lb, lb + bounddelta, ub);
    14375 SCIP_CALL( SCIPtightenVarLb(scip, var, lb + bounddelta, FALSE, cutoff, &tightened) );
    14376 }
    14377 }
    14378 }
    14379 else
    14380 {
    14381 assert(!SCIPisPositive(scip, obj));
    14382
    14383 /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
    14384 if( SCIPvarIsIntegral(var) && !SCIPisIntegral(scip, (maxactivity - rhs) / val) )
    14385 {
    14386 SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/val);
    14387 SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * val);
    14388 assert(SCIPisPositive(scip, activitydelta));
    14389
    14390 tryfixing = SCIPisLE(scip, -obj, activitydelta * secondbestratio);
    14391
    14392 bounddelta = SCIPceil(scip, (maxactivity - rhs)/val);
    14393 assert(SCIPisPositive(scip, bounddelta));
    14394 }
    14395 else
    14396 bounddelta = (maxactivity - rhs)/val;
    14397
    14398 tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
    14399
    14400 if( tryfixing )
    14401 {
    14403
    14404 if( SCIPisEQ(scip, ub - bounddelta, lb) )
    14405 {
    14406 SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), ub - bounddelta);
    14407 SCIP_CALL( SCIPfixVar(scip, var, ub - bounddelta, cutoff, &tightened) );
    14408 }
    14409 else
    14410 {
    14411 SCIPdebugMsg(scip, "tighten the upper bound of <%s> from %g to %g (lb=%g)\n", SCIPvarGetName(var), ub, ub - bounddelta, lb);
    14412 SCIP_CALL( SCIPtightenVarUb(scip, var, ub - bounddelta, FALSE, cutoff, &tightened) );
    14413 }
    14414 }
    14415 }
    14416
    14417 if( *cutoff )
    14418 return SCIP_OKAY;
    14419 if( tightened )
    14420 {
    14422 ++(*nfixedvars);
    14423 else
    14424 ++(*nchgbds);
    14425
    14426 SCIPdebugMsg(scip, "cons <%s>: %g <=\n", SCIPconsGetName(cons), factor > 0 ? consdata->lhs : -consdata->rhs);
    14427 for( v = 0; v < nvars; ++v )
    14428 {
    14429 SCIPdebugMsg(scip, "%+g <%s>([%g,%g],%g,[%d,%d],%s)\n", factor * vals[v], SCIPvarGetName(vars[v]),
    14430 SCIPvarGetLbGlobal(vars[v]), SCIPvarGetUbGlobal(vars[v]), SCIPvarGetObj(vars[v]),
    14433 SCIPvarIsIntegral(vars[v]) ? "I" : "C");
    14434 }
    14435 SCIPdebugMsg(scip, "<= %g\n", factor > 0 ? consdata->rhs : -consdata->lhs);
    14436
    14437 for( v = 0; v < nvars; ++v )
    14438 {
    14439 if( v == bestindex )
    14440 continue;
    14441
    14442 if( factor * vals[v] < 0 )
    14443 {
    14444 assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
    14445 SCIPdebugMsg(scip, "fix <%s> to its lower bound (%g)\n",
    14446 SCIPvarGetName(vars[v]), SCIPvarGetLbGlobal(vars[v]));
    14447 SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetLbGlobal(vars[v]), cutoff, &tightened) );
    14448 }
    14449 else
    14450 {
    14451 assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
    14452 SCIPdebugMsg(scip, "fix <%s> to its upper bound (%g)\n",
    14453 SCIPvarGetName(vars[v]), SCIPvarGetUbGlobal(vars[v]));
    14454 SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetUbGlobal(vars[v]), cutoff, &tightened) );
    14455 }
    14456
    14457 if( *cutoff )
    14458 return SCIP_OKAY;
    14459 if( tightened )
    14460 ++(*nfixedvars);
    14461 }
    14462 SCIPdebug( SCIPdebugMsg(scip, "### new stuffing fixed %d vars, tightened %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds); )
    14463 }
    14464 }
    14465 }
    14466
    14467 return SCIP_OKAY;
    14468}
    14469
    14470/** applies full dual presolving on variables that only appear in linear constraints */
    14471static
    14473 SCIP* scip, /**< SCIP data structure */
    14474 SCIP_CONS** conss, /**< constraint set */
    14475 int nconss, /**< number of constraints */
    14476 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
    14477 int* nchgbds, /**< pointer to count the number of bound changes */
    14478 int* nchgvartypes /**< pointer to count the number of variable type changes */
    14479 )
    14480{
    14481 SCIP_Real* redlb;
    14482 SCIP_Real* redub;
    14483 int* nlocksdown;
    14484 int* nlocksup;
    14485 SCIP_Bool* isimplint;
    14486 SCIP_VAR** origvars;
    14487 SCIP_VAR** vars;
    14488 SCIP_VAR** conscontvars;
    14489 int nvars;
    14490 int nbinvars;
    14491 int nintvars;
    14492 int ncontvars;
    14493 int v;
    14494 int c;
    14495
    14496 /* we calculate redundancy bounds with the following meaning:
    14497 * redlb[v] == k : if x_v >= k, we can always round x_v down to x_v == k without violating any constraint
    14498 * redub[v] == k : if x_v <= k, we can always round x_v up to x_v == k without violating any constraint
    14499 * then:
    14500 * c_v >= 0 : x_v <= redlb[v] is feasible due to optimality
    14501 * c_v <= 0 : x_v >= redub[v] is feasible due to optimality
    14502 */
    14503
    14504 /* Additionally, we detect continuous variables that are implied integral.
    14505 * A continuous variable j is implied integral if it only has only +/-1 coefficients,
    14506 * and all constraints (including the bounds as trivial constraints) in which:
    14507 * c_j > 0: the variable is down-locked,
    14508 * c_j < 0: the variable is up-locked,
    14509 * c_j = 0: the variable appears
    14510 * have, apart from j, only integer variables with integral coefficients and integral sides.
    14511 * This is because then, the value of the variable is either determined by one of its bounds or
    14512 * by one of these constraints, and in all cases, the value of the variable is integral.
    14513 */
    14514
    14515 assert(scip != NULL);
    14516 assert(nconss == 0 || conss != NULL);
    14517 assert(nchgbds != NULL);
    14518 assert(!SCIPinProbing(scip));
    14519
    14520 /* get active variables */
    14521 nvars = SCIPgetNVars(scip);
    14522 origvars = SCIPgetVars(scip);
    14523
    14524 /* if the problem is a pure binary program, nothing can be achieved by full dual presolve */
    14525 nbinvars = SCIPgetNBinVars(scip);
    14526 if( nbinvars == nvars )
    14527 return SCIP_OKAY;
    14528
    14529 /* get number of continuous variables */
    14530 ncontvars = SCIPgetNContVars(scip);
    14531 nintvars = nvars - ncontvars;
    14532
    14533 /* copy the variable array since this array might change during the curse of this algorithm */
    14534 nvars = nvars - nbinvars;
    14535 SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &(origvars[nbinvars]), nvars) );
    14536
    14537 /* allocate temporary memory */
    14538 SCIP_CALL( SCIPallocBufferArray(scip, &redlb, nvars) );
    14539 SCIP_CALL( SCIPallocBufferArray(scip, &redub, nvars) );
    14540 SCIP_CALL( SCIPallocBufferArray(scip, &nlocksdown, nvars) );
    14541 SCIP_CALL( SCIPallocBufferArray(scip, &nlocksup, nvars) );
    14542 SCIP_CALL( SCIPallocBufferArray(scip, &isimplint, ncontvars) );
    14543 SCIP_CALL( SCIPallocBufferArray(scip, &conscontvars, ncontvars) );
    14544
    14545 /* initialize redundancy bounds */
    14546 for( v = 0; v < nvars; ++v )
    14547 {
    14548 assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY || SCIPvarIsImpliedIntegral(vars[v]));
    14549 redlb[v] = SCIPvarGetLbGlobal(vars[v]);
    14550 redub[v] = SCIPvarGetUbGlobal(vars[v]);
    14551 }
    14552 BMSclearMemoryArray(nlocksdown, nvars);
    14553 BMSclearMemoryArray(nlocksup, nvars);
    14554
    14555 /* Initialize isimplint array: variable may be implied integral if rounded to their best bound they are integral
    14556 * we better not use SCIPisFeasIntegral() in these checks.
    14557 */
    14558 for( v = 0; v < ncontvars; v++ )
    14559 {
    14560 SCIP_VAR* var;
    14561 SCIP_Real obj;
    14562 SCIP_Real lb;
    14563 SCIP_Real ub;
    14564
    14565 var = vars[v + nintvars - nbinvars];
    14566 assert(!SCIPvarIsIntegral(var));
    14567
    14568 lb = SCIPvarGetLbGlobal(var);
    14569 ub = SCIPvarGetUbGlobal(var);
    14570
    14571 obj = SCIPvarGetObj(var);
    14572 if( SCIPisZero(scip, obj) )
    14573 isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb)) && (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
    14574 else
    14575 {
    14576 if( SCIPisPositive(scip, obj) )
    14577 isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb));
    14578 else
    14579 {
    14580 assert(SCIPisNegative(scip, obj));
    14581 isimplint[v] = (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
    14582 }
    14583 }
    14584 }
    14585
    14586 /* scan all constraints */
    14587 for( c = 0; c < nconss; ++c )
    14588 {
    14589 /* we only need to consider constraints that have been locked (i.e., checked constraints or constraints that are
    14590 * part of checked disjunctions)
    14591 */
    14592 if( SCIPconsIsLocked(conss[c]) )
    14593 {
    14594 SCIP_CONSDATA* consdata;
    14595 SCIP_Bool lhsexists;
    14596 SCIP_Bool rhsexists;
    14597 SCIP_Bool hasimpliedpotential;
    14598 SCIP_Bool integralcoefs;
    14599 int nlockspos;
    14600 int contvarpos;
    14601 int nconscontvars;
    14602 int i;
    14603
    14604 consdata = SCIPconsGetData(conss[c]);
    14605 assert(consdata != NULL);
    14606
    14607 /* get number of times the constraint was locked */
    14608 nlockspos = SCIPconsGetNLocksPos(conss[c]);
    14609
    14610 /* we do not want to include constraints with locked negation (this would be too weird) */
    14611 if( SCIPconsGetNLocksNeg(conss[c]) > 0 )
    14612 {
    14613 /* mark all non-implied continuous variables */
    14614 for( i = 0; i < consdata->nvars; ++i )
    14615 {
    14616 SCIP_VAR* var;
    14617
    14618 var = consdata->vars[i];
    14619 if( !SCIPvarIsIntegral(var) )
    14620 {
    14621 int contv;
    14622 contv = SCIPvarGetProbindex(var) - nintvars;
    14623 assert(0 <= contv && contv < ncontvars); /* variable should be active due to applyFixings() */
    14624 isimplint[contv] = FALSE;
    14625 }
    14626 }
    14627 continue;
    14628 }
    14629
    14630 /* check for existing sides */
    14631 lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
    14632 rhsexists = !SCIPisInfinity(scip, consdata->rhs);
    14633
    14634 /* count locks and update redundancy bounds */
    14635 contvarpos = -1;
    14636 nconscontvars = 0;
    14637 hasimpliedpotential = FALSE;
    14638 integralcoefs = !SCIPconsIsModifiable(conss[c]);
    14639
    14640 for( i = 0; i < consdata->nvars; ++i )
    14641 {
    14642 SCIP_VAR* var;
    14643 SCIP_Real val;
    14644 SCIP_Real minresactivity;
    14645 SCIP_Real maxresactivity;
    14646 SCIP_Real newredlb;
    14647 SCIP_Real newredub;
    14648 SCIP_Bool ismintight;
    14649 SCIP_Bool ismaxtight;
    14650 SCIP_Bool isminsettoinfinity;
    14651 SCIP_Bool ismaxsettoinfinity;
    14652 int arrayindex;
    14653
    14654 var = consdata->vars[i];
    14655 assert(var != NULL);
    14656 val = consdata->vals[i];
    14657 assert(!SCIPisZero(scip, val));
    14658
    14659 /* check if still all integer variables have integral coefficients */
    14660 if( SCIPvarIsIntegral(var) )
    14661 integralcoefs = integralcoefs && SCIPisIntegral(scip, val);
    14662
    14663 /* we do not need to process binary variables */
    14664 if( SCIPvarIsBinary(var) )
    14665 continue;
    14666
    14667 if( SCIPconsIsModifiable(conss[c]) )
    14668 {
    14669 minresactivity = -SCIPinfinity(scip);
    14670 maxresactivity = SCIPinfinity(scip);
    14671 isminsettoinfinity = TRUE;
    14672 ismaxsettoinfinity = TRUE;
    14673 }
    14674 else
    14675 {
    14676 /* calculate residual activity bounds if variable would be fixed to zero */
    14677 consdataGetGlbActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
    14678 &ismintight, &ismaxtight, &isminsettoinfinity, &ismaxsettoinfinity);
    14679
    14680 /* We called consdataGetGlbActivityResiduals() saying that we do not need a good relaxation,
    14681 * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
    14682 * This is needed, because we do not want to rely on relaxed finite resactivities.
    14683 */
    14684 assert((ismintight || isminsettoinfinity) && (ismaxtight || ismaxsettoinfinity));
    14685
    14686 /* check minresactivity for reliability */
    14687 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
    14688 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, TRUE);
    14689
    14690 /* check maxresactivity for reliability */
    14691 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
    14692 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, TRUE);
    14693 }
    14694
    14695 arrayindex = SCIPvarGetProbindex(var) - nbinvars;
    14696
    14697 assert(0 <= arrayindex && arrayindex < nvars); /* variable should be active due to applyFixings() */
    14698
    14699 newredlb = redlb[arrayindex];
    14700 newredub = redub[arrayindex];
    14701 if( val > 0.0 )
    14702 {
    14703 if( lhsexists )
    14704 {
    14705 /* lhs <= d*x + a*y, d > 0 -> redundant in y if x >= (lhs - min{a*y})/d */
    14706 nlocksdown[arrayindex] += nlockspos;
    14707 newredlb = (isminsettoinfinity ? SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
    14708 }
    14709 if( rhsexists )
    14710 {
    14711 /* d*x + a*y <= rhs, d > 0 -> redundant in y if x <= (rhs - max{a*y})/d */
    14712 nlocksup[arrayindex] += nlockspos;
    14713 newredub = (ismaxsettoinfinity ? -SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
    14714 }
    14715 }
    14716 else
    14717 {
    14718 if( lhsexists )
    14719 {
    14720 /* lhs <= d*x + a*y, d < 0 -> redundant in y if x <= (lhs - min{a*y})/d */
    14721 nlocksup[arrayindex] += nlockspos;
    14722 newredub = (isminsettoinfinity ? -SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
    14723 }
    14724 if( rhsexists )
    14725 {
    14726 /* d*x + a*y <= rhs, d < 0 -> redundant in y if x >= (rhs - max{a*y})/d */
    14727 nlocksdown[arrayindex] += nlockspos;
    14728 newredlb = (ismaxsettoinfinity ? SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
    14729 }
    14730 }
    14731
    14732 /* if the variable is integer, we have to round the value to the next integral value */
    14733 if( SCIPvarIsIntegral(var) )
    14734 {
    14735 if( !SCIPisInfinity(scip, newredlb) )
    14736 newredlb = SCIPceil(scip, newredlb);
    14737 if( !SCIPisInfinity(scip, -newredub) )
    14738 newredub = SCIPfloor(scip, newredub);
    14739 }
    14740
    14741 /* update redundancy bounds */
    14742 redlb[arrayindex] = MAX(redlb[arrayindex], newredlb);
    14743 redub[arrayindex] = MIN(redub[arrayindex], newredub);
    14744
    14745 /* collect the continuous variables of the constraint */
    14746 if( !SCIPvarIsIntegral(var) )
    14747 {
    14748 int contv;
    14749
    14750 assert(nconscontvars < ncontvars);
    14751 contvarpos = i;
    14752 conscontvars[nconscontvars] = var;
    14753 nconscontvars++;
    14754
    14755 contv = SCIPvarGetProbindex(var) - nintvars;
    14756 assert(0 <= contv && contv < ncontvars);
    14757 hasimpliedpotential = hasimpliedpotential || isimplint[contv];
    14758 }
    14759 }
    14760
    14761 /* update implied integrality status of continuous variables */
    14762 if( hasimpliedpotential )
    14763 {
    14764 if( nconscontvars > 1 || !integralcoefs )
    14765 {
    14766 /* there is more than one continuous variable or the integer variables have fractional coefficients:
    14767 * none of the continuous variables is implied integral
    14768 */
    14769 for( i = 0; i < nconscontvars; i++ )
    14770 {
    14771 int contv;
    14772 contv = SCIPvarGetProbindex(conscontvars[i]) - nintvars;
    14773 assert(0 <= contv && contv < ncontvars);
    14774 isimplint[contv] = FALSE;
    14775 }
    14776 }
    14777 else
    14778 {
    14779 SCIP_VAR* var;
    14780 SCIP_Real val;
    14781 SCIP_Real absval;
    14782 int contv;
    14783
    14784 /* there is exactly one continuous variable and the integer variables have integral coefficients:
    14785 * this is the interesting case, and we have to check whether the coefficient is +/-1 and the corresponding
    14786 * side(s) of the constraint is integral
    14787 */
    14788 assert(nconscontvars == 1);
    14789 assert(0 <= contvarpos && contvarpos < consdata->nvars);
    14790 var = consdata->vars[contvarpos];
    14791 val = consdata->vals[contvarpos];
    14792 contv = SCIPvarGetProbindex(var) - nintvars;
    14793 assert(0 <= contv && contv < ncontvars);
    14794 assert(isimplint[contv]);
    14795
    14796 absval = REALABS(val);
    14797 if( !SCIPisEQ(scip, absval, 1.0) )
    14798 isimplint[contv] = FALSE;
    14799 else
    14800 {
    14801 SCIP_Real obj;
    14802
    14803 obj = SCIPvarGetObj(var);
    14804 if( obj * val >= 0.0 && lhsexists )
    14805 {
    14806 /* the variable may be blocked by the constraint's left hand side */
    14807 isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->lhs);
    14808 }
    14809 if( obj * val <= 0.0 && rhsexists )
    14810 {
    14811 /* the variable may be blocked by the constraint's left hand side */
    14812 isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->rhs);
    14813 }
    14814 }
    14815 }
    14816 }
    14817 }
    14818 }
    14819
    14820 /* check if any bounds can be tightened due to optimality */
    14821 for( v = 0; v < nvars; ++v )
    14822 {
    14823 SCIP_VAR* var;
    14824 SCIP_Real obj;
    14825 SCIP_Bool infeasible;
    14826 SCIP_Bool tightened;
    14827
    14828 assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY || SCIPvarIsImpliedIntegral(vars[v]));
    14829 assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
    14830 assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
    14831
    14832 var = vars[v];
    14833 obj = SCIPvarGetObj(var);
    14834 if( !SCIPisPositive(scip, -obj) )
    14835 {
    14836 /* making the variable as small as possible does not increase the objective:
    14837 * check if all down locks of the variables are due to linear constraints;
    14838 * if variable is cost neutral and only upper bounded non-positively or negative largest bound to make
    14839 * constraints redundant is huge, we better do nothing for numerical reasons
    14840 */
    14842 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
    14843 && !SCIPisHugeValue(scip, -redlb[v])
    14844 && redlb[v] < SCIPvarGetUbGlobal(var) )
    14845 {
    14846 SCIP_Real ub;
    14847
    14848 /* if x_v >= redlb[v], we can always round x_v down to x_v == redlb[v] without violating any constraint
    14849 * -> tighten upper bound to x_v <= redlb[v]
    14850 */
    14851 SCIPdebugMsg(scip, "variable <%s> only locked down in linear constraints: dual presolve <%s>[%.15g,%.15g] <= %.15g\n",
    14853 redlb[v]);
    14854 SCIP_CALL( SCIPtightenVarUb(scip, var, redlb[v], FALSE, &infeasible, &tightened) );
    14855 assert(!infeasible);
    14856
    14857 ub = SCIPvarGetUbGlobal(var);
    14858 redub[v] = MIN(redub[v], ub);
    14859 if( tightened )
    14860 (*nchgbds)++;
    14861 }
    14862 }
    14863 if( !SCIPisPositive(scip, obj) )
    14864 {
    14865 /* making the variable as large as possible does not increase the objective:
    14866 * check if all up locks of the variables are due to linear constraints;
    14867 * if variable is cost neutral and only lower bounded non-negatively or positive smallest bound to make
    14868 * constraints redundant is huge, we better do nothing for numerical reasons
    14869 */
    14871 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v]
    14872 && !SCIPisHugeValue(scip, redub[v])
    14873 && redub[v] > SCIPvarGetLbGlobal(var) )
    14874 {
    14875 SCIP_Real lb;
    14876
    14877 /* if x_v <= redub[v], we can always round x_v up to x_v == redub[v] without violating any constraint
    14878 * -> tighten lower bound to x_v >= redub[v]
    14879 */
    14880 SCIPdebugMsg(scip, "variable <%s> only locked up in linear constraints: dual presolve <%s>[%.15g,%.15g] >= %.15g\n",
    14882 redub[v]);
    14883 SCIP_CALL( SCIPtightenVarLb(scip, var, redub[v], FALSE, &infeasible, &tightened) );
    14884 assert(!infeasible);
    14885
    14886 lb = SCIPvarGetLbGlobal(var);
    14887 redlb[v] = MAX(redlb[v], lb);
    14888 if( tightened )
    14889 (*nchgbds)++;
    14890 }
    14891 }
    14892 }
    14893
    14894 /* @TODO: improve range names */
    14895 /* declare continuous variables implied integral */
    14896 for( v = nintvars - nbinvars; v < nvars; ++v )
    14897 {
    14898 SCIP_VAR* var;
    14899 SCIP_Bool infeasible;
    14900
    14901 var = vars[v];
    14902 assert(var != NULL);
    14903
    14904 assert(!SCIPvarIsIntegral(var));
    14905 assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
    14906 assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
    14907 assert(0 <= v - nintvars + nbinvars && v - nintvars + nbinvars < ncontvars);
    14908
    14909 /* @TODO: relax lock conditions */
    14910 /* we can only conclude implied integrality if the variable appears in no other constraint */
    14911 if( isimplint[v - nintvars + nbinvars]
    14912 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
    14913 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v] )
    14914 {
    14915 /* since we locally copied the variable array we can change the variable type immediately */
    14916 assert(!SCIPvarIsIntegral(var));
    14918 (*nchgvartypes)++;
    14919 if( infeasible )
    14920 {
    14921 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
    14922 *cutoff = TRUE;
    14923
    14924 break;
    14925 }
    14926
    14927 SCIPdebugMsg(scip, "dual presolve: declare continuous variable <%s>[%g,%g] implied integral\n",
    14929 }
    14930 }
    14931
    14932 /* free temporary memory */
    14933 SCIPfreeBufferArray(scip, &conscontvars);
    14934 SCIPfreeBufferArray(scip, &isimplint);
    14935 SCIPfreeBufferArray(scip, &nlocksup);
    14936 SCIPfreeBufferArray(scip, &nlocksdown);
    14937 SCIPfreeBufferArray(scip, &redub);
    14938 SCIPfreeBufferArray(scip, &redlb);
    14939
    14940 SCIPfreeBufferArray(scip, &vars);
    14941
    14942 return SCIP_OKAY;
    14943}
    14944
    14945/** helper function to enforce constraints */
    14946static
    14948 SCIP* scip, /**< SCIP data structure */
    14949 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
    14950 SCIP_CONS** conss, /**< constraints to process */
    14951 int nconss, /**< number of constraints */
    14952 int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
    14953 SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
    14954 SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
    14955 )
    14956{
    14957 SCIP_CONSHDLRDATA* conshdlrdata;
    14958 SCIP_Bool checkrelmaxabs;
    14959 SCIP_Bool violated;
    14960 SCIP_Bool cutoff = FALSE;
    14961 int c;
    14962
    14963 assert(scip != NULL);
    14964 assert(conshdlr != NULL);
    14965 assert(result != NULL);
    14966
    14968
    14969 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    14970 assert(conshdlrdata != NULL);
    14971
    14972 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
    14973
    14974 SCIPdebugMsg(scip, "Enforcement method of linear constraints for %s solution\n", sol == NULL ? "LP" : "relaxation");
    14975
    14976 /* check for violated constraints
    14977 * LP is processed at current node -> we can add violated linear constraints to the SCIP_LP
    14978 */
    14979 *result = SCIP_FEASIBLE;
    14980
    14981 /* check all useful linear constraints for feasibility */
    14982 for( c = 0; c < nusefulconss; ++c )
    14983 {
    14984 SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
    14985
    14986 if( violated )
    14987 {
    14988 /* insert LP row as cut */
    14989 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
    14990 if ( cutoff )
    14991 *result = SCIP_CUTOFF;
    14992 else
    14993 *result = SCIP_SEPARATED;
    14994 }
    14995 }
    14996
    14997 /* check all obsolete linear constraints for feasibility */
    14998 for( c = nusefulconss; c < nconss && *result == SCIP_FEASIBLE; ++c )
    14999 {
    15000 SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
    15001
    15002 if( violated )
    15003 {
    15004 /* insert LP row as cut */
    15005 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
    15006 if ( cutoff )
    15007 *result = SCIP_CUTOFF;
    15008 else
    15009 *result = SCIP_SEPARATED;
    15010 }
    15011 }
    15012
    15013 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
    15014
    15015 return SCIP_OKAY;
    15016}
    15017
    15018/** adds symmetry information of constraint to a symmetry detection graph */
    15019static
    15021 SCIP* scip, /**< SCIP pointer */
    15022 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
    15023 SCIP_CONS* cons, /**< constraint */
    15024 SYM_GRAPH* graph, /**< symmetry detection graph */
    15025 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
    15026 )
    15027{
    15028 SCIP_CONSDATA* consdata;
    15029 SCIP_VAR** vars;
    15030 SCIP_Real* vals;
    15031 SCIP_Real constant = 0.0;
    15032 SCIP_Real lhs;
    15033 SCIP_Real rhs;
    15034 int nlocvars;
    15035 int nvars;
    15036 int i;
    15037
    15038 assert(scip != NULL);
    15039 assert(cons != NULL);
    15040 assert(graph != NULL);
    15041 assert(success != NULL);
    15042
    15043 consdata = SCIPconsGetData(cons);
    15044 assert(consdata != NULL);
    15045
    15046 /* get active variables of the constraint */
    15047 nvars = SCIPgetNVars(scip);
    15048 nlocvars = consdata->nvars;
    15049
    15050 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
    15051 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );
    15052
    15053 for( i = 0; i < nlocvars; ++i )
    15054 {
    15055 vars[i] = consdata->vars[i];
    15056 vals[i] = consdata->vals[i];
    15057 }
    15058
    15059 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
    15060 lhs = consdata->lhs - constant;
    15061 rhs = consdata->rhs - constant;
    15062
    15063 /* if rhs is infinite, normalize rhs to be finite to make sure that different encodings
    15064 * of the same constraint are rated as equal
    15065 */
    15066 if ( SCIPisInfinity(scip, rhs) )
    15067 {
    15068 SCIP_Real tmp;
    15069 assert(!SCIPisInfinity(scip, -lhs));
    15070
    15071 for( i = 0; i < nlocvars; ++i )
    15072 vals[i] *= -1;
    15073 tmp = rhs;
    15074 rhs = -lhs;
    15075 lhs = -tmp;
    15076 }
    15077
    15078 SCIP_CALL( SCIPextendPermsymDetectionGraphLinear(scip, graph, vars, vals, nlocvars,
    15079 cons, lhs, rhs, success) );
    15080
    15081 SCIPfreeBufferArray(scip, &vals);
    15082 SCIPfreeBufferArray(scip, &vars);
    15083
    15084 return SCIP_OKAY;
    15085}
    15086
    15087/*
    15088 * Callback methods of constraint handler
    15089 */
    15090
    15091/** copy method for constraint handler plugins (called when SCIP copies plugins) */
    15092static
    15093SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
    15094{ /*lint --e{715}*/
    15095 assert(scip != NULL);
    15096 assert(conshdlr != NULL);
    15097
    15099
    15100 /* call inclusion method of constraint handler */
    15102
    15103 *valid = TRUE;
    15104
    15105 return SCIP_OKAY;
    15106}
    15107
    15108/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
    15109static
    15110SCIP_DECL_CONSFREE(consFreeLinear)
    15111{ /*lint --e{715}*/
    15112 SCIP_CONSHDLRDATA* conshdlrdata;
    15113
    15114 assert(scip != NULL);
    15115 assert(conshdlr != NULL);
    15116
    15118
    15119 /* free constraint handler data */
    15120 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    15121 assert(conshdlrdata != NULL);
    15122
    15123 conshdlrdataFree(scip, &conshdlrdata);
    15124
    15125 SCIPconshdlrSetData(conshdlr, NULL);
    15126
    15127 return SCIP_OKAY;
    15128}
    15129
    15130
    15131/** initialization method of constraint handler (called after problem was transformed) */
    15132static
    15133SCIP_DECL_CONSINIT(consInitLinear)
    15134{
    15135 SCIP_CONSHDLRDATA* conshdlrdata;
    15136 int c;
    15137
    15138 assert(scip != NULL);
    15139
    15140 /* check for event handler */
    15141 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    15142 assert(conshdlrdata != NULL);
    15143 assert(conshdlrdata->eventhdlr != NULL);
    15144 assert(nconss == 0 || conss != NULL);
    15145
    15146 conshdlrdata->naddconss = 0;
    15147
    15148 /* catch events for the constraints */
    15149 for( c = 0; c < nconss; ++c )
    15150 {
    15151 /* catch all events */
    15152 SCIP_CALL( consCatchAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
    15153 }
    15154
    15155 return SCIP_OKAY;
    15156}
    15157
    15158
    15159/** deinitialization method of constraint handler (called before transformed problem is freed) */
    15160static
    15161SCIP_DECL_CONSEXIT(consExitLinear)
    15162{
    15163 SCIP_CONSHDLRDATA* conshdlrdata;
    15164 int c;
    15165
    15166 assert(scip != NULL);
    15167
    15168 /* check for event handler */
    15169 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    15170 assert(conshdlrdata != NULL);
    15171 assert(conshdlrdata->eventhdlr != NULL);
    15172
    15173 /* drop events for the constraints */
    15174 for( c = nconss - 1; c >= 0; --c )
    15175 {
    15176 SCIP_CONSDATA* consdata;
    15177
    15178 consdata = SCIPconsGetData(conss[c]);
    15179 assert(consdata != NULL);
    15180
    15181 if( consdata->eventdata != NULL )
    15182 {
    15183 /* drop all events */
    15184 SCIP_CALL( consDropAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
    15185 assert(consdata->eventdata == NULL);
    15186 }
    15187 }
    15188
    15189 return SCIP_OKAY;
    15190}
    15191
    15192/** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
    15193static
    15195 SCIP* scip, /**< SCIP data structure */
    15196 SCIP_Real lhs, /**< left hand side */
    15197 SCIP_Real rhs /**< right hand side */
    15198 )
    15199{
    15200 assert(scip != NULL);
    15201
    15202 return !(SCIPisEQ(scip, lhs, rhs) || SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs) );
    15203}
    15204
    15205/** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
    15206static
    15208 SCIP* scip, /**< SCIP data structure */
    15209 SCIP_Real x /**< value */
    15210 )
    15211{
    15212 assert(scip != NULL);
    15213
    15214 return (!SCIPisInfinity(scip, x) && !SCIPisNegative(scip, x) && SCIPisIntegral(scip, x));
    15215}
    15216
    15217/** performs linear constraint type classification as used for MIPLIB
    15218 *
    15219 * iterates through all linear constraints and stores relevant statistics in the linear constraint statistics \p linconsstats.
    15220 *
    15221 * @note only constraints are iterated that belong to the linear constraint handler. If the problem has been presolved already,
    15222 * constraints that were upgraded to more special types such as, e.g., varbound constraints, will not be shown correctly anymore.
    15223 * Similarly, if specialized constraints were created through the API, these are currently not present.
    15224 */
    15226 SCIP* scip, /**< SCIP data structure */
    15227 SCIP_LINCONSSTATS* linconsstats /**< linear constraint type classification */
    15228 )
    15229{
    15230 int c;
    15231 SCIP_CONSHDLR* conshdlr;
    15232 SCIP_CONS** conss;
    15233 int nconss;
    15234
    15235 assert(scip != NULL);
    15236 assert(linconsstats != NULL);
    15237 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
    15238 assert(conshdlr != NULL);
    15239
    15241 {
    15242 conss = SCIPgetConss(scip);
    15243 nconss = SCIPgetNConss(scip);
    15244 }
    15245 else
    15246 {
    15247 conss = SCIPconshdlrGetConss(conshdlr);
    15248 nconss = SCIPconshdlrGetNConss(conshdlr);
    15249 }
    15250
    15251 /* reset linear constraint type classification */
    15252 SCIPlinConsStatsReset(linconsstats);
    15253
    15254 /* loop through all constraints */
    15255 for( c = 0; c < nconss; c++ )
    15256 {
    15257 SCIP_CONS* cons;
    15258 SCIP_CONSDATA* consdata;
    15259 SCIP_Real lhs;
    15260 SCIP_Real rhs;
    15261 int i;
    15262
    15263 /* get constraint */
    15264 cons = conss[c];
    15265 assert(cons != NULL);
    15266
    15267 /* skip constraints that are not handled by the constraint handler */
    15268 if( SCIPconsGetHdlr(cons) != conshdlr )
    15269 continue;
    15270
    15271 /* get constraint data */
    15272 consdata = SCIPconsGetData(cons);
    15273 assert(consdata != NULL);
    15274 rhs = consdata->rhs;
    15275 lhs = consdata->lhs;
    15276
    15277 /* merge multiples and delete variables with zero coefficient */
    15278 SCIP_CALL( mergeMultiples(scip, cons) );
    15279 for( i = 0; i < consdata->nvars; i++ )
    15280 {
    15281 assert(!SCIPisZero(scip, consdata->vals[i]));
    15282 }
    15283
    15284 /* is constraint of type SCIP_CONSTYPE_EMPTY? */
    15285 if( consdata->nvars == 0 )
    15286 {
    15287 SCIPdebugMsg(scip, "classified as EMPTY: ");
    15290
    15291 continue;
    15292 }
    15293
    15294 /* is constraint of type SCIP_CONSTYPE_FREE? */
    15295 if( SCIPisInfinity(scip, rhs) && SCIPisInfinity(scip, -lhs) )
    15296 {
    15297 SCIPdebugMsg(scip, "classified as FREE: ");
    15300
    15301 continue;
    15302 }
    15303
    15304 /* is constraint of type SCIP_CONSTYPE_SINGLETON? */
    15305 if( consdata->nvars == 1 )
    15306 {
    15307 SCIPdebugMsg(scip, "classified as SINGLETON: ");
    15310
    15311 continue;
    15312 }
    15313
    15314 /* is constraint of type SCIP_CONSTYPE_AGGREGATION? */
    15315 if( consdata->nvars == 2 && SCIPisEQ(scip, lhs, rhs) )
    15316 {
    15317 SCIPdebugMsg(scip, "classified as AGGREGATION: ");
    15320
    15321 continue;
    15322 }
    15323
    15324 /* is constraint of type SCIP_CONSTYPE_{VARBOUND,PRECEDENCE}? */
    15325 if( consdata->nvars == 2 )
    15326 {
    15327 /* precedence constraints have same variable type and same absolute coefficient with opposite sign */
    15328 if( SCIPvarGetType(consdata->vars[0]) == SCIPvarGetType(consdata->vars[1])
    15329 && SCIPisEQ(scip, consdata->vals[0], -consdata->vals[1]) )
    15330 {
    15331 SCIPdebugMsg(scip, "classified as PRECEDENCE: ");
    15334
    15335 continue;
    15336 }
    15337 /* varbound constraints have otherwise a binary variable */
    15338 else if( SCIPvarGetType(consdata->vars[0]) == SCIP_VARTYPE_BINARY
    15339 || SCIPvarGetType(consdata->vars[1]) == SCIP_VARTYPE_BINARY )
    15340 {
    15341 SCIPdebugMsg(scip, "classified as VARBOUND: ");
    15344
    15345 continue;
    15346 }
    15347 }
    15348
    15349 /* is constraint of type SCIP_CONSTYPE_{SETPARTITION, SETPACKING, SETCOVERING, CARDINALITY, INVKNAPSACK}? */
    15350 {
    15351 SCIP_Real scale;
    15352 SCIP_Real b;
    15353 SCIP_Bool unmatched;
    15354 int nnegbinvars;
    15355
    15356 unmatched = FALSE;
    15357 nnegbinvars = 0;
    15358
    15359 scale = REALABS(consdata->vals[0]);
    15360
    15361 /* scan through variables and detect if all variables are binary and have a coefficient +/-1 */
    15362 for( i = 0; i < consdata->nvars && !unmatched; i++ )
    15363 {
    15364 unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
    15365 unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
    15366 unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
    15367 unmatched = unmatched || !SCIPisEQ(scip, REALABS(consdata->vals[i]), scale);
    15368
    15369 if( consdata->vals[i] < 0.0 )
    15370 nnegbinvars++;
    15371 }
    15372
    15373 if( !unmatched )
    15374 {
    15375 if( SCIPisEQ(scip, lhs, rhs) )
    15376 {
    15377 b = rhs/scale + nnegbinvars;
    15378 if( SCIPisEQ(scip, 1.0, b) )
    15379 {
    15380 SCIPdebugMsg(scip, "classified as SETPARTITION: ");
    15383
    15384 continue;
    15385 }
    15386 else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
    15387 {
    15388 SCIPdebugMsg(scip, "classified as CARDINALITY: ");
    15391
    15392 continue;
    15393 }
    15394 }
    15395
    15396 /* compute right hand side divided by scale */
    15397 if( !SCIPisInfinity(scip, rhs) )
    15398 b = rhs/scale + nnegbinvars;
    15399 else
    15400 b = SCIPinfinity(scip);
    15401
    15402 if( SCIPisEQ(scip, 1.0, b) )
    15403 {
    15404 SCIPdebugMsg(scip, "classified as SETPACKING: ");
    15407
    15408 /* relax right hand side to prevent further classifications */
    15409 rhs = SCIPinfinity(scip);
    15410 }
    15411 else if( !SCIPisInfinity(scip, b) && SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
    15412 {
    15413 SCIPdebugMsg(scip, "classified as INVKNAPSACK: ");
    15415
    15417
    15418 /* relax right hand side to prevent further classifications */
    15419 rhs = SCIPinfinity(scip);
    15420 }
    15421
    15422 if( !SCIPisInfinity(scip, lhs) )
    15423 b = lhs/scale + nnegbinvars;
    15424 else
    15425 b = SCIPinfinity(scip);
    15426
    15427 if( SCIPisEQ(scip, 1.0, b) )
    15428 {
    15429 SCIPdebugMsg(scip, "classified as SETCOVERING: ");
    15432
    15433 /* relax left hand side to prevent further classifications */
    15434 lhs = -SCIPinfinity(scip);
    15435 }
    15436
    15437 /* if both sides are infinite at this point, no further classification is necessary for this constraint */
    15438 if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
    15439 continue;
    15440 }
    15441 }
    15442
    15443 /* is constraint of type SCIP_CONSTYPE_{EQKNAPSACK, BINPACKING, KNAPSACK}? */
    15444 /* @todo If coefficients or rhs are not integral, we currently do not check
    15445 * if the constraint could be scaled (finitely), such that they are.
    15446 */
    15447 {
    15448 SCIP_Real b;
    15449 SCIP_Bool unmatched;
    15450
    15451 b = rhs;
    15452 unmatched = FALSE;
    15453 for( i = 0; i < consdata->nvars && !unmatched; i++ )
    15454 {
    15455 unmatched = unmatched || !SCIPvarIsIntegral(consdata->vars[i]);
    15456 unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
    15457 unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
    15458 unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
    15459
    15460 if( SCIPisNegative(scip, consdata->vals[i]) )
    15461 b -= consdata->vals[i];
    15462 }
    15463 unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
    15464
    15465 if( !unmatched )
    15466 {
    15467 if( SCIPisEQ(scip, lhs, rhs) )
    15468 {
    15469 SCIPdebugMsg(scip, "classified as EQKNAPSACK: ");
    15471
    15473
    15474 continue;
    15475 }
    15476 else
    15477 {
    15478 SCIP_Bool matched;
    15479
    15480 matched = FALSE;
    15481 for( i = 0; i < consdata->nvars && !matched; i++ )
    15482 {
    15483 matched = matched || SCIPisEQ(scip, b, REALABS(consdata->vals[i]));
    15484 }
    15485
    15486 SCIPdebugMsg(scip, "classified as %s: ", matched ? "BINPACKING" : "KNAPSACK");
    15489 }
    15490
    15491 /* check if finite left hand side allows for a second classification, relax already used right hand side */
    15492 if( SCIPisInfinity(scip, -lhs) )
    15493 continue;
    15494 else
    15495 rhs = SCIPinfinity(scip);
    15496 }
    15497 }
    15498
    15499 /* is constraint of type SCIP_CONSTYPE_{INTKNAPSACK}? */
    15500 {
    15501 SCIP_Real b;
    15502 SCIP_Bool unmatched;
    15503
    15504 unmatched = FALSE;
    15505
    15506 b = rhs;
    15507 unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
    15508
    15509 for( i = 0; i < consdata->nvars && !unmatched; i++ )
    15510 {
    15511 unmatched = unmatched || !SCIPvarIsIntegral(consdata->vars[i]);
    15512 unmatched = unmatched || SCIPisNegative(scip, SCIPvarGetLbGlobal(consdata->vars[i]));
    15513 unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
    15514 unmatched = unmatched || SCIPisNegative(scip, consdata->vals[i]);
    15515 }
    15516
    15517 if( !unmatched )
    15518 {
    15519 SCIPdebugMsg(scip, "classified as INTKNAPSACK: ");
    15522
    15523 /* check if finite left hand side allows for a second classification, relax already used right hand side */
    15524 if( SCIPisInfinity(scip, -lhs) )
    15525 continue;
    15526 else
    15527 rhs = SCIPinfinity(scip);
    15528 }
    15529 }
    15530
    15531 /* is constraint of type SCIP_CONSTYPE_{MIXEDBINARY}? */
    15532 {
    15533 SCIP_Bool unmatched;
    15534
    15535 unmatched = FALSE;
    15536 for( i = 0; i < consdata->nvars && !unmatched; i++ )
    15537 {
    15538 if( SCIPvarIsIntegral(consdata->vars[i])
    15539 && ( SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0)
    15540 || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0) ) )
    15541 unmatched = TRUE;
    15542 }
    15543
    15544 if( !unmatched )
    15545 {
    15546 SCIPdebugMsg(scip, "classified as MIXEDBINARY (%d): ", isRangedRow(scip, lhs, rhs) ? 2 : 1);
    15549
    15550 continue;
    15551 }
    15552 }
    15553
    15554 /* no special structure detected */
    15555 SCIPdebugMsg(scip, "classified as GENERAL: ");
    15557 SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_GENERAL, isRangedRow(scip, lhs, rhs) ? 2 : 1);
    15558 }
    15559
    15560 return SCIP_OKAY;
    15561}
    15562
    15563
    15564/** presolving deinitialization method of constraint handler (called after presolving has been finished) */
    15565static
    15566SCIP_DECL_CONSEXITPRE(consExitpreLinear)
    15567{ /*lint --e{715}*/
    15568 int c;
    15569#ifdef SCIP_STATISTIC
    15570 SCIP_CONSHDLRDATA* conshdlrdata;
    15571 int ngoodconss;
    15572 int nallconss;
    15573#endif
    15574
    15575 /* delete all linear constraints that were upgraded to a more specific constraint type;
    15576 * make sure, only active variables remain in the remaining constraints
    15577 */
    15578 assert(scip != NULL);
    15579
    15580#ifdef SCIP_STATISTIC
    15581 /* count number of well behaved linear constraints */
    15582 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    15583 assert(conshdlrdata != NULL);
    15584
    15585 ngoodconss = 0;
    15586 nallconss = 0;
    15587
    15588 for( c = 0; c < nconss; ++c )
    15589 {
    15590 SCIP_CONSDATA* consdata;
    15591
    15592 if( SCIPconsIsDeleted(conss[c]) )
    15593 continue;
    15594
    15595 consdata = SCIPconsGetData(conss[c]);
    15596 assert(consdata != NULL);
    15597
    15598 if( consdata->upgraded )
    15599 continue;
    15600
    15601 nallconss++;
    15602
    15604
    15605 if( SCIPisLT(scip, consdata->maxactdelta, conshdlrdata->maxeasyactivitydelta) )
    15606 ngoodconss++;
    15607 }
    15608 if( nallconss )
    15609 {
    15610 SCIPstatisticMessage("below threshold: %d / %d ratio= %g\n", ngoodconss, nallconss, (100.0 * ngoodconss / nallconss));
    15611 }
    15612#endif
    15613
    15614 for( c = 0; c < nconss; ++c )
    15615 {
    15616 SCIP_CONSDATA* consdata;
    15617
    15618 if( SCIPconsIsDeleted(conss[c]) )
    15619 continue;
    15620
    15621 consdata = SCIPconsGetData(conss[c]);
    15622 assert(consdata != NULL);
    15623
    15624 if( consdata->upgraded )
    15625 {
    15626 /* this is no problem reduction, because the upgraded constraint was added to the problem before, and the
    15627 * (redundant) linear constraint was only kept in order to support presolving the the linear constraint handler
    15628 */
    15629 SCIP_CALL( SCIPdelCons(scip, conss[c]) );
    15630 }
    15631 else
    15632 {
    15633 /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */
    15634 SCIP_CALL( applyFixings(scip, conss[c], NULL) );
    15635 }
    15636 }
    15637
    15638 return SCIP_OKAY;
    15639}
    15640
    15641/** solving process initialization method of constraint handler */
    15642static
    15643SCIP_DECL_CONSINITSOL(consInitsolLinear)
    15644{ /*lint --e{715}*/
    15645 /* add nlrow representation to NLP, if NLP had been constructed */
    15647 {
    15648 int c;
    15649 for( c = 0; c < nconss; ++c )
    15650 {
    15651 SCIP_CALL( addNlrow(scip, conss[c]) );
    15652 }
    15653 }
    15654
    15655 return SCIP_OKAY;
    15656}
    15657
    15658/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
    15659static
    15660SCIP_DECL_CONSEXITSOL(consExitsolLinear)
    15661{ /*lint --e{715}*/
    15662 int c;
    15663
    15664 assert(scip != NULL);
    15665
    15666 /* release the rows and nlrows of all constraints */
    15667 for( c = 0; c < nconss; ++c )
    15668 {
    15669 SCIP_CONSDATA* consdata;
    15670
    15671 consdata = SCIPconsGetData(conss[c]);
    15672 assert(consdata != NULL);
    15673
    15674 if( consdata->row != NULL )
    15675 {
    15676 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
    15677 }
    15678
    15679 if( consdata->nlrow != NULL )
    15680 {
    15681 SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
    15682 }
    15683 }
    15684
    15685 /* if this is a restart, convert cutpool rows into linear constraints */
    15686 if( restart )
    15687 {
    15688 int ncutsadded;
    15689
    15690 ncutsadded = 0;
    15691
    15692 /* create out of all active cuts in cutpool linear constraints */
    15693 SCIP_CALL( SCIPconvertCutsToConss(scip, NULL, NULL, TRUE, &ncutsadded) );
    15694
    15695 if( ncutsadded > 0 )
    15696 {
    15698 "(restart) converted %d cuts from the global cut pool into linear constraints\n", ncutsadded);
    15699 /* an extra blank line should be printed separately since the buffer message handler only handles up to one
    15700 * line correctly
    15701 */
    15703 }
    15704 }
    15705
    15706 return SCIP_OKAY;
    15707}
    15708
    15709
    15710/** constraint activation notification method of constraint handler */
    15711static
    15712SCIP_DECL_CONSACTIVE(consActiveLinear)
    15713{ /*lint --e{715}*/
    15714 assert(cons != NULL);
    15715
    15717 {
    15718 SCIP_CALL( addNlrow(scip, cons) );
    15719 }
    15720
    15721 return SCIP_OKAY;
    15722}
    15723
    15724/** constraint deactivation notification method of constraint handler */
    15725static
    15726SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
    15727{ /*lint --e{715}*/
    15728 SCIP_CONSDATA* consdata;
    15729
    15730 assert(scip != NULL);
    15731 assert(conshdlr != NULL);
    15732 assert(cons != NULL );
    15733
    15735
    15736 /* get constraint data */
    15737 consdata = SCIPconsGetData(cons);
    15738 assert(consdata != NULL);
    15739
    15740 if( SCIPconsIsDeleted(cons) )
    15741 {
    15742 SCIP_CONSHDLRDATA* conshdlrdata;
    15743
    15744 /* check for event handler */
    15745 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    15746 assert(conshdlrdata != NULL);
    15747 assert(conshdlrdata->eventhdlr != NULL);
    15748
    15749 /* free event data */
    15750 if( consdata->eventdata != NULL )
    15751 {
    15752 /* drop bound change events of variables */
    15753 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
    15754 }
    15755 assert(consdata->eventdata == NULL);
    15756 }
    15757
    15758 /* remove row from NLP, if still in solving
    15759 * if we are in exitsolve, the whole NLP will be freed anyway
    15760 */
    15761 if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
    15762 {
    15763 SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
    15764 }
    15765
    15766 return SCIP_OKAY;
    15767}
    15768
    15769
    15770/** frees specific constraint data */
    15771static
    15772SCIP_DECL_CONSDELETE(consDeleteLinear)
    15773{ /*lint --e{715}*/
    15774 assert(scip != NULL);
    15775 assert(conshdlr != NULL);
    15776
    15778
    15779 if( (*consdata)->eventdata != NULL )
    15780 {
    15781 SCIP_CONSHDLRDATA* conshdlrdata;
    15782
    15783 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    15784 assert(conshdlrdata != NULL);
    15785
    15786 /* drop all events */
    15787 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
    15788 assert((*consdata)->eventdata == NULL);
    15789 }
    15790
    15791 /* free linear constraint */
    15792 SCIP_CALL( consdataFree(scip, consdata) );
    15793
    15794 return SCIP_OKAY;
    15795}
    15796
    15797
    15798/** transforms constraint data into data belonging to the transformed problem */
    15799static
    15800SCIP_DECL_CONSTRANS(consTransLinear)
    15801{ /*lint --e{715}*/
    15802 SCIP_CONSDATA* sourcedata;
    15803 SCIP_CONSDATA* targetdata;
    15804
    15805 /*debugMsg(scip, "Trans method of linear constraints\n");*/
    15806
    15807 assert(scip != NULL);
    15808 assert(conshdlr != NULL);
    15810 assert(sourcecons != NULL);
    15811 assert(targetcons != NULL);
    15812
    15814
    15815 sourcedata = SCIPconsGetData(sourcecons);
    15816 assert(sourcedata != NULL);
    15817 assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
    15818
    15819 /* create linear constraint data for target constraint */
    15820 SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars, sourcedata->vals, sourcedata->lhs,
    15821 sourcedata->rhs) );
    15822
    15823#ifndef NDEBUG
    15824 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
    15825 if( SCIPconsIsEnforced(sourcecons) || SCIPconsIsChecked(sourcecons) )
    15826 {
    15827 int n;
    15828 for(n = targetdata->nvars - 1; n >= 0; --n )
    15829 assert(!SCIPvarIsRelaxationOnly(targetdata->vars[n]));
    15830 }
    15831#endif
    15832
    15833 /* create target constraint */
    15834 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
    15835 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
    15836 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
    15837 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
    15838 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
    15839
    15840 return SCIP_OKAY;
    15841}
    15842
    15843
    15844/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
    15845static
    15846SCIP_DECL_CONSINITLP(consInitlpLinear)
    15847{ /*lint --e{715}*/
    15848 int c;
    15849
    15850 assert(scip != NULL);
    15851
    15853
    15854 *infeasible = FALSE;
    15855
    15856 for( c = 0; c < nconss && !(*infeasible); ++c )
    15857 {
    15858 assert(SCIPconsIsInitial(conss[c]));
    15859 SCIP_CALL( addRelaxation(scip, conss[c], infeasible) );
    15860 }
    15861
    15862 return SCIP_OKAY;
    15863}
    15864
    15865
    15866/** separation method of constraint handler for LP solutions */
    15867static
    15868SCIP_DECL_CONSSEPALP(consSepalpLinear)
    15869{ /*lint --e{715}*/
    15870 SCIP_CONSHDLRDATA* conshdlrdata;
    15871 SCIP_Real loclowerbound;
    15872 SCIP_Real glblowerbound;
    15873 SCIP_Real cutoffbound;
    15874 SCIP_Real maxbound;
    15875 SCIP_Bool separatecards;
    15876 SCIP_Bool cutoff;
    15877 int c;
    15878 int depth;
    15879 int nrounds;
    15880 int maxsepacuts;
    15881 int ncuts;
    15882
    15883 assert(scip != NULL);
    15884 assert(conshdlr != NULL);
    15885 assert(result != NULL);
    15886
    15888
    15889 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    15890 assert(conshdlrdata != NULL);
    15891 depth = SCIPgetDepth(scip);
    15892 nrounds = SCIPgetNSepaRounds(scip);
    15893
    15894 /*debugMsg(scip, "Sepa method of linear constraints\n");*/
    15895
    15896 *result = SCIP_DIDNOTRUN;
    15897
    15898 /* only call the separator a given number of times at each node */
    15899 if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
    15900 || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
    15901 return SCIP_OKAY;
    15902
    15903 /* get the maximal number of cuts allowed in a separation round */
    15904 maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
    15905
    15906 /* check if we want to produce knapsack cardinality cuts at this node */
    15907 loclowerbound = SCIPgetLocalLowerbound(scip);
    15908 glblowerbound = SCIPgetLowerbound(scip);
    15909 cutoffbound = SCIPgetCutoffbound(scip);
    15910 maxbound = glblowerbound + conshdlrdata->maxcardbounddist * (cutoffbound - glblowerbound);
    15911 separatecards = SCIPisLE(scip, loclowerbound, maxbound);
    15912 separatecards = separatecards && (SCIPgetNLPBranchCands(scip) > 0);
    15913
    15914 *result = SCIP_DIDNOTFIND;
    15915 ncuts = 0;
    15916 cutoff = FALSE;
    15917
    15918 /* check all useful linear constraints for feasibility */
    15919 for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
    15920 {
    15921 /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
    15922 SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, NULL, separatecards, conshdlrdata->separateall, &ncuts, &cutoff) );
    15923 }
    15924
    15925 /* adjust return value */
    15926 if( cutoff )
    15927 *result = SCIP_CUTOFF;
    15928 else if( ncuts > 0 )
    15929 *result = SCIP_SEPARATED;
    15930
    15931 /* combine linear constraints to get more cuts */
    15932 /**@todo further cuts of linear constraints */
    15933
    15934 return SCIP_OKAY;
    15935}
    15936
    15937
    15938/** separation method of constraint handler for arbitrary primal solutions */
    15939static
    15940SCIP_DECL_CONSSEPASOL(consSepasolLinear)
    15941{ /*lint --e{715}*/
    15942 SCIP_CONSHDLRDATA* conshdlrdata;
    15943 int c;
    15944 int depth;
    15945 int nrounds;
    15946 int maxsepacuts;
    15947 int ncuts;
    15948 SCIP_Bool cutoff;
    15949
    15950 assert(scip != NULL);
    15951 assert(conshdlr != NULL);
    15952 assert(result != NULL);
    15953
    15955
    15956 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    15957 assert(conshdlrdata != NULL);
    15958 depth = SCIPgetDepth(scip);
    15959 nrounds = SCIPgetNSepaRounds(scip);
    15960
    15961 /*debugMsg(scip, "Sepa method of linear constraints\n");*/
    15962
    15963 *result = SCIP_DIDNOTRUN;
    15964
    15965 /* only call the separator a given number of times at each node */
    15966 if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
    15967 || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
    15968 return SCIP_OKAY;
    15969
    15970 /* get the maximal number of cuts allowed in a separation round */
    15971 maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
    15972
    15973 *result = SCIP_DIDNOTFIND;
    15974 ncuts = 0;
    15975 cutoff = FALSE;
    15976
    15977 /* check all useful linear constraints for feasibility */
    15978 for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
    15979 {
    15980 /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
    15981 SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, sol, TRUE, conshdlrdata->separateall, &ncuts, &cutoff) );
    15982 }
    15983
    15984 /* adjust return value */
    15985 if( cutoff )
    15986 *result = SCIP_CUTOFF;
    15987 else if( ncuts > 0 )
    15988 *result = SCIP_SEPARATED;
    15989
    15990 /* combine linear constraints to get more cuts */
    15991 /**@todo further cuts of linear constraints */
    15992
    15993 return SCIP_OKAY;
    15994}
    15995
    15996
    15997/** constraint enforcing method of constraint handler for LP solutions */
    15998static
    15999SCIP_DECL_CONSENFOLP(consEnfolpLinear)
    16000{ /*lint --e{715}*/
    16001 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
    16002
    16003 return SCIP_OKAY;
    16004}
    16005
    16006/** constraint enforcing method of constraint handler for relaxation solutions */
    16007static
    16008SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
    16009{ /*lint --e{715}*/
    16010 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
    16011
    16012 return SCIP_OKAY;
    16013}
    16014
    16015/** constraint enforcing method of constraint handler for pseudo solutions */
    16016static
    16017SCIP_DECL_CONSENFOPS(consEnfopsLinear)
    16018{ /*lint --e{715}*/
    16019 SCIP_CONSHDLRDATA* conshdlrdata;
    16020 SCIP_Bool checkrelmaxabs;
    16021 SCIP_Bool violated;
    16022 int c;
    16023
    16024 assert(scip != NULL);
    16025 assert(conshdlr != NULL);
    16026 assert(result != NULL);
    16027
    16029
    16030 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    16031 assert(conshdlrdata != NULL);
    16032
    16033 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
    16034
    16035 SCIPdebugMsg(scip, "Enfops method of linear constraints\n");
    16036
    16037 /* if the solution is infeasible anyway due to objective value, skip the enforcement */
    16038 if( objinfeasible )
    16039 {
    16040 SCIPdebugMsg(scip, "-> pseudo solution is objective infeasible, return.\n");
    16041
    16042 *result = SCIP_DIDNOTRUN;
    16043 return SCIP_OKAY;
    16044 }
    16045
    16046 /* check all linear constraints for feasibility */
    16047 violated = FALSE;
    16048 for( c = 0; c < nconss && !violated; ++c )
    16049 {
    16050 SCIP_CALL( checkCons(scip, conss[c], NULL, TRUE, checkrelmaxabs, &violated) );
    16051 }
    16052
    16053 if( violated )
    16054 *result = SCIP_INFEASIBLE;
    16055 else
    16056 *result = SCIP_FEASIBLE;
    16057
    16058 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
    16059
    16060 return SCIP_OKAY;
    16061}
    16062
    16063
    16064/** feasibility check method of constraint handler for integral solutions */
    16065static
    16066SCIP_DECL_CONSCHECK(consCheckLinear)
    16067{ /*lint --e{715}*/
    16068 SCIP_CONSHDLRDATA* conshdlrdata;
    16069 SCIP_Bool checkrelmaxabs;
    16070 int c;
    16071
    16072 assert(scip != NULL);
    16073 assert(conshdlr != NULL);
    16074 assert(result != NULL);
    16075
    16077
    16078 *result = SCIP_FEASIBLE;
    16079
    16080 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    16081 assert(conshdlrdata != NULL);
    16082
    16083 checkrelmaxabs = conshdlrdata->checkrelmaxabs;
    16084
    16085 /*debugMsg(scip, "Check method of linear constraints\n");*/
    16086
    16087 /* check all linear constraints for feasibility */
    16088 for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
    16089 {
    16090 SCIP_Bool violated = FALSE;
    16091 SCIP_CALL( checkCons(scip, conss[c], sol, checklprows, checkrelmaxabs, &violated) );
    16092
    16093 if( violated )
    16094 {
    16095 *result = SCIP_INFEASIBLE;
    16096
    16097 if( printreason )
    16098 {
    16099 SCIP_CONSDATA* consdata;
    16100 SCIP_Real activity;
    16101
    16102 consdata = SCIPconsGetData(conss[c]);
    16103 assert( consdata != NULL);
    16104
    16105 activity = consdataGetActivity(scip, consdata, sol);
    16106
    16107 SCIP_CALL( consPrintConsSol(scip, conss[c], sol, NULL ) );
    16108 SCIPinfoMessage(scip, NULL, ";\n");
    16109
    16110 if( activity == SCIP_INVALID || SCIPisInfinity(scip, ABS(activity)) ) /*lint !e777*/
    16111 SCIPinfoMessage(scip, NULL, "activity invalid due to infinity contributions\n");
    16112 else if( SCIPisFeasLT(scip, activity, consdata->lhs) )
    16113 SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - activity);
    16114 else if( SCIPisFeasGT(scip, activity, consdata->rhs) )
    16115 SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - consdata->rhs);
    16116 }
    16117 }
    16118 }
    16119
    16120 return SCIP_OKAY;
    16121}
    16122
    16123
    16124/** domain propagation method of constraint handler */
    16125static
    16126SCIP_DECL_CONSPROP(consPropLinear)
    16127{ /*lint --e{715}*/
    16128 SCIP_CONSHDLRDATA* conshdlrdata;
    16129 SCIP_Bool rangedrowpropagation = FALSE;
    16130 SCIP_Bool tightenbounds;
    16131 SCIP_Bool cutoff;
    16132 int naddedconss = 0;
    16133 int nchgbds = 0;
    16134 int i;
    16135
    16136 assert(scip != NULL);
    16137 assert(conshdlr != NULL);
    16138 assert(result != NULL);
    16139
    16141
    16142 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    16143 assert(conshdlrdata != NULL);
    16144
    16145 /*debugMsg(scip, "Prop method of linear constraints\n");*/
    16146
    16147 /* check, if we want to tighten variable's bounds (in probing, we always want to tighten the bounds) */
    16148 if( SCIPinProbing(scip) )
    16149 tightenbounds = TRUE;
    16150 else
    16151 {
    16152 int depth;
    16153 int propfreq;
    16154 int tightenboundsfreq;
    16155 int rangedrowfreq;
    16156
    16157 depth = SCIPgetDepth(scip);
    16158 propfreq = SCIPconshdlrGetPropFreq(conshdlr);
    16159 tightenboundsfreq = propfreq * conshdlrdata->tightenboundsfreq;
    16160 tightenbounds = (conshdlrdata->tightenboundsfreq >= 0)
    16161 && ((tightenboundsfreq == 0 && depth == 0) || (tightenboundsfreq >= 1 && (depth % tightenboundsfreq == 0)));
    16162
    16163 /* check if we want to do ranged row propagation */
    16164 rangedrowpropagation = conshdlrdata->rangedrowpropagation;
    16165 rangedrowpropagation = rangedrowpropagation && !SCIPinRepropagation(scip);
    16166 rangedrowpropagation = rangedrowpropagation && (depth <= conshdlrdata->rangedrowmaxdepth);
    16167 rangedrowfreq = propfreq * conshdlrdata->rangedrowfreq;
    16168 rangedrowpropagation = rangedrowpropagation && (conshdlrdata->rangedrowfreq >= 0)
    16169 && ((rangedrowfreq == 0 && depth == 0) || (rangedrowfreq >= 1 && (depth % rangedrowfreq == 0)));
    16170 rangedrowpropagation = rangedrowpropagation && (SCIPgetStage(scip) != SCIP_STAGE_PRESOLVING); /* ranged rows are also presolved */
    16171 }
    16172
    16173 cutoff = FALSE;
    16174
    16175 /* process constraints marked for propagation */
    16176 for( i = 0; i < nmarkedconss && !cutoff; i++ )
    16177 {
    16179 SCIP_CALL( propagateCons(scip, conss[i], tightenbounds, rangedrowpropagation,
    16180 conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, &nchgbds, &naddedconss) );
    16181 assert(naddedconss == 0 || (SCIPgetStage(scip) != SCIP_STAGE_PRESOLVING));
    16182 }
    16183
    16184 /* adjust result code */
    16185 if( cutoff )
    16186 *result = SCIP_CUTOFF;
    16187 else if( nchgbds > 0 )
    16188 *result = SCIP_REDUCEDDOM;
    16189 else if( naddedconss > 0 )
    16190 *result = SCIP_CONSADDED;
    16191 else
    16192 *result = SCIP_DIDNOTFIND;
    16193
    16194 return SCIP_OKAY;
    16195}
    16196
    16197
    16198#define MAXCONSPRESOLROUNDS 10
    16199/** presolving method of constraint handler */
    16200static
    16201SCIP_DECL_CONSPRESOL(consPresolLinear)
    16202{ /*lint --e{715}*/
    16203 SCIP_CONSHDLRDATA* conshdlrdata;
    16204 SCIP_CONS* cons;
    16205 SCIP_CONSDATA* consdata;
    16206 SCIP_Real minactivity;
    16207 SCIP_Real maxactivity;
    16208 SCIP_Bool isminacttight;
    16209 SCIP_Bool ismaxacttight;
    16210 SCIP_Bool isminsettoinfinity;
    16211 SCIP_Bool ismaxsettoinfinity;
    16212 SCIP_Bool cutoff;
    16213 int oldnfixedvars;
    16214 int oldnaggrvars;
    16215 int oldnchgbds;
    16216 int oldndelconss;
    16217 int oldnupgdconss;
    16218 int oldnchgcoefs;
    16219 int oldnchgsides;
    16220 int firstchange;
    16221 int firstupgradetry;
    16222 int c;
    16223
    16224 assert(scip != NULL);
    16225 assert(conshdlr != NULL);
    16226 assert(result != NULL);
    16227
    16229
    16230 /* remember old preprocessing counters */
    16231 cutoff = FALSE;
    16232 oldnfixedvars = *nfixedvars;
    16233 oldnaggrvars = *naggrvars;
    16234 oldnchgbds = *nchgbds;
    16235 oldndelconss = *ndelconss;
    16236 oldnupgdconss = *nupgdconss;
    16237 oldnchgcoefs = *nchgcoefs;
    16238 oldnchgsides = *nchgsides;
    16239
    16240 /*debugMsg(scip, "Presol method of linear constraints\n");*/
    16241
    16242 /* get constraint handler data */
    16243 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    16244 assert(conshdlrdata != NULL);
    16245
    16246 /* process single constraints */
    16247 firstchange = INT_MAX;
    16248 firstupgradetry = INT_MAX;
    16249 for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
    16250 {
    16251 int npresolrounds;
    16252 SCIP_Bool infeasible;
    16253
    16254 infeasible = FALSE;
    16255
    16256 cons = conss[c];
    16257 assert(SCIPconsIsActive(cons));
    16258 consdata = SCIPconsGetData(cons);
    16259 assert(consdata != NULL);
    16260
    16261 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
    16262 if( SCIPisEQ(scip, consdata->rhs, consdata->lhs) )
    16263 {
    16264 consdata->lhs = consdata->rhs;
    16265 assert(consdata->row == NULL);
    16266 }
    16267
    16268 if( consdata->eventdata == NULL )
    16269 {
    16270 /* catch bound change events of variables */
    16271 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
    16272 assert(consdata->eventdata != NULL);
    16273 }
    16274
    16275 /* constraint should not be already presolved in the initial round */
    16276 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || SCIPconsIsMarkedPropagate(cons));
    16277 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || consdata->boundstightened == 0);
    16278 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->presolved);
    16279 assert(!SCIPconsIsMarkedPropagate(cons) || !consdata->presolved);
    16280
    16281 /* incorporate fixings and aggregations in constraint */
    16282 SCIP_CALL( applyFixings(scip, cons, &infeasible) );
    16283
    16284 if( infeasible )
    16285 {
    16286 SCIPdebugMsg(scip, " -> infeasible fixing\n");
    16287 cutoff = TRUE;
    16288 break;
    16289 }
    16290
    16291 assert(consdata->removedfixings);
    16292
    16293 /* we can only presolve linear constraints, that are not modifiable */
    16294 if( SCIPconsIsModifiable(cons) )
    16295 continue;
    16296
    16297 /* remember the first changed constraint to begin the next aggregation round with */
    16298 if( firstchange == INT_MAX && consdata->changed )
    16299 firstchange = c;
    16300
    16301 /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
    16302 if( firstupgradetry == INT_MAX && !consdata->upgradetried )
    16303 firstupgradetry = c;
    16304
    16305 /* check, if constraint is already preprocessed */
    16306 if( consdata->presolved )
    16307 continue;
    16308
    16309 assert(SCIPconsIsActive(cons));
    16310
    16311 SCIPdebugMsg(scip, "presolving linear constraint <%s>\n", SCIPconsGetName(cons));
    16313
    16314 /* apply presolving as long as possible on the single constraint (however, abort after a certain number of rounds
    16315 * to avoid nearly infinite cycling due to very small bound changes)
    16316 */
    16317 npresolrounds = 0;
    16318 while( !consdata->presolved && npresolrounds < MAXCONSPRESOLROUNDS && !SCIPisStopped(scip) )
    16319 {
    16320 assert(!cutoff);
    16321 npresolrounds++;
    16322
    16323 /* mark constraint being presolved and propagated */
    16324 consdata->presolved = TRUE;
    16326
    16327 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
    16328
    16329 if( infeasible )
    16330 {
    16331 SCIPdebugMsg(scip, " -> infeasible normalization\n");
    16332 cutoff = TRUE;
    16333 break;
    16334 }
    16335
    16336 /* tighten left and right hand side due to integrality */
    16337 SCIP_CALL( tightenSides(scip, cons, nchgsides, &infeasible) );
    16338
    16339 if( infeasible )
    16340 {
    16341 SCIPdebugMsg(scip, " -> infeasibility detected during tightening sides\n");
    16342 cutoff = TRUE;
    16343 break;
    16344 }
    16345
    16346 /* check bounds */
    16347 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
    16348 {
    16349 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
    16350 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
    16351 cutoff = TRUE;
    16352 break;
    16353 }
    16354
    16355 /* tighten variable's bounds */
    16356 SCIP_CALL( tightenBounds(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, nchgbds) );
    16357 if( cutoff )
    16358 break;
    16359
    16360 /* check for fixed variables */
    16361 SCIP_CALL( fixVariables(scip, cons, &cutoff, nfixedvars) );
    16362 if( cutoff )
    16363 break;
    16364
    16365 /* if the maximal coefficient is large, recompute the activities before infeasibility and redundancy checks */
    16366 if( ( consdata->validmaxabsval && consdata->maxabsval > MAXVALRECOMP )
    16367 || ( consdata->validminabsval && consdata->minabsval < MINVALRECOMP ) )
    16368 {
    16371 }
    16372
    16373 /* get activity bounds */
    16374 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &isminacttight, &ismaxacttight,
    16375 &isminsettoinfinity, &ismaxsettoinfinity);
    16376
    16377 /* check constraint for infeasibility and redundancy */
    16378 if( SCIPisFeasGT(scip, minactivity, consdata->rhs) || SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
    16379 {
    16380 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
    16381 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
    16382 cutoff = TRUE;
    16383 break;
    16384 }
    16385 else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
    16386 {
    16387 SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
    16388 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
    16389 SCIP_CALL( SCIPdelCons(scip, cons) );
    16390 assert(!SCIPconsIsActive(cons));
    16391
    16392 if( !consdata->upgraded )
    16393 (*ndelconss)++;
    16394 break;
    16395 }
    16396 else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisGE(scip, minactivity, consdata->lhs) )
    16397 {
    16398 SCIPdebugMsg(scip, "linear constraint <%s> left hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
    16399 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
    16400 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
    16401 if( !consdata->upgraded )
    16402 (*nchgsides)++;
    16403 }
    16404 else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
    16405 {
    16406 SCIPdebugMsg(scip, "linear constraint <%s> right hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
    16407 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
    16409 if( !consdata->upgraded )
    16410 (*nchgsides)++;
    16411 }
    16412
    16413 /* handle empty constraint */
    16414 if( consdata->nvars == 0 )
    16415 {
    16416 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
    16417 {
    16418 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
    16419 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
    16420 cutoff = TRUE;
    16421 }
    16422 else
    16423 {
    16424 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
    16425 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
    16426 SCIP_CALL( SCIPdelCons(scip, cons) );
    16427 assert(!SCIPconsIsActive(cons));
    16428
    16429 if( !consdata->upgraded )
    16430 (*ndelconss)++;
    16431 }
    16432 break;
    16433 }
    16434
    16435 /* reduce big-M coefficients, that make the constraint redundant if the variable is on a bound */
    16436 SCIP_CALL( consdataTightenCoefs(scip, cons, nchgcoefs, nchgsides) );
    16437
    16438 /* try to simplify inequalities */
    16439 if( conshdlrdata->simplifyinequalities )
    16440 {
    16441 SCIP_CALL( simplifyInequalities(scip, cons, nchgcoefs, nchgsides, &cutoff) );
    16442
    16443 if( cutoff )
    16444 break;
    16445 }
    16446
    16447 /* aggregation variable in equations */
    16448 if( conshdlrdata->aggregatevariables )
    16449 {
    16450 SCIP_CALL( aggregateVariables(scip, cons, &cutoff, nfixedvars, naggrvars) );
    16451 if( cutoff )
    16452 break;
    16453 }
    16454 }
    16455
    16456 if( !cutoff && !SCIPisStopped(scip) )
    16457 {
    16458 /* perform ranged row propagation */
    16459 if( conshdlrdata->rangedrowpropagation )
    16460 {
    16461 int lastnfixedvars;
    16462
    16463 lastnfixedvars = *nfixedvars;
    16464
    16465 SCIP_CALL( rangedRowPropagation(scip, cons, &cutoff, nfixedvars, nchgbds, naddconss) );
    16466 if( !cutoff )
    16467 {
    16468 if( lastnfixedvars < *nfixedvars )
    16469 {
    16470 SCIP_CALL( applyFixings(scip, cons, &cutoff) );
    16471 }
    16472 }
    16473 }
    16474
    16475 /* extract cliques from constraint */
    16476 if( conshdlrdata->extractcliques && !cutoff && SCIPconsIsActive(cons) )
    16477 {
    16478 SCIP_CALL( extractCliques(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars,
    16479 nfixedvars, nchgbds, &cutoff) );
    16480
    16481 /* check if the constraint got redundant or infeasible */
    16482 if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 0 )
    16483 {
    16484 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
    16485 {
    16486 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
    16487 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
    16488 cutoff = TRUE;
    16489 }
    16490 else
    16491 {
    16492 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
    16493 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
    16494 SCIP_CALL( SCIPdelCons(scip, cons) );
    16495 assert(!SCIPconsIsActive(cons));
    16496
    16497 if( !consdata->upgraded )
    16498 (*ndelconss)++;
    16499 }
    16500 }
    16501 }
    16502
    16503 /* convert special equalities */
    16504 if( !cutoff && SCIPconsIsActive(cons) )
    16505 {
    16506 SCIP_CALL( convertEquality(scip, cons, conshdlrdata, &cutoff, nfixedvars, naggrvars, ndelconss, nchgvartypes) );
    16507 }
    16508
    16509 /* apply dual presolving for variables that appear in only one constraint */
    16510 if( !cutoff && SCIPconsIsActive(cons) && conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) )
    16511 {
    16512 SCIP_CALL( dualPresolve(scip, conshdlrdata, cons, &cutoff, nfixedvars, naggrvars, ndelconss, nchgvartypes) );
    16513 }
    16514
    16515 /* check if an inequality is parallel to the objective function */
    16516 if( !cutoff && SCIPconsIsActive(cons) )
    16517 {
    16518 SCIP_CALL( checkParallelObjective(scip, cons, conshdlrdata) );
    16519 }
    16520
    16521 /* remember the first changed constraint to begin the next aggregation round with */
    16522 if( firstchange == INT_MAX && consdata->changed )
    16523 firstchange = c;
    16524
    16525 /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
    16526 if( firstupgradetry == INT_MAX && !consdata->upgradetried )
    16527 firstupgradetry = c;
    16528 }
    16529
    16530 /* singleton column stuffing */
    16531 if( !cutoff && SCIPconsIsActive(cons) && SCIPconsIsChecked(cons) &&
    16532 (conshdlrdata->singletonstuffing || conshdlrdata->singlevarstuffing) && SCIPallowStrongDualReds(scip) )
    16533 {
    16534 SCIP_CALL( presolStuffing(scip, cons, conshdlrdata->singletonstuffing,
    16535 conshdlrdata->singlevarstuffing, &cutoff, nfixedvars, nchgbds) );
    16536
    16537 /* handle empty constraint */
    16538 if( consdata->nvars == 0 )
    16539 {
    16540 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
    16541 {
    16542 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
    16543 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
    16544 cutoff = TRUE;
    16545 }
    16546 else
    16547 {
    16548 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
    16549 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
    16550 SCIP_CALL( SCIPdelCons(scip, cons) );
    16551 assert(!SCIPconsIsActive(cons));
    16552
    16553 if( !consdata->upgraded )
    16554 (*ndelconss)++;
    16555 }
    16556 break;
    16557 }
    16558 }
    16559 }
    16560
    16561 /* process pairs of constraints: check them for redundancy and try to aggregate them;
    16562 * only apply this expensive procedure in exhaustive presolving timing
    16563 */
    16564 if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && (conshdlrdata->presolusehashing || conshdlrdata->presolpairwise) && !SCIPisStopped(scip) )
    16565 {
    16566 assert(firstchange >= 0);
    16567
    16568 if( firstchange < nconss && conshdlrdata->presolusehashing )
    16569 {
    16570 /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
    16571 SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff,
    16572 ndelconss, nchgsides) );
    16573 }
    16574
    16575 if( firstchange < nconss && conshdlrdata->presolpairwise )
    16576 {
    16577 SCIP_CONS** usefulconss;
    16578 int nusefulconss;
    16579 int firstchangenew;
    16580 SCIP_Longint npaircomparisons;
    16581
    16582 npaircomparisons = 0;
    16583 oldndelconss = *ndelconss;
    16584 oldnchgsides = *nchgsides;
    16585 oldnchgcoefs = *nchgcoefs;
    16586
    16587 /* allocate temporary memory */
    16588 SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, nconss) );
    16589
    16590 nusefulconss = 0;
    16591 firstchangenew = -1;
    16592 for( c = 0; c < nconss; ++c )
    16593 {
    16594 /* update firstchange */
    16595 if( c == firstchange )
    16596 firstchangenew = nusefulconss;
    16597
    16598 /* ignore inactive and modifiable constraints */
    16599 if( !SCIPconsIsActive(conss[c]) || SCIPconsIsModifiable(conss[c]) )
    16600 continue;
    16601
    16602 usefulconss[nusefulconss] = conss[c];
    16603 ++nusefulconss;
    16604 }
    16605 firstchange = firstchangenew;
    16606 assert(firstchangenew >= 0 && firstchangenew <= nusefulconss);
    16607
    16608 for( c = firstchange; c < nusefulconss && !cutoff && !SCIPisStopped(scip); ++c )
    16609 {
    16610 /* constraint has become inactive or modifiable during pairwise presolving */
    16611 if( usefulconss[c] == NULL )
    16612 continue;
    16613
    16614 npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? c : (c - firstchange); /*lint !e776*/
    16615
    16616 assert(SCIPconsIsActive(usefulconss[c]) && !SCIPconsIsModifiable(usefulconss[c]));
    16617 SCIP_CALL( preprocessConstraintPairs(scip, usefulconss, firstchange, c, conshdlrdata->maxaggrnormscale,
    16618 &cutoff, ndelconss, nchgsides, nchgcoefs) );
    16619
    16620 if( npaircomparisons > conshdlrdata->nmincomparisons )
    16621 {
    16622 assert(npaircomparisons > 0);
    16623 if( ((*ndelconss - oldndelconss) + (*nchgsides - oldnchgsides)/2.0 + (*nchgcoefs - oldnchgcoefs)/10.0) / ((SCIP_Real) npaircomparisons) < conshdlrdata->mingainpernmincomp )
    16624 break;
    16625 oldndelconss = *ndelconss;
    16626 oldnchgsides = *nchgsides;
    16627 oldnchgcoefs = *nchgcoefs;
    16628 npaircomparisons = 0;
    16629 }
    16630 }
    16631 /* free temporary memory */
    16632 SCIPfreeBufferArray(scip, &usefulconss);
    16633 }
    16634 }
    16635
    16636 /* before upgrading, check whether we can apply some additional dual presolving, because a variable only appears
    16637 * in linear constraints and we therefore have full information about it
    16638 */
    16639 if( !cutoff && firstupgradetry < nconss
    16640 && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
    16641 && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides
    16642 )
    16643 {
    16644 if( conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) && !SCIPisStopped(scip) )
    16645 {
    16646 SCIP_CALL( fullDualPresolve(scip, conss, nconss, &cutoff, nchgbds, nchgvartypes) );
    16647 }
    16648 }
    16649
    16650 /* try to upgrade constraints into a more specific constraint type;
    16651 * only upgrade constraints, if no reductions were found in this round (otherwise, the linear constraint handler
    16652 * may find additional reductions before giving control away to other (less intelligent?) constraint handlers)
    16653 */
    16654 if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && SCIPisPresolveFinished(scip) )
    16655 {
    16656 for( c = firstupgradetry; c < nconss && !SCIPisStopped(scip); ++c )
    16657 {
    16658 cons = conss[c];
    16659
    16660 /* don't upgrade modifiable constraints */
    16661 if( SCIPconsIsModifiable(cons) )
    16662 continue;
    16663
    16664 consdata = SCIPconsGetData(cons);
    16665 assert(consdata != NULL);
    16666
    16667 /* only upgrade completely presolved constraints, that changed since the last upgrading call */
    16668 if( consdata->upgradetried )
    16669 continue;
    16670 /* @todo force that upgrade will be performed later? */
    16671 if( !consdata->presolved )
    16672 continue;
    16673
    16674 consdata->upgradetried = TRUE;
    16675 if( SCIPconsIsActive(cons) )
    16676 {
    16677 SCIP_CONS* upgdcons;
    16678
    16679 SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
    16680 if( upgdcons != NULL )
    16681 {
    16682 /* add the upgraded constraint to the problem */
    16683 SCIP_CALL( SCIPaddConsUpgrade(scip, cons, &upgdcons) );
    16684 ++(*nupgdconss);
    16685
    16686 /* mark the linear constraint being upgraded and to be removed after presolving;
    16687 * don't delete it directly, because it may help to preprocess other linear constraints
    16688 */
    16689 assert(!consdata->upgraded);
    16690 consdata->upgraded = TRUE;
    16691
    16692 /* delete upgraded inequalities immediately;
    16693 * delete upgraded equalities, if we don't need it anymore for aggregation and redundancy checking
    16694 */
    16695 if( SCIPisLT(scip, consdata->lhs, consdata->rhs)
    16696 || !conshdlrdata->presolpairwise
    16697 || (conshdlrdata->maxaggrnormscale == 0.0) )
    16698 {
    16699 SCIP_CALL( SCIPdelCons(scip, cons) );
    16700 }
    16701 }
    16702 }
    16703 }
    16704 }
    16705
    16706 /* return the correct result code */
    16707 if( cutoff )
    16708 *result = SCIP_CUTOFF;
    16709 else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss
    16710 || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
    16711 *result = SCIP_SUCCESS;
    16712 else
    16713 *result = SCIP_DIDNOTFIND;
    16714
    16715 return SCIP_OKAY;
    16716}
    16717
    16718
    16719/** propagation conflict resolving method of constraint handler */
    16720static
    16721SCIP_DECL_CONSRESPROP(consRespropLinear)
    16722{ /*lint --e{715}*/
    16723 assert(scip != NULL);
    16724 assert(cons != NULL);
    16725 assert(result != NULL);
    16726
    16727 SCIP_CALL( resolvePropagation(scip, cons, infervar, intToInferInfo(inferinfo), boundtype, bdchgidx, result) );
    16728
    16729 return SCIP_OKAY;
    16730}
    16731
    16732
    16733/** variable rounding lock method of constraint handler */
    16734static
    16735SCIP_DECL_CONSLOCK(consLockLinear)
    16736{ /*lint --e{715}*/
    16737 SCIP_CONSDATA* consdata;
    16738 SCIP_Bool haslhs;
    16739 SCIP_Bool hasrhs;
    16740 int i;
    16741
    16742 assert(scip != NULL);
    16743 assert(cons != NULL);
    16744 consdata = SCIPconsGetData(cons);
    16745 assert(consdata != NULL);
    16746
    16747 haslhs = !SCIPisInfinity(scip, -consdata->lhs);
    16748 hasrhs = !SCIPisInfinity(scip, consdata->rhs);
    16749
    16750 /* update rounding locks of every single variable */
    16751 for( i = 0; i < consdata->nvars; ++i )
    16752 {
    16753 if( SCIPisPositive(scip, consdata->vals[i]) )
    16754 {
    16755 if( haslhs )
    16756 {
    16757 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
    16758 }
    16759 if( hasrhs )
    16760 {
    16761 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
    16762 }
    16763 }
    16764 else
    16765 {
    16766 if( haslhs )
    16767 {
    16768 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
    16769 }
    16770 if( hasrhs )
    16771 {
    16772 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
    16773 }
    16774 }
    16775 }
    16776
    16777 return SCIP_OKAY;
    16778}
    16779
    16780
    16781/** variable deletion method of constraint handler */
    16782static
    16783SCIP_DECL_CONSDELVARS(consDelvarsLinear)
    16784{
    16785 assert(scip != NULL);
    16786 assert(conshdlr != NULL);
    16787 assert(conss != NULL || nconss == 0);
    16788
    16789 if( nconss > 0 )
    16790 {
    16791 SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
    16792 }
    16793
    16794 return SCIP_OKAY;
    16795}
    16796
    16797/** constraint display method of constraint handler */
    16798static
    16799SCIP_DECL_CONSPRINT(consPrintLinear)
    16800{ /*lint --e{715}*/
    16801 assert(scip != NULL);
    16802 assert(conshdlr != NULL);
    16803 assert(cons != NULL);
    16804
    16806
    16807 return SCIP_OKAY;
    16808}
    16809
    16810/** constraint copying method of constraint handler */
    16811static
    16812SCIP_DECL_CONSCOPY(consCopyLinear)
    16813{ /*lint --e{715}*/
    16814 SCIP_VAR** sourcevars;
    16815 SCIP_Real* sourcecoefs;
    16816 const char* consname;
    16817 int nvars;
    16818
    16819 assert(scip != NULL);
    16820 assert(sourcescip != NULL);
    16821 assert(sourcecons != NULL);
    16822
    16823 /* get variables and coefficients of the source constraint */
    16824 sourcevars = SCIPgetVarsLinear(sourcescip, sourcecons);
    16825 sourcecoefs = SCIPgetValsLinear(sourcescip, sourcecons);
    16826 nvars = SCIPgetNVarsLinear(sourcescip, sourcecons);
    16827
    16828 if( name != NULL )
    16829 consname = name;
    16830 else
    16831 consname = SCIPconsGetName(sourcecons);
    16832
    16833 SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, sourcecoefs,
    16834 SCIPgetLhsLinear(sourcescip, sourcecons), SCIPgetRhsLinear(sourcescip, sourcecons), varmap, consmap,
    16835 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
    16836 assert(cons != NULL || *valid == FALSE);
    16837
    16838 /* @todo should also the checkabsolute flag of the constraint be copied? */
    16839
    16840 return SCIP_OKAY;
    16841}
    16842
    16843/** find operators '<=', '==', '>=', [free] in input string and return those places
    16844 *
    16845 * There should only be one operator, except for ranged rows for which exactly two operators '<=' must be present.
    16846 */
    16847static
    16849 const char* str, /**< null terminated input string */
    16850 char** firstoperator, /**< pointer to store the string starting at the first operator */
    16851 char** secondoperator, /**< pointer to store the string starting at the second operator */
    16852 SCIP_Bool* success /**< pointer to store if the line contains a valid operator order */
    16853 )
    16854{
    16855 char* curr;
    16856
    16857 assert(str != NULL);
    16858 assert(firstoperator != NULL);
    16859 assert(secondoperator != NULL);
    16860
    16861 *firstoperator = NULL;
    16862 *secondoperator = NULL;
    16863
    16864 curr = (char*)str;
    16865 *success = TRUE;
    16866
    16867 /* loop over the input string to find all operators */
    16868 while( *curr && *success )
    16869 {
    16870 SCIP_Bool found = FALSE;
    16871 int increment = 1;
    16872
    16873 /* try if we found a possible operator */
    16874 switch( *curr )
    16875 {
    16876 case '<':
    16877 case '=':
    16878 case '>':
    16879
    16880 /* check if the two characters curr[0,1] form an operator together */
    16881 if( curr[1] == '=' )
    16882 {
    16883 found = TRUE;
    16884
    16885 /* update increment to continue after this operator */
    16886 increment = 2;
    16887 }
    16888 break;
    16889 case '[':
    16890 if( strncmp(curr, "[free]", 6) == 0 )
    16891 {
    16892 found = TRUE;
    16893
    16894 /* update increment to continue after this operator */
    16895 increment = 6;
    16896 }
    16897 break;
    16898 default:
    16899 break;
    16900 }
    16901
    16902 /* assign the found operator to the first or second pointer and check for violations of the linear constraint grammar */
    16903 if( found )
    16904 {
    16905 if( *firstoperator == NULL )
    16906 {
    16907 *firstoperator = curr;
    16908 }
    16909 else
    16910 {
    16911 if( *secondoperator != NULL )
    16912 {
    16913 SCIPerrorMessage("Found more than two operators in line %s\n", str);
    16914 *success = FALSE;
    16915 }
    16916 else if( strncmp(*firstoperator, "<=", 2) != 0 )
    16917 {
    16918 SCIPerrorMessage("Two operators in line that is not a ranged row: %s", str);
    16919 *success = FALSE;
    16920 }
    16921 else if( strncmp(curr, "<=", 2) != 0 )
    16922 {
    16923 SCIPerrorMessage("Bad second operator, expected ranged row specification: %s", str);
    16924 *success = FALSE;
    16925 }
    16926
    16927 *secondoperator = curr;
    16928 }
    16929 }
    16930
    16931 curr += increment;
    16932 }
    16933
    16934 /* check if we did find at least one operator */
    16935 if( *success )
    16936 {
    16937 if( *firstoperator == NULL )
    16938 {
    16939 SCIPerrorMessage("Could not find any operator in line %s\n", str);
    16940 *success = FALSE;
    16941 }
    16942 }
    16943}
    16944
    16945/** constraint parsing method of constraint handler */
    16946static
    16947SCIP_DECL_CONSPARSE(consParseLinear)
    16948{ /*lint --e{715}*/
    16949 SCIP_VAR** vars;
    16950 SCIP_Real* coefs = NULL;
    16951 int nvars;
    16952 int coefssize = 100;
    16953 int requsize;
    16954 SCIP_Real lhs;
    16955 SCIP_Real rhs;
    16956 char* endptr;
    16957 char* firstop;
    16958 char* secondop;
    16959 SCIP_Bool operatorsuccess;
    16960 char* lhsstrptr = NULL;
    16961 char* rhsstrptr = NULL;
    16962 char* varstrptr = (char*)str;
    16963
    16964 assert(scip != NULL);
    16965 assert(success != NULL);
    16966 assert(str != NULL);
    16967 assert(name != NULL);
    16968 assert(cons != NULL);
    16969
    16970 *success = FALSE;
    16971
    16972 /* return of string empty */
    16973 if( !(*str) )
    16974 return SCIP_OKAY;
    16975
    16976 /* set left and right hand side to their default values */
    16977 lhs = -SCIPinfinity(scip);
    16978 rhs = SCIPinfinity(scip);
    16979
    16980 /* ignore whitespace */
    16981 SCIP_CALL( SCIPskipSpace((char**)&str) );
    16982
    16983 /* find operators in the line first, all other remaining parsing depends on occurence of the operators '<=', '>=', '==',
    16984 * and the special word [free]
    16985 */
    16986 findOperators(str, &firstop, &secondop, &operatorsuccess);
    16987
    16988 /* if the grammar is not valid for parsing a linear constraint, return */
    16989 if( ! operatorsuccess )
    16990 return SCIP_OKAY;
    16991 assert(firstop != NULL);
    16992
    16993 /* assign the strings for parsing the left hand side, right hand side, and the linear variable sum */
    16994 switch( *firstop )
    16995 {
    16996 case '<':
    16997 assert(firstop[1] == '=');
    16998 /* we have ranged row lhs <= a_1 x_1 + ... + a_n x_n <= rhs */
    16999 if( secondop != NULL )
    17000 {
    17001 assert(secondop[0] == '<' && secondop[1] == '=');
    17002 lhsstrptr = (char *)str;
    17003 varstrptr = firstop + 2;
    17004 rhsstrptr = secondop + 2;
    17005 }
    17006 else
    17007 {
    17008 /* we have an inequality with infinite left hand side a_1 x_1 + ... + a_n x_n <= rhs */
    17009 lhsstrptr = NULL;
    17010 varstrptr = (char *)str;
    17011 rhsstrptr = firstop + 2;
    17012 }
    17013 break;
    17014 case '>':
    17015 assert(firstop[1] == '=');
    17016 assert(secondop == NULL);
    17017 /* we have a_1 x_1 + ... + a_n x_n >= lhs */
    17018 lhsstrptr = firstop + 2;
    17019 break;
    17020 case '=':
    17021 assert(firstop[1] == '=');
    17022 assert(secondop == NULL);
    17023 /* we have a_1 x_1 + ... + a_n x_n == lhs (rhs) */
    17024 rhsstrptr = firstop + 2;
    17025 lhsstrptr = firstop + 2;
    17026 break;
    17027 case '[':
    17028 assert(strncmp(firstop, "[free]", 6) == 0);
    17029 assert(secondop == NULL);
    17030 /* nothing to assign in case of a free a_1 x_1 + ... + a_n x_n [free] */
    17031 break;
    17032 default:
    17033 /* it should not be possible that a different character appears in that position */
    17034 SCIPerrorMessage("Parsing has wrong operator character '%c', should be one of <=>[", *firstop);
    17035 return SCIP_READERROR;
    17036 }
    17037
    17038 /* parse left hand side, if necessary */
    17039 if( lhsstrptr != NULL )
    17040 {
    17041 if( ! SCIPparseReal(scip, lhsstrptr, &lhs, &endptr) )
    17042 {
    17043 SCIPerrorMessage("error parsing left hand side number from <%s>\n", lhsstrptr);
    17044 return SCIP_OKAY;
    17045 }
    17046
    17047 /* in case of an equation, assign the left also to the right hand side */
    17048 if( rhsstrptr == lhsstrptr )
    17049 rhs = lhs;
    17050 }
    17051
    17052 /* parse right hand side, if different from left hand side */
    17053 if( rhsstrptr != NULL && rhsstrptr != lhsstrptr )
    17054 {
    17055 if( ! SCIPparseReal(scip, rhsstrptr, &rhs, &endptr) )
    17056 {
    17057 SCIPerrorMessage("error parsing right hand side number from <%s>\n", lhsstrptr);
    17058 return SCIP_OKAY;
    17059 }
    17060 }
    17061
    17062 /* initialize buffers for storing the variables and coefficients */
    17063 SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) );
    17064 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
    17065
    17066 assert(varstrptr != NULL);
    17067
    17068 /* parse linear sum to get variables and coefficients */
    17069 SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
    17070
    17071 if( *success && requsize > coefssize )
    17072 {
    17073 /* realloc buffers and try again */
    17074 coefssize = requsize;
    17075 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, coefssize) );
    17076 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
    17077
    17078 SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
    17079 assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
    17080 }
    17081
    17082 if( !*success )
    17083 {
    17084 SCIPerrorMessage("no luck in parsing linear sum '%s'\n", varstrptr);
    17085 }
    17086 else
    17087 {
    17088 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
    17089 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
    17090 }
    17091
    17092 SCIPfreeBufferArray(scip, &coefs);
    17093 SCIPfreeBufferArray(scip, &vars);
    17094
    17095 return SCIP_OKAY;
    17096}
    17097
    17098
    17099/** constraint method of constraint handler which returns the variables (if possible) */
    17100static
    17101SCIP_DECL_CONSGETVARS(consGetVarsLinear)
    17102{ /*lint --e{715}*/
    17103 SCIP_CONSDATA* consdata;
    17104
    17105 consdata = SCIPconsGetData(cons);
    17106 assert(consdata != NULL);
    17107
    17108 if( varssize < consdata->nvars )
    17109 (*success) = FALSE;
    17110 else
    17111 {
    17112 assert(vars != NULL);
    17113
    17114 BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
    17115 (*success) = TRUE;
    17116 }
    17117
    17118 return SCIP_OKAY;
    17119}
    17120
    17121/**! [Callback for the number of variables]*/
    17122/** constraint method of constraint handler which returns the number of variables (if possible) */
    17123static
    17124SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
    17125{ /*lint --e{715}*/
    17126 SCIP_CONSDATA* consdata;
    17127
    17128 consdata = SCIPconsGetData(cons);
    17129 assert(consdata != NULL);
    17130
    17131 (*nvars) = consdata->nvars;
    17132 (*success) = TRUE;
    17133
    17134 return SCIP_OKAY;
    17135}
    17136/**! [Callback for the number of variables]*/
    17137
    17138/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
    17139static
    17140SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphLinear)
    17141{ /*lint --e{715}*/
    17142 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
    17143
    17144 return SCIP_OKAY;
    17145}
    17146
    17147/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
    17148static
    17149SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphLinear)
    17150{ /*lint --e{715}*/
    17151 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
    17152
    17153 return SCIP_OKAY;
    17154}
    17155
    17156/*
    17157 * Callback methods of event handler
    17158 */
    17159
    17160/** execution method of event handler */
    17161static
    17162SCIP_DECL_EVENTEXEC(eventExecLinear)
    17163{ /*lint --e{715}*/
    17164 SCIP_CONS* cons;
    17165 SCIP_CONSDATA* consdata;
    17166 SCIP_VAR* var;
    17167 SCIP_EVENTTYPE eventtype;
    17168
    17169 assert(scip != NULL);
    17170 assert(eventhdlr != NULL);
    17171 assert(eventdata != NULL);
    17172 assert(event != NULL);
    17173
    17175
    17176 cons = eventdata->cons;
    17177 assert(cons != NULL);
    17178 consdata = SCIPconsGetData(cons);
    17179 assert(consdata != NULL);
    17180
    17181 /* we can skip events droped for deleted constraints */
    17182 if( SCIPconsIsDeleted(cons) )
    17183 return SCIP_OKAY;
    17184
    17185 eventtype = SCIPeventGetType(event);
    17186 var = SCIPeventGetVar(event);
    17187
    17189 {
    17190 SCIP_Real oldbound;
    17191 SCIP_Real newbound;
    17192 SCIP_Real val;
    17193 int varpos;
    17194
    17195 varpos = eventdata->varpos;
    17196 assert(0 <= varpos && varpos < consdata->nvars);
    17197 oldbound = SCIPeventGetOldbound(event);
    17198 newbound = SCIPeventGetNewbound(event);
    17199 assert(var != NULL);
    17200 assert(consdata->vars[varpos] == var);
    17201 val = consdata->vals[varpos];
    17202
    17203 /* we only need to update the activities if the constraint is active,
    17204 * otherwise we mark them to be invalid
    17205 */
    17206 if( SCIPconsIsActive(cons) )
    17207 {
    17208 /* update the activity values */
    17210 consdataUpdateActivitiesLb(scip, consdata, var, oldbound, newbound, val, TRUE);
    17211 else
    17212 {
    17213 assert((eventtype & SCIP_EVENTTYPE_UBCHANGED) != SCIP_EVENTTYPE_DISABLED);
    17214 consdataUpdateActivitiesUb(scip, consdata, var, oldbound, newbound, val, TRUE);
    17215 }
    17216 }
    17217 else
    17219
    17220 consdata->presolved = FALSE;
    17221
    17222 /* in probing do not reset disabled ranged row propagation */
    17223 if( !SCIPinProbing(scip) )
    17224 consdata->rangedrowpropagated = 0;
    17225
    17226 /* bound change can turn the constraint infeasible or redundant only if it was a tightening */
    17228 {
    17230
    17231 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
    17232 if( consdata->maxactdeltavar == var )
    17233 {
    17234 consdata->maxactdelta = SCIP_INVALID;
    17235 consdata->maxactdeltavar = NULL;
    17236 }
    17237
    17238 /* check whether bound tightening might now be successful */
    17239 if( consdata->boundstightened > 0)
    17240 {
    17241 switch( eventtype )
    17242 {
    17244 if( (val > 0.0 ? !SCIPisInfinity(scip, consdata->rhs) : !SCIPisInfinity(scip, -consdata->lhs)) )
    17245 consdata->boundstightened = 0;
    17246 break;
    17248 if( (val > 0.0 ? !SCIPisInfinity(scip, -consdata->lhs) : !SCIPisInfinity(scip, consdata->rhs)) )
    17249 consdata->boundstightened = 0;
    17250 break;
    17251 default:
    17252 SCIPerrorMessage("invalid event type %" SCIP_EVENTTYPE_FORMAT "\n", eventtype);
    17253 return SCIP_INVALIDDATA;
    17254 }
    17255 }
    17256 }
    17257 /* update maximal activity delta if a bound was relaxed */
    17258 else if( !SCIPisInfinity(scip, consdata->maxactdelta) )
    17259 {
    17260 SCIP_Real lb;
    17261 SCIP_Real ub;
    17262 SCIP_Real domain;
    17263 SCIP_Real delta;
    17264
    17266
    17267 lb = SCIPvarGetLbLocal(var);
    17268 ub = SCIPvarGetUbLocal(var);
    17269
    17270 domain = ub - lb;
    17271 delta = REALABS(val) * domain;
    17272
    17273 if( delta > consdata->maxactdelta )
    17274 {
    17275 consdata->maxactdelta = delta;
    17276 consdata->maxactdeltavar = var;
    17277 }
    17278 }
    17279 }
    17280 else if( (eventtype & SCIP_EVENTTYPE_VARFIXED) != SCIP_EVENTTYPE_DISABLED )
    17281 {
    17282 /* we want to remove the fixed variable */
    17283 consdata->presolved = FALSE;
    17284 consdata->removedfixings = FALSE;
    17285 consdata->rangedrowpropagated = 0;
    17286
    17287 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
    17288 if( consdata->maxactdeltavar == var )
    17289 {
    17290 consdata->maxactdelta = SCIP_INVALID;
    17291 consdata->maxactdeltavar = NULL;
    17292 }
    17293 }
    17294 else if( (eventtype & SCIP_EVENTTYPE_VARUNLOCKED) != SCIP_EVENTTYPE_DISABLED )
    17295 {
    17296 /* there is only one lock left: we may multi-aggregate the variable as slack of an equation */
    17299 consdata->presolved = FALSE;
    17300 }
    17301 else if( (eventtype & SCIP_EVENTTYPE_GBDCHANGED) != SCIP_EVENTTYPE_DISABLED )
    17302 {
    17303 SCIP_Real oldbound;
    17304 SCIP_Real newbound;
    17305 SCIP_Real val;
    17306 int varpos;
    17307
    17308 varpos = eventdata->varpos;
    17309 assert(0 <= varpos && varpos < consdata->nvars);
    17310 oldbound = SCIPeventGetOldbound(event);
    17311 newbound = SCIPeventGetNewbound(event);
    17312 assert(var != NULL);
    17313 assert(consdata->vars[varpos] == var);
    17314 val = consdata->vals[varpos];
    17315
    17316 consdata->rangedrowpropagated = 0;
    17317
    17318 /* update the activity values */
    17320 consdataUpdateActivitiesGlbLb(scip, consdata, oldbound, newbound, val, TRUE);
    17321 else
    17322 {
    17323 assert((eventtype & SCIP_EVENTTYPE_GUBCHANGED) != SCIP_EVENTTYPE_DISABLED);
    17324 consdataUpdateActivitiesGlbUb(scip, consdata, oldbound, newbound, val, TRUE);
    17325 }
    17326
    17327 /* if the variable is binary but not fixed it had to become binary due to this global change */
    17329 {
    17331 consdata->indexsorted = FALSE;
    17332 else
    17333 consdata->coefsorted = FALSE;
    17334 }
    17335 }
    17336 else if( (eventtype & SCIP_EVENTTYPE_TYPECHANGED) != SCIP_EVENTTYPE_DISABLED )
    17337 {
    17339
    17340 /* for presolving it only matters if a variable becomes integral */
    17341 consdata->presolved = (consdata->presolved && (SCIPeventGetOldtype(event) != SCIP_VARTYPE_CONTINUOUS || SCIPvarIsImpliedIntegral(var)));
    17342
    17343 /* the ordering is preserved if the variable remains binary */
    17344 consdata->indexsorted = (consdata->indexsorted && SCIPvarIsBinary(var) && (SCIPeventGetOldtype(event) != SCIP_VARTYPE_CONTINUOUS || SCIPvarIsImpliedIntegral(var)));
    17345 }
    17347 {
    17349
    17350 /* for presolving it only matters if a variable becomes integral */
    17351 consdata->presolved = (consdata->presolved && (SCIPeventGetOldImpltype(event) != SCIP_IMPLINTTYPE_NONE || SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS));
    17352
    17353 /* the ordering is preserved if the variable remains binary */
    17354 consdata->indexsorted = (consdata->indexsorted && SCIPvarIsBinary(var) && (SCIPeventGetOldImpltype(event) != SCIP_IMPLINTTYPE_NONE || SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS));
    17355 }
    17356 else
    17357 {
    17358 assert((eventtype & SCIP_EVENTTYPE_VARDELETED) != SCIP_EVENTTYPE_DISABLED);
    17359 consdata->varsdeleted = TRUE;
    17360 }
    17361
    17362 return SCIP_OKAY;
    17363}
    17364
    17365
    17366/*
    17367 * Callback methods of conflict handler
    17368 */
    17369
    17370/** conflict processing method of conflict handler (called when conflict was found) */
    17371static
    17372SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
    17373{ /*lint --e{715}*/
    17374 SCIP_VAR** vars;
    17375 SCIP_Real* vals;
    17376 SCIP_Real lhs;
    17377 int i;
    17378
    17379 assert(scip != NULL);
    17380 assert(conflicthdlr != NULL);
    17381 assert(bdchginfos != NULL || nbdchginfos == 0);
    17382 assert(result != NULL);
    17383
    17385
    17386 /* don't process already resolved conflicts */
    17387 if( resolved )
    17388 {
    17389 *result = SCIP_DIDNOTRUN;
    17390 return SCIP_OKAY;
    17391 }
    17392
    17393 *result = SCIP_DIDNOTFIND;
    17394
    17395 /* create array of variables and coefficients: sum_{i \in P} x_i - sum_{i \in N} x_i >= 1 - |N| */
    17396 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
    17397 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nbdchginfos) );
    17398 lhs = 1.0;
    17399 for( i = 0; i < nbdchginfos; ++i )
    17400 {
    17401 assert(bdchginfos != NULL);
    17402
    17403 vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
    17404
    17405 /* we can only treat binary variables */
    17406 /**@todo extend linear conflict constraints to some non-binary cases */
    17407 if( !SCIPvarIsBinary(vars[i]) )
    17408 break;
    17409
    17410 /* check whether the variable is fixed to zero (P) or one (N) in the conflict set */
    17411 if( SCIPbdchginfoGetNewbound(bdchginfos[i]) < 0.5 )
    17412 vals[i] = 1.0;
    17413 else
    17414 {
    17415 vals[i] = -1.0;
    17416 lhs -= 1.0;
    17417 }
    17418 }
    17419
    17420 if( i == nbdchginfos )
    17421 {
    17422 SCIP_CONS* cons;
    17423 SCIP_CONS* upgdcons;
    17424 char consname[SCIP_MAXSTRLEN];
    17425
    17426 /* create a constraint out of the conflict set */
    17428 SCIP_CALL( SCIPcreateConsLinear(scip, &cons, consname, nbdchginfos, vars, vals, lhs, SCIPinfinity(scip),
    17429 FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
    17430
    17431 /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
    17432 SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
    17433 if( upgdcons != NULL )
    17434 {
    17435 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
    17436 cons = upgdcons;
    17437 }
    17438
    17439 /* add conflict to SCIP */
    17440 SCIP_CALL( SCIPaddConflict(scip, node, &cons, validnode, conftype, cutoffinvolved) );
    17441
    17442 *result = SCIP_CONSADDED;
    17443 }
    17444
    17445 /* free temporary memory */
    17446 SCIPfreeBufferArray(scip, &vals);
    17447 SCIPfreeBufferArray(scip, &vars);
    17448
    17449 return SCIP_OKAY;
    17450}
    17451
    17452
    17453/*
    17454 * Nonlinear constraint upgrading
    17455 */
    17456
    17457/** tries to upgrade a nonlinear constraint into a linear constraint */
    17458static
    17459SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
    17460{
    17461 SCIP_CONSDATA* consdata;
    17462 SCIP_EXPR* expr;
    17463 SCIP_Real lhs;
    17464 SCIP_Real rhs;
    17465 int i;
    17466
    17467 assert(nupgdconss != NULL);
    17468 assert(upgdconss != NULL);
    17469 assert(upgdconsssize > 0);
    17470
    17471 expr = SCIPgetExprNonlinear(cons);
    17472 assert(expr != NULL);
    17473
    17474 /* not a linear constraint if the expression is not a sum
    17475 * (unless the expression is a variable or a constant or a constant*variable, but these are simplified away in cons_nonlinear)
    17476 */
    17477 if( !SCIPisExprSum(scip, expr) )
    17478 return SCIP_OKAY;
    17479
    17480 /* if at least one child is not a variable, then not a linear constraint */
    17481 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
    17482 if( !SCIPisExprVar(scip, SCIPexprGetChildren(expr)[i]) )
    17483 return SCIP_OKAY;
    17484
    17485 /* consider constant part of the sum expression */
    17488
    17489 SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
    17490 0, NULL, NULL, lhs, rhs,
    17494 SCIPconsIsStickingAtNode(cons)) );
    17495 assert(upgdconss[0] != NULL);
    17496
    17497 consdata = SCIPconsGetData(upgdconss[0]);
    17498
    17499 /* add linear terms */
    17501 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
    17502 {
    17504 }
    17505
    17506 /* check violation of this linear constraint with absolute tolerances, to be consistent with the original nonlinear constraint */
    17507 consdata->checkabsolute = TRUE;
    17508
    17509 *nupgdconss = 1;
    17510
    17511 SCIPdebugMsg(scip, "created linear constraint:\n");
    17512 SCIPdebugPrintCons(scip, upgdconss[0], NULL);
    17513
    17514 return SCIP_OKAY;
    17515} /*lint !e715*/
    17516
    17517/*
    17518 * constraint specific interface methods
    17519 */
    17520
    17521/** creates the handler for linear constraints and includes it in SCIP */
    17523 SCIP* scip /**< SCIP data structure */
    17524 )
    17525{
    17526 SCIP_CONSHDLRDATA* conshdlrdata;
    17527 SCIP_CONSHDLR* conshdlr;
    17528 SCIP_EVENTHDLR* eventhdlr;
    17529 SCIP_CONFLICTHDLR* conflicthdlr;
    17530
    17531 assert(scip != NULL);
    17532
    17533 /* create event handler for bound change events */
    17535 eventExecLinear, NULL) );
    17536
    17537 /* create conflict handler for linear constraints */
    17539 conflictExecLinear, NULL) );
    17540
    17541 /* create constraint handler data */
    17542 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
    17543
    17544 /* include constraint handler */
    17547 consEnfolpLinear, consEnfopsLinear, consCheckLinear, consLockLinear,
    17548 conshdlrdata) );
    17549
    17550 assert(conshdlr != NULL);
    17551
    17552 /* set non-fundamental callbacks via specific setter functions */
    17553 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLinear, consCopyLinear) );
    17554 SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveLinear) );
    17555 SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveLinear) );
    17556 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLinear) );
    17557 SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsLinear) );
    17558 SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitLinear) );
    17559 SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLinear) );
    17560 SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolLinear) );
    17561 SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLinear) );
    17562 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLinear) );
    17563 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLinear) );
    17564 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLinear) );
    17565 SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitLinear) );
    17566 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLinear) );
    17567 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLinear) );
    17569 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLinear) );
    17572 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLinear) );
    17573 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLinear, consSepasolLinear, CONSHDLR_SEPAFREQ,
    17575 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLinear) );
    17576 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLinear) );
    17577 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphLinear) );
    17578 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphLinear) );
    17579
    17580 if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
    17581 {
    17582 /* include the linear constraint upgrade in the nonlinear constraint handler */
    17584 }
    17585
    17586 /* add linear constraint handler parameters */
    17588 "constraints/" CONSHDLR_NAME "/tightenboundsfreq",
    17589 "multiplier on propagation frequency, how often the bounds are tightened (-1: never, 0: only at root)",
    17590 &conshdlrdata->tightenboundsfreq, TRUE, DEFAULT_TIGHTENBOUNDSFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
    17592 "constraints/" CONSHDLR_NAME "/maxrounds",
    17593 "maximal number of separation rounds per node (-1: unlimited)",
    17594 &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
    17596 "constraints/" CONSHDLR_NAME "/maxroundsroot",
    17597 "maximal number of separation rounds per node in the root node (-1: unlimited)",
    17598 &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
    17600 "constraints/" CONSHDLR_NAME "/maxsepacuts",
    17601 "maximal number of cuts separated per separation round",
    17602 &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
    17604 "constraints/" CONSHDLR_NAME "/maxsepacutsroot",
    17605 "maximal number of cuts separated per separation round in the root node",
    17606 &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
    17608 "constraints/" CONSHDLR_NAME "/presolpairwise",
    17609 "should pairwise constraint comparison be performed in presolving?",
    17610 &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
    17612 "constraints/" CONSHDLR_NAME "/presolusehashing",
    17613 "should hash table be used for detecting redundant constraints in advance",
    17614 &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
    17616 "constraints/" CONSHDLR_NAME "/nmincomparisons",
    17617 "number for minimal pairwise presolve comparisons",
    17618 &conshdlrdata->nmincomparisons, TRUE, DEFAULT_NMINCOMPARISONS, 1, INT_MAX, NULL, NULL) );
    17620 "constraints/" CONSHDLR_NAME "/mingainpernmincomparisons",
    17621 "minimal gain per minimal pairwise presolve comparisons to repeat pairwise comparison round",
    17622 &conshdlrdata->mingainpernmincomp, TRUE, DEFAULT_MINGAINPERNMINCOMP, 0.0, 1.0, NULL, NULL) );
    17624 "constraints/" CONSHDLR_NAME "/maxaggrnormscale",
    17625 "maximal allowed relative gain in maximum norm for constraint aggregation (0.0: disable constraint aggregation)",
    17626 &conshdlrdata->maxaggrnormscale, TRUE, DEFAULT_MAXAGGRNORMSCALE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
    17628 "constraints/" CONSHDLR_NAME "/maxeasyactivitydelta",
    17629 "maximum activity delta to run easy propagation on linear constraint (faster, but numerically less stable)",
    17630 &conshdlrdata->maxeasyactivitydelta, TRUE, DEFAULT_MAXEASYACTIVITYDELTA, 0.0, SCIP_REAL_MAX, NULL, NULL) );
    17632 "constraints/" CONSHDLR_NAME "/maxcardbounddist",
    17633 "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for separating knapsack cardinality cuts",
    17634 &conshdlrdata->maxcardbounddist, TRUE, DEFAULT_MAXCARDBOUNDDIST, 0.0, 1.0, NULL, NULL) );
    17636 "constraints/" CONSHDLR_NAME "/separateall",
    17637 "should all constraints be subject to cardinality cut generation instead of only the ones with non-zero dual value?",
    17638 &conshdlrdata->separateall, FALSE, DEFAULT_SEPARATEALL, NULL, NULL) );
    17640 "constraints/" CONSHDLR_NAME "/aggregatevariables",
    17641 "should presolving search for aggregations in equations",
    17642 &conshdlrdata->aggregatevariables, TRUE, DEFAULT_AGGREGATEVARIABLES, NULL, NULL) );
    17644 "constraints/" CONSHDLR_NAME "/simplifyinequalities",
    17645 "should presolving try to simplify inequalities",
    17646 &conshdlrdata->simplifyinequalities, TRUE, DEFAULT_SIMPLIFYINEQUALITIES, NULL, NULL) );
    17648 "constraints/" CONSHDLR_NAME "/dualpresolving",
    17649 "should dual presolving steps be performed?",
    17650 &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
    17652 "constraints/" CONSHDLR_NAME "/singletonstuffing",
    17653 "should stuffing of singleton continuous variables be performed?",
    17654 &conshdlrdata->singletonstuffing, TRUE, DEFAULT_SINGLETONSTUFFING, NULL, NULL) );
    17656 "constraints/" CONSHDLR_NAME "/singlevarstuffing",
    17657 "should single variable stuffing be performed, which tries to fulfill constraints using the cheapest variable?",
    17658 &conshdlrdata->singlevarstuffing, TRUE, DEFAULT_SINGLEVARSTUFFING, NULL, NULL) );
    17660 "constraints/" CONSHDLR_NAME "/sortvars", "apply binaries sorting in decr. order of coeff abs value?",
    17661 &conshdlrdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL) );
    17663 "constraints/" CONSHDLR_NAME "/checkrelmaxabs",
    17664 "should the violation for a constraint with side 0.0 be checked relative to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)?",
    17665 &conshdlrdata->checkrelmaxabs, TRUE, DEFAULT_CHECKRELMAXABS, NULL, NULL) );
    17667 "constraints/" CONSHDLR_NAME "/detectcutoffbound",
    17668 "should presolving try to detect constraints parallel to the objective function defining an upper bound and prevent these constraints from entering the LP?",
    17669 &conshdlrdata->detectcutoffbound, TRUE, DEFAULT_DETECTCUTOFFBOUND, NULL, NULL) );
    17671 "constraints/" CONSHDLR_NAME "/detectlowerbound",
    17672 "should presolving try to detect constraints parallel to the objective function defining a lower bound and prevent these constraints from entering the LP?",
    17673 &conshdlrdata->detectlowerbound, TRUE, DEFAULT_DETECTLOWERBOUND, NULL, NULL) );
    17675 "constraints/" CONSHDLR_NAME "/detectpartialobjective",
    17676 "should presolving try to detect subsets of constraints parallel to the objective function?",
    17677 &conshdlrdata->detectpartialobjective, TRUE, DEFAULT_DETECTPARTIALOBJECTIVE, NULL, NULL) );
    17679 "constraints/" CONSHDLR_NAME "/rangedrowpropagation",
    17680 "should presolving and propagation try to improve bounds, detect infeasibility, and extract sub-constraints from ranged rows and equations?",
    17681 &conshdlrdata->rangedrowpropagation, TRUE, DEFAULT_RANGEDROWPROPAGATION, NULL, NULL) );
    17683 "constraints/" CONSHDLR_NAME "/rangedrowartcons",
    17684 "should presolving and propagation extract sub-constraints from ranged rows and equations?",
    17685 &conshdlrdata->rangedrowartcons, TRUE, DEFAULT_RANGEDROWARTCONS, NULL, NULL) );
    17687 "constraints/" CONSHDLR_NAME "/rangedrowmaxdepth",
    17688 "maximum depth to apply ranged row propagation",
    17689 &conshdlrdata->rangedrowmaxdepth, TRUE, DEFAULT_RANGEDROWMAXDEPTH, 0, INT_MAX, NULL, NULL) );
    17691 "constraints/" CONSHDLR_NAME "/rangedrowfreq",
    17692 "frequency for applying ranged row propagation",
    17693 &conshdlrdata->rangedrowfreq, TRUE, DEFAULT_RANGEDROWFREQ, 1, SCIP_MAXTREEDEPTH, NULL, NULL) );
    17695 "constraints/" CONSHDLR_NAME "/multaggrremove",
    17696 "should multi-aggregations only be performed if the constraint can be removed afterwards?",
    17697 &conshdlrdata->multaggrremove, TRUE, DEFAULT_MULTAGGRREMOVE, NULL, NULL) );
    17699 "constraints/" CONSHDLR_NAME "/maxmultaggrquot",
    17700 "maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation",
    17701 &conshdlrdata->maxmultaggrquot, TRUE, DEFAULT_MAXMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
    17703 "constraints/" CONSHDLR_NAME "/maxdualmultaggrquot",
    17704 "maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation",
    17705 &conshdlrdata->maxdualmultaggrquot, TRUE, DEFAULT_MAXDUALMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
    17707 "constraints/" CONSHDLR_NAME "/extractcliques",
    17708 "should Cliques be extracted?",
    17709 &conshdlrdata->extractcliques, TRUE, DEFAULT_EXTRACTCLIQUES, NULL, NULL) );
    17710
    17711 return SCIP_OKAY;
    17712}
    17713
    17714/** includes a linear constraint update method into the linear constraint handler */
    17716 SCIP* scip, /**< SCIP data structure */
    17717 SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
    17718 int priority, /**< priority of upgrading method */
    17719 const char* conshdlrname /**< name of the constraint handler */
    17720 )
    17721{
    17722 SCIP_CONSHDLR* conshdlr;
    17723 SCIP_CONSHDLRDATA* conshdlrdata;
    17724 SCIP_LINCONSUPGRADE* linconsupgrade;
    17726 char paramdesc[SCIP_MAXSTRLEN];
    17727
    17728 assert(scip != NULL);
    17729 assert(linconsupgd != NULL);
    17730 assert(conshdlrname != NULL );
    17731
    17732 /* find the linear constraint handler */
    17733 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
    17734 if( conshdlr == NULL )
    17735 {
    17736 SCIPerrorMessage("linear constraint handler not found\n");
    17737 return SCIP_PLUGINNOTFOUND;
    17738 }
    17739
    17740 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    17741 assert(conshdlrdata != NULL);
    17742
    17743 /* check if linear constraint update method already exists in constraint handler data */
    17744 if( !conshdlrdataHasUpgrade(scip, conshdlrdata, linconsupgd, conshdlrname) )
    17745 {
    17746 /* create a linear constraint upgrade data object */
    17747 SCIP_CALL( linconsupgradeCreate(scip, &linconsupgrade, linconsupgd, priority) );
    17748
    17749 /* insert linear constraint update method into constraint handler data */
    17750 SCIP_CALL( conshdlrdataIncludeUpgrade(scip, conshdlrdata, linconsupgrade) );
    17751
    17752 /* adds parameter to turn on and off the upgrading step */
    17753 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/linear/upgrade/%s", conshdlrname);
    17754 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "enable linear upgrading for constraint handler <%s>", conshdlrname);
    17756 paramname, paramdesc,
    17757 &linconsupgrade->active, FALSE, TRUE, NULL, NULL) );
    17758 }
    17759
    17760 return SCIP_OKAY;
    17761}
    17762
    17763/** creates and captures a linear constraint
    17764 *
    17765 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
    17766 */
    17768 SCIP* scip, /**< SCIP data structure */
    17769 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    17770 const char* name, /**< name of constraint */
    17771 int nvars, /**< number of nonzeros in the constraint */
    17772 SCIP_VAR** vars, /**< array with variables of constraint entries */
    17773 SCIP_Real* vals, /**< array with coefficients of constraint entries */
    17774 SCIP_Real lhs, /**< left hand side of constraint */
    17775 SCIP_Real rhs, /**< right hand side of constraint */
    17776 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
    17777 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
    17778 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
    17779 * Usually set to TRUE. */
    17780 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
    17781 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    17782 SCIP_Bool check, /**< should the constraint be checked for feasibility?
    17783 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    17784 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
    17785 * Usually set to TRUE. */
    17786 SCIP_Bool local, /**< is constraint only valid locally?
    17787 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
    17788 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
    17789 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
    17790 * adds coefficients to this constraint. */
    17791 SCIP_Bool dynamic, /**< is constraint subject to aging?
    17792 * Usually set to FALSE. Set to TRUE for own cuts which
    17793 * are separated as constraints. */
    17794 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
    17795 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
    17796 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
    17797 * if it may be moved to a more global node?
    17798 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
    17799 )
    17800{
    17801 SCIP_CONSHDLR* conshdlr;
    17802 SCIP_CONSDATA* consdata;
    17803 int i;
    17804
    17805 assert(scip != NULL);
    17806 assert(cons != NULL);
    17807
    17808 /* find the linear constraint handler */
    17809 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
    17810 if( conshdlr == NULL )
    17811 {
    17812 SCIPerrorMessage("linear constraint handler not found\n");
    17813 return SCIP_PLUGINNOTFOUND;
    17814 }
    17815
    17816 /* terminate if a coefficient is infinite */
    17817 assert(SCIPisFinite(lhs));
    17818 assert(SCIPisFinite(rhs));
    17819 for( i = 0; i < nvars; ++i )
    17820 {
    17821 assert(SCIPisFinite(vals[i]));
    17822 if( SCIPisInfinity(scip, REALABS(vals[i])) )
    17823 {
    17824 SCIPerrorMessage("coefficient of variable <%s> in constraint <%s> is infinite,"
    17825 " consider adjusting the infinity threshold\n", SCIPvarGetName(vars[i]), name);
    17826 SCIPABORT();
    17827 return SCIP_INVALIDDATA;
    17828 }
    17829 }
    17830
    17831 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
    17832 * constraint after presolving we have to ensure that it holds active variables
    17833 */
    17834 if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE && nvars > 0 )
    17835 {
    17836 SCIP_VAR** consvars;
    17837 SCIP_Real* consvals;
    17838 SCIP_Real constant = 0.0;
    17839 int nconsvars;
    17840 int requiredsize;
    17841
    17842 nconsvars = nvars;
    17843 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, vars, nconsvars) );
    17844 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) );
    17845
    17846 /* get active variables for new constraint */
    17847 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize) );
    17848
    17849 /* if space was not enough we need to resize the buffers */
    17850 if( requiredsize > nconsvars )
    17851 {
    17852 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
    17853 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
    17854
    17855 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize) );
    17856 }
    17857 assert(requiredsize == nconsvars);
    17858
    17859 /* adjust sides and check that we do not subtract infinity values */
    17860 if( SCIPisInfinity(scip, REALABS(constant)) )
    17861 {
    17862 SCIPfreeBufferArray(scip, &consvals);
    17863 SCIPfreeBufferArray(scip, &consvars);
    17864 SCIPerrorMessage("while creating constraint <%s> inactive variables lead to an infinite constant\n", name);
    17865 SCIPABORT();
    17866 return SCIP_INVALIDDATA;
    17867 }
    17868 else
    17869 {
    17870 if( !SCIPisInfinity(scip, REALABS(lhs)) )
    17871 lhs -= constant;
    17872 if( !SCIPisInfinity(scip, REALABS(rhs)) )
    17873 rhs -= constant;
    17874
    17875 if( SCIPisInfinity(scip, -lhs) )
    17876 lhs = -SCIPinfinity(scip);
    17877 else if( SCIPisInfinity(scip, lhs) )
    17878 lhs = SCIPinfinity(scip);
    17879
    17880 if( SCIPisInfinity(scip, rhs) )
    17881 rhs = SCIPinfinity(scip);
    17882 else if( SCIPisInfinity(scip, -rhs) )
    17883 rhs = -SCIPinfinity(scip);
    17884 }
    17885
    17886 /* create constraint data */
    17887 SCIP_CALL( consdataCreate(scip, &consdata, nconsvars, consvars, consvals, lhs, rhs) );
    17888
    17889 SCIPfreeBufferArray(scip, &consvals);
    17890 SCIPfreeBufferArray(scip, &consvars);
    17891 }
    17892 else
    17893 {
    17894 /* create constraint data */
    17895 SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, vals, lhs, rhs) );
    17896 }
    17897 assert(consdata != NULL);
    17898
    17899#ifndef NDEBUG
    17900 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
    17901 if( check || enforce )
    17902 {
    17903 int n;
    17904 for(n = consdata->nvars - 1; n >= 0; --n )
    17905 assert(!SCIPvarIsRelaxationOnly(consdata->vars[n]));
    17906 }
    17907#endif
    17908
    17909 /* create constraint */
    17910 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
    17911 local, modifiable, dynamic, removable, stickingatnode) );
    17912
    17913 return SCIP_OKAY;
    17914}
    17915
    17916/** creates and captures a linear constraint
    17917 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
    17918 * method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
    17919 *
    17920 * @see SCIPcreateConsLinear() for information about the basic constraint flag configuration
    17921 *
    17922 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
    17923 */
    17925 SCIP* scip, /**< SCIP data structure */
    17926 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    17927 const char* name, /**< name of constraint */
    17928 int nvars, /**< number of nonzeros in the constraint */
    17929 SCIP_VAR** vars, /**< array with variables of constraint entries */
    17930 SCIP_Real* vals, /**< array with coefficients of constraint entries */
    17931 SCIP_Real lhs, /**< left hand side of constraint */
    17932 SCIP_Real rhs /**< right hand side of constraint */
    17933 )
    17934{
    17935 assert(scip != NULL);
    17936
    17937 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, vals, lhs, rhs,
    17939
    17940 return SCIP_OKAY;
    17941}
    17942
    17943/** creates by copying and captures a linear constraint */
    17945 SCIP* scip, /**< target SCIP data structure */
    17946 SCIP_CONS** cons, /**< pointer to store the created target constraint */
    17947 SCIP* sourcescip, /**< source SCIP data structure */
    17948 const char* name, /**< name of constraint */
    17949 int nvars, /**< number of variables in source variable array */
    17950 SCIP_VAR** sourcevars, /**< source variables of the linear constraints */
    17951 SCIP_Real* sourcecoefs, /**< coefficient array of the linear constraint, or NULL if all coefficients are one */
    17952 SCIP_Real lhs, /**< left hand side of the linear constraint */
    17953 SCIP_Real rhs, /**< right hand side of the linear constraint */
    17954 SCIP_HASHMAP* varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
    17955 * variables of the target SCIP */
    17956 SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
    17957 * target constraints */
    17958 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
    17959 SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
    17960 SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
    17961 SCIP_Bool check, /**< should the constraint be checked for feasibility? */
    17962 SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
    17963 SCIP_Bool local, /**< is constraint only valid locally? */
    17964 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
    17965 SCIP_Bool dynamic, /**< is constraint subject to aging? */
    17966 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
    17967 SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even
    17968 * if it may be moved to a more global node? */
    17969 SCIP_Bool global, /**< create a global or a local copy? */
    17970 SCIP_Bool* valid /**< pointer to store if the copying was valid */
    17971 )
    17972{
    17973 SCIP_VAR** vars;
    17974 SCIP_Real* coefs;
    17975
    17976 SCIP_Real constant;
    17977 int requiredsize;
    17978 int v;
    17979 SCIP_Bool success;
    17980
    17981 if( SCIPisGT(scip, lhs, rhs) )
    17982 {
    17983 *valid = FALSE;
    17984 return SCIP_OKAY;
    17985 }
    17986
    17987 (*valid) = TRUE;
    17988
    17989 if( nvars == 0 )
    17990 {
    17991 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, 0, NULL, NULL, lhs, rhs,
    17992 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
    17993 return SCIP_OKAY;
    17994 }
    17995
    17996 /* duplicate variable array */
    17997 SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, sourcevars, nvars) );
    17998
    17999 /* duplicate coefficient array */
    18000 if( sourcecoefs != NULL )
    18001 {
    18002 SCIP_CALL( SCIPduplicateBufferArray(scip, &coefs, sourcecoefs, nvars) );
    18003 }
    18004 else
    18005 {
    18006 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
    18007 for( v = 0; v < nvars; ++v )
    18008 coefs[v] = 1.0;
    18009 }
    18010
    18011 constant = 0.0;
    18012
    18013 /* transform source variable to active variables of the source SCIP since only these can be mapped to variables of
    18014 * the target SCIP
    18015 */
    18016 if( !SCIPvarIsOriginal(vars[0]) )
    18017 {
    18018 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize) );
    18019
    18020 if( requiredsize > nvars )
    18021 {
    18022 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
    18023 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requiredsize) );
    18024
    18025 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize) );
    18026 }
    18027 assert(requiredsize == nvars);
    18028 }
    18029 else
    18030 {
    18031 for( v = 0; v < nvars; ++v )
    18032 {
    18033 assert(SCIPvarIsOriginal(vars[v]));
    18034 SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &coefs[v], &constant) );
    18035 assert(vars[v] != NULL);
    18036 }
    18037 }
    18038
    18039 success = TRUE;
    18040 /* map variables of the source constraint to variables of the target SCIP */
    18041 for( v = 0; v < nvars && success; ++v )
    18042 {
    18043 SCIP_VAR* var;
    18044 var = vars[v];
    18045
    18046 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
    18047 assert(!SCIPvarIsRelaxationOnly(var) || (!check && !enforce));
    18048
    18049 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &vars[v], varmap, consmap, global, &success) );
    18050 assert(!(success) || vars[v] != NULL);
    18051 }
    18052
    18053 /* only create the target constraint, if all variables could be copied */
    18054 if( success )
    18055 {
    18056 if( !SCIPisInfinity(scip, -lhs) )
    18057 lhs -= constant;
    18058
    18059 if( !SCIPisInfinity(scip, rhs) )
    18060 rhs -= constant;
    18061
    18062 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
    18063 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
    18064 }
    18065 else
    18066 *valid = FALSE;
    18067
    18068 /* free buffer array */
    18069 SCIPfreeBufferArray(scip, &coefs);
    18070 SCIPfreeBufferArray(scip, &vars);
    18071
    18072 return SCIP_OKAY;
    18073}
    18074
    18075/** adds coefficient to linear constraint (if it is not zero) */
    18077 SCIP* scip, /**< SCIP data structure */
    18078 SCIP_CONS* cons, /**< constraint data */
    18079 SCIP_VAR* var, /**< variable of constraint entry */
    18080 SCIP_Real val /**< coefficient of constraint entry */
    18081 )
    18082{
    18083 assert(scip != NULL);
    18084 assert(cons != NULL);
    18085 assert(var != NULL);
    18086
    18088
    18089 /* terminate if coefficient is infinite */
    18090 assert(SCIPisFinite(val));
    18091 if( SCIPisInfinity(scip, REALABS(val)) )
    18092 {
    18093 SCIPerrorMessage("coefficient of variable <%s> in constraint <%s> is infinite,"
    18094 " consider adjusting the infinity threshold\n", SCIPvarGetName(var), SCIPconsGetName(cons));
    18095 SCIPABORT();
    18096 return SCIP_INVALIDDATA;
    18097 }
    18098
    18099 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
    18100 * constraint after presolving we have to ensure that it holds active variables
    18101 */
    18103 {
    18104 SCIP_CONSDATA* consdata;
    18105 SCIP_VAR** consvars;
    18106 SCIP_Real* consvals;
    18107 SCIP_Real constant = 0.0;
    18108 SCIP_Real rhs;
    18109 SCIP_Real lhs;
    18110 int nconsvars;
    18111 int requiredsize;
    18112 int v;
    18113
    18114 nconsvars = 1;
    18115 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
    18116 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
    18117 consvars[0] = var;
    18118 consvals[0] = val;
    18119
    18120 /* get active variables for new constraint */
    18121 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize) );
    18122
    18123 /* if space was not enough we need to resize the buffers */
    18124 if( requiredsize > nconsvars )
    18125 {
    18126 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
    18127 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
    18128
    18129 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize) );
    18130 }
    18131 assert(requiredsize == nconsvars);
    18132
    18133 consdata = SCIPconsGetData(cons);
    18134 assert(consdata != NULL);
    18135
    18136 lhs = consdata->lhs;
    18137 rhs = consdata->rhs;
    18138
    18139 /* adjust sides and check that we do not subtract infinity values */
    18140 /* constant is infinite */
    18141 if( SCIPisInfinity(scip, REALABS(constant)) )
    18142 {
    18143 if( constant < 0.0 )
    18144 {
    18145 if( SCIPisInfinity(scip, lhs) )
    18146 {
    18147 SCIPfreeBufferArray(scip, &consvals);
    18148 SCIPfreeBufferArray(scip, &consvars);
    18149
    18150 SCIPerrorMessage("adding variable <%s> leads to inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite left hand side of the constraint\n", SCIPvarGetName(var), SCIPconsGetName(cons));
    18151
    18152 SCIPABORT();
    18153 return SCIP_INVALIDDATA; /*lint !e527*/
    18154 }
    18155 if( SCIPisInfinity(scip, rhs) )
    18156 {
    18157 SCIPfreeBufferArray(scip, &consvals);
    18158 SCIPfreeBufferArray(scip, &consvars);
    18159
    18160 SCIPerrorMessage("adding variable <%s> leads to inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite right hand side of the constraint\n", SCIPvarGetName(var), SCIPconsGetName(cons));
    18161
    18162 SCIPABORT();
    18163 return SCIP_INVALIDDATA; /*lint !e527*/
    18164 }
    18165
    18166 lhs = -SCIPinfinity(scip);
    18167 rhs = -SCIPinfinity(scip);
    18168 }
    18169 else
    18170 {
    18171 if( SCIPisInfinity(scip, -lhs) )
    18172 {
    18173 SCIPfreeBufferArray(scip, &consvals);
    18174 SCIPfreeBufferArray(scip, &consvars);
    18175
    18176 SCIPerrorMessage("adding variable <%s> leads to inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite left hand side of the constraint\n", SCIPvarGetName(var), SCIPconsGetName(cons));
    18177
    18178 SCIPABORT();
    18179 return SCIP_INVALIDDATA; /*lint !e527*/
    18180 }
    18181 if( SCIPisInfinity(scip, -rhs) )
    18182 {
    18183 SCIPfreeBufferArray(scip, &consvals);
    18184 SCIPfreeBufferArray(scip, &consvars);
    18185
    18186 SCIPerrorMessage("adding variable <%s> leads to inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite right hand side of the constraint\n", SCIPvarGetName(var), SCIPconsGetName(cons));
    18187
    18188 SCIPABORT();
    18189 return SCIP_INVALIDDATA; /*lint !e527*/
    18190 }
    18191
    18192 lhs = SCIPinfinity(scip);
    18193 rhs = SCIPinfinity(scip);
    18194 }
    18195 }
    18196 /* constant is not infinite */
    18197 else
    18198 {
    18199 if( !SCIPisInfinity(scip, REALABS(lhs)) )
    18200 lhs -= constant;
    18201 if( !SCIPisInfinity(scip, REALABS(rhs)) )
    18202 rhs -= constant;
    18203
    18204 if( SCIPisInfinity(scip, -lhs) )
    18205 lhs = -SCIPinfinity(scip);
    18206 else if( SCIPisInfinity(scip, lhs) )
    18207 lhs = SCIPinfinity(scip);
    18208
    18209 if( SCIPisInfinity(scip, rhs) )
    18210 rhs = SCIPinfinity(scip);
    18211 else if( SCIPisInfinity(scip, -rhs) )
    18212 rhs = -SCIPinfinity(scip);
    18213 }
    18214
    18215 /* add all active variables to constraint */
    18216 for( v = nconsvars - 1; v >= 0; --v )
    18217 {
    18218 if( !SCIPisZero(scip, consvals[v]) )
    18219 {
    18220 SCIP_CALL( addCoef(scip, cons, consvars[v], consvals[v]) );
    18221 }
    18222 }
    18223
    18224 /* update left and right hand sides */
    18225 SCIP_CALL( chgLhs(scip, cons, lhs) );
    18226 SCIP_CALL( chgRhs(scip, cons, rhs) );
    18227
    18228 SCIPfreeBufferArray(scip, &consvals);
    18229 SCIPfreeBufferArray(scip, &consvars);
    18230 }
    18231 else if( !SCIPisZero(scip, val) )
    18232 {
    18233 SCIP_CALL( addCoef(scip, cons, var, val) );
    18234 }
    18235
    18236 return SCIP_OKAY;
    18237}
    18238
    18239/** changes coefficient of variable in linear constraint; deletes the variable if coefficient is zero; adds variable if
    18240 * not yet contained in the constraint
    18241 *
    18242 * @note This method may only be called during problem creation stage for an original constraint and variable.
    18243 *
    18244 * @note This method requires linear time to search for occurences of the variable in the constraint data.
    18245 */
    18247 SCIP* scip, /**< SCIP data structure */
    18248 SCIP_CONS* cons, /**< constraint data */
    18249 SCIP_VAR* var, /**< variable of constraint entry */
    18250 SCIP_Real val /**< new coefficient of constraint entry */
    18251 )
    18252{
    18253 SCIP_CONSDATA* consdata;
    18254 SCIP_VAR** vars;
    18255 SCIP_Bool found;
    18256 int i;
    18257
    18258 assert(scip != NULL);
    18259 assert(cons != NULL);
    18260 assert(var != NULL);
    18261
    18263
    18265 {
    18266 SCIPerrorMessage("method may only be called during problem creation stage for original constraints and variables\n");
    18267 return SCIP_INVALIDDATA;
    18268 }
    18269
    18270 consdata = SCIPconsGetData(cons);
    18271 assert(consdata != NULL);
    18272
    18273 vars = consdata->vars;
    18274 found = FALSE;
    18275 i = 0;
    18276 while( i < consdata->nvars )
    18277 {
    18278 if( vars[i] == var )
    18279 {
    18280 if( found || SCIPisZero(scip, val) )
    18281 {
    18282 SCIP_CALL( delCoefPos(scip, cons, i) );
    18283
    18284 /* decrease i by one since otherwise we would skip the coefficient which has been switched to position i */
    18285 i--;
    18286 }
    18287 else
    18288 {
    18289 SCIP_CALL( chgCoefPos(scip, cons, i, val) );
    18290 }
    18291 found = TRUE;
    18292 }
    18293 i++;
    18294 }
    18295
    18296 if( !found )
    18297 {
    18298 SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
    18299 }
    18300
    18301 return SCIP_OKAY;
    18302}
    18303
    18304/** deletes variable from linear constraint
    18305 *
    18306 * @note This method may only be called during problem creation stage for an original constraint and variable.
    18307 *
    18308 * @note This method requires linear time to search for occurences of the variable in the constraint data.
    18309 */
    18311 SCIP* scip, /**< SCIP data structure */
    18312 SCIP_CONS* cons, /**< constraint data */
    18313 SCIP_VAR* var /**< variable of constraint entry */
    18314 )
    18315{
    18316 assert(scip != NULL);
    18317 assert(cons != NULL);
    18318 assert(var != NULL);
    18319
    18320 SCIP_CALL( SCIPchgCoefLinear(scip, cons, var, 0.0) );
    18321
    18322 return SCIP_OKAY;
    18323}
    18324
    18325/** gets left hand side of linear constraint */
    18327 SCIP* scip, /**< SCIP data structure */
    18328 SCIP_CONS* cons /**< constraint data */
    18329 )
    18330{
    18331 SCIP_CONSDATA* consdata;
    18332
    18333 assert(scip != NULL);
    18334 assert(cons != NULL);
    18335
    18337
    18338 consdata = SCIPconsGetData(cons);
    18339 assert(consdata != NULL);
    18340
    18341 return consdata->lhs;
    18342}
    18343
    18344/** gets right hand side of linear constraint */
    18346 SCIP* scip, /**< SCIP data structure */
    18347 SCIP_CONS* cons /**< constraint data */
    18348 )
    18349{
    18350 SCIP_CONSDATA* consdata;
    18351
    18352 assert(scip != NULL);
    18353 assert(cons != NULL);
    18354
    18356
    18357 consdata = SCIPconsGetData(cons);
    18358 assert(consdata != NULL);
    18359
    18360 return consdata->rhs;
    18361}
    18362
    18363/** changes left hand side of linear constraint */
    18365 SCIP* scip, /**< SCIP data structure */
    18366 SCIP_CONS* cons, /**< constraint data */
    18367 SCIP_Real lhs /**< new left hand side */
    18368 )
    18369{
    18370 assert(scip != NULL);
    18371 assert(cons != NULL);
    18372
    18374
    18375 SCIP_CALL( chgLhs(scip, cons, lhs) );
    18376
    18377 return SCIP_OKAY;
    18378}
    18379
    18380/** changes right hand side of linear constraint */
    18382 SCIP* scip, /**< SCIP data structure */
    18383 SCIP_CONS* cons, /**< constraint data */
    18384 SCIP_Real rhs /**< new right hand side */
    18385 )
    18386{
    18387 assert(scip != NULL);
    18388 assert(cons != NULL);
    18389
    18391
    18392 SCIP_CALL( chgRhs(scip, cons, rhs) );
    18393
    18394 return SCIP_OKAY;
    18395}
    18396
    18397/** gets the number of variables in the linear constraint */
    18399 SCIP* scip, /**< SCIP data structure */
    18400 SCIP_CONS* cons /**< constraint data */
    18401 )
    18402{
    18403 SCIP_CONSDATA* consdata;
    18404
    18405 assert(scip != NULL);
    18406 assert(cons != NULL);
    18407
    18409
    18410 consdata = SCIPconsGetData(cons);
    18411 assert(consdata != NULL);
    18412
    18413 return consdata->nvars;
    18414}
    18415
    18416/** gets the array of variables in the linear constraint; the user must not modify this array! */
    18418 SCIP* scip, /**< SCIP data structure */
    18419 SCIP_CONS* cons /**< constraint data */
    18420 )
    18421{
    18422 SCIP_CONSDATA* consdata;
    18423
    18424 assert(scip != NULL);
    18425 assert(cons != NULL);
    18426
    18428
    18429 consdata = SCIPconsGetData(cons);
    18430 assert(consdata != NULL);
    18431
    18432 return consdata->vars;
    18433}
    18434
    18435/** gets the array of coefficient values in the linear constraint; the user must not modify this array! */
    18437 SCIP* scip, /**< SCIP data structure */
    18438 SCIP_CONS* cons /**< constraint data */
    18439 )
    18440{
    18441 SCIP_CONSDATA* consdata;
    18442
    18443 assert(scip != NULL);
    18444 assert(cons != NULL);
    18445
    18447
    18448 consdata = SCIPconsGetData(cons);
    18449 assert(consdata != NULL);
    18450
    18451 return consdata->vals;
    18452}
    18453
    18454/** gets the activity of the linear constraint in the given solution
    18455 *
    18456 * @note if the solution contains values at infinity, this method will return SCIP_INVALID in case the activity
    18457 * comprises positive and negative infinity contributions
    18458 */
    18460 SCIP* scip, /**< SCIP data structure */
    18461 SCIP_CONS* cons, /**< constraint data */
    18462 SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
    18463 )
    18464{
    18465 SCIP_CONSDATA* consdata;
    18466
    18467 assert(scip != NULL);
    18468 assert(cons != NULL);
    18469
    18471
    18472 consdata = SCIPconsGetData(cons);
    18473 assert(consdata != NULL);
    18474
    18475 if( consdata->row != NULL )
    18476 return SCIPgetRowSolActivity(scip, consdata->row, sol);
    18477 else
    18478 return consdataGetActivity(scip, consdata, sol);
    18479}
    18480
    18481/** gets the feasibility of the linear constraint in the given solution */
    18483 SCIP* scip, /**< SCIP data structure */
    18484 SCIP_CONS* cons, /**< constraint data */
    18485 SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
    18486 )
    18487{
    18488 SCIP_CONSDATA* consdata;
    18489
    18490 assert(scip != NULL);
    18491 assert(cons != NULL);
    18492
    18494
    18495 consdata = SCIPconsGetData(cons);
    18496 assert(consdata != NULL);
    18497
    18498 if( consdata->row != NULL )
    18499 return SCIPgetRowSolFeasibility(scip, consdata->row, sol);
    18500 else
    18501 return consdataGetFeasibility(scip, consdata, sol);
    18502}
    18503
    18504/** gets the dual solution of the linear constraint in the current LP */
    18506 SCIP* scip, /**< SCIP data structure */
    18507 SCIP_CONS* cons /**< constraint data */
    18508 )
    18509{
    18510 SCIP_CONSDATA* consdata;
    18511
    18512 assert(scip != NULL);
    18513 assert(cons != NULL);
    18514 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
    18515
    18517
    18518 consdata = SCIPconsGetData(cons);
    18519 assert(consdata != NULL);
    18520
    18521 if( consdata->row != NULL )
    18522 return SCIProwGetDualsol(consdata->row);
    18523 else
    18524 return 0.0;
    18525}
    18526
    18527/** gets the dual Farkas value of the linear constraint in the current infeasible LP */
    18529 SCIP* scip, /**< SCIP data structure */
    18530 SCIP_CONS* cons /**< constraint data */
    18531 )
    18532{
    18533 SCIP_CONSDATA* consdata;
    18534
    18535 assert(scip != NULL);
    18536 assert(cons != NULL);
    18537 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
    18538
    18540
    18541 consdata = SCIPconsGetData(cons);
    18542 assert(consdata != NULL);
    18543
    18544 if( consdata->row != NULL )
    18545 return SCIProwGetDualfarkas(consdata->row);
    18546 else
    18547 return 0.0;
    18548}
    18549
    18550/** returns the linear relaxation of the given linear constraint; may return NULL if no LP row was yet created;
    18551 * the user must not modify the row!
    18552 */
    18554 SCIP* scip, /**< SCIP data structure */
    18555 SCIP_CONS* cons /**< constraint data */
    18556 )
    18557{
    18558 SCIP_CONSDATA* consdata;
    18559
    18560 assert(scip != NULL);
    18561 assert(cons != NULL);
    18562
    18564
    18565 consdata = SCIPconsGetData(cons);
    18566 assert(consdata != NULL);
    18567
    18568 return consdata->row;
    18569}
    18570
    18571/** creates and returns the row of the given linear constraint */
    18573 SCIP* scip, /**< SCIP data structure */
    18574 SCIP_CONS* cons /**< constraint data */
    18575 )
    18576{
    18577 SCIP_CONSDATA* consdata;
    18578
    18579 assert(scip != NULL);
    18580 assert(cons != NULL);
    18581
    18583
    18584 consdata = SCIPconsGetData(cons);
    18585 assert(consdata != NULL);
    18586
    18587 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
    18589
    18590 SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) ) ;
    18591
    18592 return SCIP_OKAY;
    18593}
    18594
    18595/** tries to automatically convert a linear constraint into a more specific and more specialized constraint */
    18597 SCIP* scip, /**< SCIP data structure */
    18598 SCIP_CONS* cons, /**< source constraint to try to convert */
    18599 SCIP_CONS** upgdcons /**< pointer to store upgraded constraint, or NULL if not successful */
    18600 )
    18601{
    18602 SCIP_CONSHDLR* conshdlr;
    18603 SCIP_CONSHDLRDATA* conshdlrdata;
    18604 SCIP_CONSDATA* consdata;
    18605 SCIP_VAR* var;
    18606 SCIP_Real val;
    18607 SCIP_Real lb;
    18608 SCIP_Real ub;
    18609 SCIP_Real poscoeffsum;
    18610 SCIP_Real negcoeffsum;
    18611 SCIP_Bool infeasible;
    18612 SCIP_Bool integral;
    18613 int nchgsides = 0;
    18614 int nposbin;
    18615 int nnegbin;
    18616 int nposint;
    18617 int nnegint;
    18618 int nposimpl;
    18619 int nnegimpl;
    18620 int nposimplbin;
    18621 int nnegimplbin;
    18622 int nposcont;
    18623 int nnegcont;
    18624 int ncoeffspone;
    18625 int ncoeffsnone;
    18626 int ncoeffspint;
    18627 int ncoeffsnint;
    18628 int ncoeffspfrac;
    18629 int ncoeffsnfrac;
    18630 int i;
    18631
    18632 assert(scip != NULL);
    18633 assert(cons != NULL);
    18634 assert(upgdcons != NULL);
    18635
    18636 *upgdcons = NULL;
    18637
    18638 /* we cannot upgrade a modifiable linear constraint, since we don't know what additional coefficients to expect */
    18639 if( SCIPconsIsModifiable(cons) )
    18640 return SCIP_OKAY;
    18641
    18642 /* check for upgradability */
    18643 if( SCIPconsGetNUpgradeLocks(cons) > 0 )
    18644 return SCIP_OKAY;
    18645
    18646 /* get the constraint handler and check, if it's really a linear constraint */
    18647 conshdlr = SCIPconsGetHdlr(cons);
    18648
    18650
    18651 /* get constraint handler data and constraint data */
    18652 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    18653 assert(conshdlrdata != NULL);
    18654 consdata = SCIPconsGetData(cons);
    18655 assert(consdata != NULL);
    18656
    18657 /* check, if the constraint was already upgraded and will be deleted anyway after preprocessing */
    18658 if( consdata->upgraded )
    18659 return SCIP_OKAY;
    18660
    18661 /* check, if the constraint is already stored as LP row */
    18662 if( consdata->row != NULL )
    18663 {
    18664 if( SCIProwIsInLP(consdata->row) )
    18665 {
    18666 SCIPerrorMessage("cannot upgrade linear constraint that is already stored as row in the LP\n");
    18667 return SCIP_INVALIDDATA;
    18668 }
    18669 else
    18670 {
    18671 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
    18672 }
    18673 }
    18674
    18675 SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
    18676
    18677 /* normalizeCons() can only detect infeasibility when scaling with the gcd. in that case, the scaling was
    18678 * skipped and we hope that the infeasibility gets detected later again.
    18679 *
    18680 * TODO: do we want to try to upgrade the constraint anyway?
    18681 *
    18682 * TODO: this needs to be fixed on master by changing the API and passing a pointer to whether the constraint is
    18683 * proven to be infeasible.
    18684 */
    18685 if( infeasible ) /*lint !e774*/
    18686 return SCIP_OKAY;
    18687
    18688 /* tighten sides */
    18689 SCIP_CALL( tightenSides(scip, cons, &nchgsides, &infeasible) );
    18690
    18691 if( infeasible ) /*lint !e774*/
    18692 return SCIP_OKAY;
    18693
    18694 /*
    18695 * calculate some statistics on linear constraint
    18696 */
    18697
    18698 nposbin = 0;
    18699 nnegbin = 0;
    18700 nposint = 0;
    18701 nnegint = 0;
    18702 nposimpl = 0;
    18703 nnegimpl = 0;
    18704 nposimplbin = 0;
    18705 nnegimplbin = 0;
    18706 nposcont = 0;
    18707 nnegcont = 0;
    18708 ncoeffspone = 0;
    18709 ncoeffsnone = 0;
    18710 ncoeffspint = 0;
    18711 ncoeffsnint = 0;
    18712 ncoeffspfrac = 0;
    18713 ncoeffsnfrac = 0;
    18714 integral = TRUE;
    18715 poscoeffsum = 0.0;
    18716 negcoeffsum = 0.0;
    18717
    18718 for( i = 0; i < consdata->nvars; ++i )
    18719 {
    18720 var = consdata->vars[i];
    18721 val = consdata->vals[i];
    18722 lb = SCIPvarGetLbLocal(var);
    18723 ub = SCIPvarGetUbLocal(var);
    18724 assert(!SCIPisZero(scip, val));
    18725
    18726 if( SCIPvarIsImpliedIntegral(var) )
    18727 {
    18728 if( SCIPvarIsBinary(var) )
    18729 {
    18730 if( val >= 0.0 )
    18731 ++nposimplbin;
    18732 else
    18733 ++nnegimplbin;
    18734 }
    18735 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
    18736 integral = integral && SCIPisIntegral(scip, val);
    18737 if( val >= 0.0 )
    18738 ++nposimpl;
    18739 else
    18740 ++nnegimpl;
    18741 }
    18742 else
    18743 {
    18744 switch( SCIPvarGetType(var) )
    18745 {
    18747 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
    18748 integral = integral && SCIPisIntegral(scip, val);
    18749 if( val >= 0.0 )
    18750 ++nposbin;
    18751 else
    18752 ++nnegbin;
    18753 break;
    18755 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
    18756 integral = integral && SCIPisIntegral(scip, val);
    18757 if( val >= 0.0 )
    18758 ++nposint;
    18759 else
    18760 ++nnegint;
    18761 break;
    18763 integral = integral && SCIPisEQ(scip, lb, ub) && SCIPisIntegral(scip, val * lb);
    18764 if( val >= 0.0 )
    18765 ++nposcont;
    18766 else
    18767 ++nnegcont;
    18768 break;
    18769 default:
    18770 SCIPerrorMessage("unknown variable type\n");
    18771 return SCIP_INVALIDDATA;
    18772 } /*lint !e788*/
    18773 }
    18774
    18775 if( SCIPisEQ(scip, val, 1.0) )
    18776 ncoeffspone++;
    18777 else if( SCIPisEQ(scip, val, -1.0) )
    18778 ncoeffsnone++;
    18779 else if( SCIPisIntegral(scip, val) )
    18780 {
    18781 if( SCIPisPositive(scip, val) )
    18782 ncoeffspint++;
    18783 else
    18784 ncoeffsnint++;
    18785 }
    18786 else
    18787 {
    18788 if( SCIPisPositive(scip, val) )
    18789 ncoeffspfrac++;
    18790 else
    18791 ncoeffsnfrac++;
    18792 }
    18793 if( SCIPisPositive(scip, val) )
    18794 poscoeffsum += val;
    18795 else
    18796 negcoeffsum += val;
    18797 }
    18798
    18799 /*
    18800 * call the upgrading methods
    18801 */
    18802
    18803 SCIPdebugMsg(scip, "upgrading linear constraint <%s> (%d upgrade methods):\n",
    18804 SCIPconsGetName(cons), conshdlrdata->nlinconsupgrades);
    18805 SCIPdebugMsg(scip, " +bin=%d -bin=%d +int=%d -int=%d +impl=%d -impl=%d +cont=%d -cont=%d +1=%d -1=%d +I=%d -I=%d +F=%d -F=%d possum=%.15g negsum=%.15g integral=%u\n",
    18806 nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposcont, nnegcont,
    18807 ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
    18808 poscoeffsum, negcoeffsum, integral);
    18809
    18810 /* try all upgrading methods in priority order in case the upgrading step is enable */
    18811 for( i = 0; i < conshdlrdata->nlinconsupgrades && *upgdcons == NULL; ++i )
    18812 {
    18813 if( conshdlrdata->linconsupgrades[i]->active )
    18814 {
    18815 SCIP_CALL( conshdlrdata->linconsupgrades[i]->linconsupgd(scip, cons, consdata->nvars,
    18816 consdata->vars, consdata->vals, consdata->lhs, consdata->rhs,
    18817 nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposimplbin, nnegimplbin, nposcont, nnegcont,
    18818 ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
    18819 poscoeffsum, negcoeffsum, integral,
    18820 upgdcons) );
    18821 }
    18822 }
    18823
    18824#ifdef SCIP_DEBUG
    18825 if( *upgdcons != NULL )
    18826 {
    18828 SCIPdebugMsg(scip, " -> upgraded to constraint type <%s>\n", SCIPconshdlrGetName(SCIPconsGetHdlr(*upgdcons)));
    18829 SCIPdebugPrintCons(scip, *upgdcons, NULL);
    18830 }
    18831#endif
    18832
    18833 return SCIP_OKAY; /*lint !e438*/
    18834}
    18835
    18836/** cleans up (multi-)aggregations and fixings from linear constraints */
    18838 SCIP* scip, /**< SCIP data structure */
    18839 SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
    18840 SCIP_Bool* infeasible, /**< pointer to return whether the problem was detected to be infeasible */
    18841 int* ndelconss /**< pointer to count number of deleted constraints */
    18842 )
    18843{
    18844 SCIP_CONSHDLR* conshdlr;
    18845 SCIP_CONS** conss;
    18846 int nconss;
    18847 int i;
    18848
    18849 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
    18850 if( conshdlr == NULL )
    18851 return SCIP_OKAY;
    18852
    18853 assert(infeasible != NULL);
    18854 *infeasible = FALSE;
    18855
    18856 nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr);
    18857 conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);
    18858
    18859 /* loop backwards since then deleted constraints do not interfere with the loop */
    18860 for( i = nconss - 1; i >= 0; --i )
    18861 {
    18862 SCIP_CALL( applyFixings(scip, conss[i], infeasible) );
    18863
    18864 if( *infeasible )
    18865 break;
    18866
    18867 if( SCIPconsGetData(conss[i])->nvars >= 1 )
    18868 continue;
    18869
    18870 SCIP_CALL( SCIPdelCons(scip, conss[i]) );
    18871 ++(*ndelconss);
    18872 }
    18873
    18874 return SCIP_OKAY;
    18875}
    static long bound
    SCIP_VAR * w
    Definition: circlepacking.c:67
    SCIP_VAR * a
    Definition: circlepacking.c:66
    SCIP_VAR ** b
    Definition: circlepacking.c:65
    SCIP_VAR ** x
    Definition: circlepacking.c:63
    enum Proprule PROPRULE
    Definition: cons_and.c:172
    Proprule
    Definition: cons_and.c:165
    struct InferInfo INFERINFO
    Constraint handler for knapsack constraints of the form , x binary and .
    #define MAX_CLIQUE_NONZEROS_PER_CONS
    Definition: cons_linear.c:7835
    enum Proprule PROPRULE
    Definition: cons_linear.c:354
    static SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
    static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
    Definition: cons_linear.c:3662
    #define DEFAULT_AGGREGATEVARIABLES
    Definition: cons_linear.c:141
    static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file)
    Definition: cons_linear.c:1097
    #define DEFAULT_NMINCOMPARISONS
    Definition: cons_linear.c:126
    #define DEFAULT_MULTAGGRREMOVE
    Definition: cons_linear.c:160
    #define DEFAULT_DUALPRESOLVING
    Definition: cons_linear.c:143
    #define DEFAULT_EXTRACTCLIQUES
    Definition: cons_linear.c:164
    static void permSortConsdata(SCIP_CONSDATA *consdata, int *perm, int nvars)
    Definition: cons_linear.c:3261
    #define CONSHDLR_NEEDSCONS
    Definition: cons_linear.c:107
    static void consdataRecomputeMaxActivityDelta(SCIP *scip, SCIP_CONSDATA *consdata)
    Definition: cons_linear.c:1542
    #define CONSHDLR_SEPAFREQ
    Definition: cons_linear.c:100
    static SCIP_RETCODE checkCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool checklprows, SCIP_Bool checkrelmaxabs, SCIP_Bool *violated)
    Definition: cons_linear.c:7158
    static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff)
    Definition: cons_linear.c:7442
    #define CONFLICTHDLR_PRIORITY
    Definition: cons_linear.c:117
    static void consdataGetReliableResidualActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *cancelvar, SCIP_Real *resactivity, SCIP_Bool isminresact, SCIP_Bool useglobalbounds)
    Definition: cons_linear.c:2580
    static SCIP_DECL_EVENTEXEC(eventExecLinear)
    static SCIP_RETCODE convertEquality(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss, int *nchgvartypes)
    static SCIP_Bool checkEqualObjective(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real *scale, SCIP_Real *offset)
    #define CONFLICTHDLR_NAME
    Definition: cons_linear.c:115
    #define MAXDNOM
    Definition: cons_linear.c:166
    static SCIP_RETCODE conshdlrdataIncludeUpgrade(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_LINCONSUPGRADE *linconsupgrade)
    Definition: cons_linear.c:618
    static SCIP_RETCODE extractCliques(SCIP *scip, SCIP_CONS *cons, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, int *nfixedvars, int *nchgbds, SCIP_Bool *cutoff)
    Definition: cons_linear.c:7902
    static SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
    #define CONSHDLR_CHECKPRIORITY
    Definition: cons_linear.c:99
    #define CONSHDLR_DESC
    Definition: cons_linear.c:96
    static SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
    static SCIP_DECL_CONSGETVARS(consGetVarsLinear)
    static SCIP_RETCODE createRow(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_linear.c:7418
    static SCIP_DECL_SORTINDCOMP(consdataCompVar)
    Definition: cons_linear.c:3152
    static int getVarWeight(SCIP_VAR *var)
    static SCIP_RETCODE convertBinaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss)
    Definition: cons_linear.c:9461
    static void consdataRecomputeMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
    Definition: cons_linear.c:1307
    static SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
    static SCIP_DECL_CONSPRESOL(consPresolLinear)
    static SCIP_RETCODE addConflictFixedVars(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, int inferpos)
    Definition: cons_linear.c:4981
    static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
    static SCIP_DECL_CONSFREE(consFreeLinear)
    #define DEFAULT_DETECTCUTOFFBOUND
    Definition: cons_linear.c:147
    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)
    Definition: cons_linear.c:5311
    static SCIP_RETCODE fullDualPresolve(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_Bool *cutoff, int *nchgbds, int *nchgvartypes)
    static SCIP_RETCODE convertLongEquality(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_CONS *cons, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss, int *nchgvartypes)
    Definition: cons_linear.c:9573
    static SCIP_DECL_CONSINITLP(consInitlpLinear)
    #define CONSHDLR_PROP_TIMING
    Definition: cons_linear.c:110
    static SCIP_Real consdataComputePseudoActivity(SCIP *scip, SCIP_CONSDATA *consdata)
    Definition: cons_linear.c:1254
    static SCIP_DECL_CONSPARSE(consParseLinear)
    static SCIP_RETCODE conshdlrdataEnsureLinconsupgradesSize(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, int num)
    Definition: cons_linear.c:447
    static SCIP_DECL_CONSENFOLP(consEnfolpLinear)
    static SCIP_RETCODE retrieveParallelConstraints(SCIP_HASHTABLE *hashtable, SCIP_CONS **querycons, SCIP_CONS **parallelconss, int *nparallelconss)
    #define CONFLICTHDLR_DESC
    Definition: cons_linear.c:116
    static void conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
    Definition: cons_linear.c:566
    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)
    Definition: cons_linear.c:650
    static void consdataRecomputeGlbMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
    Definition: cons_linear.c:1361
    static SCIP_DECL_CONSDELVARS(consDelvarsLinear)
    static void consdataUpdateActivitiesUb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldub, SCIP_Real newub, SCIP_Real val, SCIP_Bool checkreliability)
    Definition: cons_linear.c:2021
    static SCIP_RETCODE tightenSides(SCIP *scip, SCIP_CONS *cons, int *nchgsides, SCIP_Bool *infeasible)
    Definition: cons_linear.c:8875
    static void consdataUpdateActivitiesGlbLb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real val, SCIP_Bool checkreliability)
    Definition: cons_linear.c:2046
    static void consdataUpdateActivitiesLb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real val, SCIP_Bool checkreliability)
    Definition: cons_linear.c:1996
    #define CONSHDLR_MAXPREROUNDS
    Definition: cons_linear.c:104
    static SCIP_Bool conshdlrdataHasUpgrade(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_DECL_LINCONSUPGD((*linconsupgd)), const char *conshdlrname)
    Definition: cons_linear.c:588
    static SCIP_RETCODE chgCoefPos(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Real newval)
    Definition: cons_linear.c:3908
    static void consdataRecomputeMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
    Definition: cons_linear.c:1334
    static SCIP_RETCODE linconsupgradeCreate(SCIP *scip, SCIP_LINCONSUPGRADE **linconsupgrade, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority)
    Definition: cons_linear.c:507
    #define DEFAULT_PRESOLPAIRWISE
    Definition: cons_linear.c:124
    #define DEFAULT_MAXAGGRNORMSCALE
    Definition: cons_linear.c:133
    static SCIP_RETCODE performVarDeletions(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss)
    Definition: cons_linear.c:4091
    #define checkMaxActivityDelta(scip, consdata)
    Definition: cons_linear.c:1537
    static SCIP_DECL_CONSTRANS(consTransLinear)
    #define CONSHDLR_SEPAPRIORITY
    Definition: cons_linear.c:97
    static SCIP_Bool isFiniteNonnegativeIntegral(SCIP *scip, SCIP_Real x)
    #define DEFAULT_SINGLETONSTUFFING
    Definition: cons_linear.c:144
    #define DEFAULT_MAXROUNDSROOT
    Definition: cons_linear.c:121
    static void consdataUpdateSignatures(SCIP_CONSDATA *consdata, int pos)
    Definition: cons_linear.c:3107
    #define MINVALRECOMP
    Definition: cons_linear.c:176
    #define DEFAULT_MAXCARDBOUNDDIST
    Definition: cons_linear.c:137
    #define DEFAULT_MAXEASYACTIVITYDELTA
    Definition: cons_linear.c:135
    static SCIP_DECL_CONSEXIT(consExitLinear)
    static SCIP_RETCODE scaleCons(SCIP *scip, SCIP_CONS *cons, SCIP_Real scalar)
    Definition: cons_linear.c:3998
    static int inferInfoGetPos(INFERINFO inferinfo)
    Definition: cons_linear.c:404
    static SCIP_DECL_CONSPRINT(consPrintLinear)
    static SCIP_RETCODE detectRedundantConstraints(SCIP *scip, BMS_BLKMEM *blkmem, SCIP_CONS **conss, int nconss, int *firstchange, SCIP_Bool *cutoff, int *ndelconss, int *nchgsides)
    #define DEFAULT_CHECKRELMAXABS
    Definition: cons_linear.c:131
    #define DEFAULT_MAXDUALMULTAGGRQUOT
    Definition: cons_linear.c:163
    static void linconsupgradeFree(SCIP *scip, SCIP_LINCONSUPGRADE **linconsupgrade)
    Definition: cons_linear.c:528
    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_DECL_CONSENFOPS(consEnfopsLinear)
    static SCIP_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons, SCIP_Bool reasonisrhs)
    Definition: cons_linear.c:5190
    static SCIP_RETCODE rangedRowPropagation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *nchgbds, int *naddconss)
    Definition: cons_linear.c:5715
    static INFERINFO intToInferInfo(int i)
    Definition: cons_linear.c:373
    static SCIP_RETCODE mergeMultiples(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_linear.c:4471
    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)
    Definition: cons_linear.c:7531
    static SCIP_RETCODE addSymmetryInformation(SCIP *scip, SYM_SYMTYPE symtype, SCIP_CONS *cons, SYM_GRAPH *graph, SCIP_Bool *success)
    static void consdataGetActivityBounds(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Bool goodrelax, SCIP_Real *minactivity, SCIP_Real *maxactivity, SCIP_Bool *ismintight, SCIP_Bool *ismaxtight, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
    Definition: cons_linear.c:2533
    static void consdataCheckNonbinvar(SCIP_CONSDATA *consdata)
    Definition: cons_linear.c:1468
    static SCIP_RETCODE chgLhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
    Definition: cons_linear.c:3404
    static SCIP_DECL_CONSEXITSOL(consExitsolLinear)
    #define DEFAULT_SORTVARS
    Definition: cons_linear.c:129
    #define DEFAULT_MAXMULTAGGRQUOT
    Definition: cons_linear.c:162
    static void consdataUpdateActivitiesGlbUb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldub, SCIP_Real newub, SCIP_Real val, SCIP_Bool checkreliability)
    Definition: cons_linear.c:2069
    static SCIP_RETCODE consCatchEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
    Definition: cons_linear.c:717
    static void consdataCalcMinAbsval(SCIP_CONSDATA *consdata)
    Definition: cons_linear.c:1439
    static SCIP_RETCODE addConflictBounds(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, int inferpos, SCIP_Bool reasonisrhs)
    Definition: cons_linear.c:4799
    #define MAXCONSPRESOLROUNDS
    static SCIP_RETCODE consdataEnsureVarsSize(SCIP *scip, SCIP_CONSDATA *consdata, int num)
    Definition: cons_linear.c:472
    #define MAXACTVAL
    Definition: cons_linear.c:171
    #define NONLINCONSUPGD_PRIORITY
    Definition: cons_linear.c:179
    #define DEFAULT_MAXSEPACUTSROOT
    Definition: cons_linear.c:123
    @ PROPRULE_1_RANGEDROW
    Definition: cons_linear.c:350
    @ PROPRULE_1_LHS
    Definition: cons_linear.c:348
    @ PROPRULE_INVALID
    Definition: cons_linear.c:352
    @ PROPRULE_1_RHS
    Definition: cons_linear.c:346
    static SCIP_RETCODE tightenBounds(SCIP *scip, SCIP_CONS *cons, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, SCIP_Bool *cutoff, int *nchgbds)
    Definition: cons_linear.c:6980
    static void consdataCalcMaxAbsval(SCIP_CONSDATA *consdata)
    Definition: cons_linear.c:1415
    #define DEFAULT_RANGEDROWPROPAGATION
    Definition: cons_linear.c:155
    static SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphLinear)
    static SCIP_DECL_CONSEXITPRE(consExitpreLinear)
    static SCIP_RETCODE consDropAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
    Definition: cons_linear.c:824
    static SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
    #define DEFAULT_PRESOLUSEHASHING
    Definition: cons_linear.c:125
    static SCIP_Real consdataGetActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
    Definition: cons_linear.c:3020
    static SCIP_RETCODE consdataTightenCoefs(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides)
    Definition: cons_linear.c:8994
    static SCIP_RETCODE normalizeCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
    Definition: cons_linear.c:4151
    static SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphLinear)
    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)
    Definition: cons_linear.c:683
    static void consdataCalcSignatures(SCIP_CONSDATA *consdata)
    Definition: cons_linear.c:3132
    static SCIP_RETCODE addConflictReasonVars(SCIP *scip, SCIP_VAR **vars, int nvars, SCIP_VAR *var, SCIP_Real bound)
    Definition: cons_linear.c:5046
    static SCIP_DECL_CONSINIT(consInitLinear)
    #define DEFAULT_RANGEDROWFREQ
    Definition: cons_linear.c:158
    static SCIP_DECL_CONSDELETE(consDeleteLinear)
    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)
    Definition: cons_linear.c:2168
    #define DEFAULT_RANGEDROWARTCONS
    Definition: cons_linear.c:156
    static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, int pos)
    Definition: cons_linear.c:3795
    #define MAXSCALEDCOEFINTEGER
    Definition: cons_linear.c:168
    static void consdataUpdateAddCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
    Definition: cons_linear.c:2092
    static void getMinActivity(SCIP *scip, SCIP_CONSDATA *consdata, int posinf, int neginf, int poshuge, int neghuge, SCIP_Real delta, SCIP_Bool global, SCIP_Bool goodrelax, SCIP_Real *minactivity, SCIP_Bool *istight, SCIP_Bool *issettoinfinity)
    Definition: cons_linear.c:2345
    static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
    Definition: cons_linear.c:855
    static SCIP_DECL_CONSACTIVE(consActiveLinear)
    #define BINWEIGHT
    static SCIP_RETCODE chgRhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
    Definition: cons_linear.c:3532
    static SCIP_DECL_CONSCHECK(consCheckLinear)
    #define DEFAULT_SIMPLIFYINEQUALITIES
    Definition: cons_linear.c:142
    static SCIP_DECL_CONSSEPALP(consSepalpLinear)
    #define CONSHDLR_PROPFREQ
    Definition: cons_linear.c:101
    static SCIP_RETCODE tightenVarBoundsEasy(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
    Definition: cons_linear.c:5380
    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)
    Definition: cons_linear.c:1604
    static unsigned int getParallelConsKey(SCIP_CONS *cons)
    #define CONTWEIGHT
    static SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
    static SCIP_RETCODE fixVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars)
    Definition: cons_linear.c:7767
    #define CONSHDLR_PRESOLTIMING
    Definition: cons_linear.c:109
    #define DEFAULT_DETECTPARTIALOBJECTIVE
    Definition: cons_linear.c:153
    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)
    Definition: cons_linear.c:1056
    static SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
    #define DEFAULT_MAXSEPACUTS
    Definition: cons_linear.c:122
    static void consdataGetActivityResiduals(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool goodrelax, SCIP_Real *minresactivity, SCIP_Real *maxresactivity, SCIP_Bool *ismintight, SCIP_Bool *ismaxtight, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
    Definition: cons_linear.c:2661
    static SCIP_Real consdataGetMaxAbsval(SCIP_CONSDATA *consdata)
    Definition: cons_linear.c:2249
    static SCIP_DECL_CONSINITSOL(consInitsolLinear)
    static SCIP_DECL_CONSRESPROP(consRespropLinear)
    static SCIP_RETCODE addNlrow(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_linear.c:7495
    static SCIP_RETCODE consPrintConsSol(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, FILE *file)
    Definition: cons_linear.c:1136
    #define CONSHDLR_EAGERFREQ
    Definition: cons_linear.c:102
    static void getMaxActivity(SCIP *scip, SCIP_CONSDATA *consdata, int posinf, int neginf, int poshuge, int neghuge, SCIP_Real delta, SCIP_Bool global, SCIP_Bool goodrelax, SCIP_Real *maxactivity, SCIP_Bool *istight, SCIP_Bool *issettoinfinity)
    Definition: cons_linear.c:2440
    #define DEFAULT_TIGHTENBOUNDSFREQ
    Definition: cons_linear.c:119
    static void getNewSidesAfterAggregation(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *slackvar, SCIP_Real slackcoef, SCIP_Real *newlhs, SCIP_Real *newrhs)
    Definition: cons_linear.c:9519
    static SCIP_RETCODE convertUnaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *ndelconss)
    Definition: cons_linear.c:9405
    static SCIP_DECL_CONSSEPASOL(consSepasolLinear)
    static void consdataUpdateChgCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldval, SCIP_Real newval, SCIP_Bool checkreliability)
    Definition: cons_linear.c:2233
    #define EVENTHDLR_DESC
    Definition: cons_linear.c:113
    static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
    Definition: cons_linear.c:542
    static void consdataRecomputeGlbMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
    Definition: cons_linear.c:1388
    static SCIP_DECL_CONSPROP(consPropLinear)
    static SCIP_RETCODE applyFixings(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
    Definition: cons_linear.c:4534
    static SCIP_DECL_CONSLOCK(consLockLinear)
    static void consdataCalcActivities(SCIP *scip, SCIP_CONSDATA *consdata)
    Definition: cons_linear.c:2283
    #define DEFAULT_MAXROUNDS
    Definition: cons_linear.c:120
    static void consdataGetGlbActivityResiduals(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool goodrelax, SCIP_Real *minresactivity, SCIP_Real *maxresactivity, SCIP_Bool *ismintight, SCIP_Bool *ismaxtight, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
    Definition: cons_linear.c:2870
    #define CONSHDLR_ENFOPRIORITY
    Definition: cons_linear.c:98
    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)
    Definition: cons_linear.c:5242
    static int getInferInt(PROPRULE proprule, int pos)
    Definition: cons_linear.c:432
    static int inferInfoGetProprule(INFERINFO inferinfo)
    Definition: cons_linear.c:395
    static SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
    static SCIP_RETCODE dualPresolve(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss, int *nchgvartypes)
    #define DEFAULT_MINGAINPERNMINCOMP
    Definition: cons_linear.c:127
    static SCIP_Real consdataGetFeasibility(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
    Definition: cons_linear.c:3086
    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
    Definition: cons_linear.c:105
    static SCIP_RETCODE propagateCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool tightenbounds, SCIP_Bool rangedrowpropagation, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, SCIP_Bool *cutoff, int *nchgbds, int *naddconss)
    Definition: cons_linear.c:7621
    static SCIP_DECL_CONSCOPY(consCopyLinear)
    #define MAXSCALEDCOEF
    Definition: cons_linear.c:167
    static void consdataInvalidateActivities(SCIP_CONSDATA *consdata)
    Definition: cons_linear.c:1208
    #define DEFAULT_RANGEDROWMAXDEPTH
    Definition: cons_linear.c:157
    static SCIP_RETCODE analyzeConflictRangedRow(SCIP *scip, SCIP_CONS *cons, SCIP_VAR **vars, int nvars, SCIP_VAR *var, SCIP_Real bound)
    Definition: cons_linear.c:5657
    static SCIP_RETCODE consDropEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
    Definition: cons_linear.c:757
    static SCIP_RETCODE tightenVarBounds(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
    Definition: cons_linear.c:6700
    static SCIP_Real consdataGetMinAbsval(SCIP_CONSDATA *consdata)
    Definition: cons_linear.c:2265
    #define CONSHDLR_NAME
    Definition: cons_linear.c:95
    static SCIP_Bool consdataIsResidualIntegral(SCIP *scip, SCIP_CONSDATA *consdata, int pos, SCIP_Real val)
    static int inferInfoToInt(INFERINFO inferinfo)
    Definition: cons_linear.c:386
    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)
    Definition: cons_linear.c:3337
    #define DEFAULT_SINGLEVARSTUFFING
    Definition: cons_linear.c:145
    #define EVENTHDLR_NAME
    Definition: cons_linear.c:112
    #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)
    Definition: cons_linear.c:792
    static SCIP_RETCODE resolvePropagation(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, INFERINFO inferinfo, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_RESULT *result)
    Definition: cons_linear.c:5097
    static SCIP_Bool isRangedRow(SCIP *scip, SCIP_Real lhs, SCIP_Real rhs)
    #define DEFAULT_DETECTLOWERBOUND
    Definition: cons_linear.c:150
    static SCIP_RETCODE checkPartialObjective(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata)
    #define MAXVALRECOMP
    Definition: cons_linear.c:175
    #define CONSHDLR_DELAYPROP
    Definition: cons_linear.c:106
    static void consdataGetGlbActivityBounds(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Bool goodrelax, SCIP_Real *glbminactivity, SCIP_Real *glbmaxactivity, SCIP_Bool *ismintight, SCIP_Bool *ismaxtight, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
    Definition: cons_linear.c:2810
    static SCIP_Bool canTightenBounds(SCIP_CONS *cons)
    Definition: cons_linear.c:5214
    #define DEFAULT_SEPARATEALL
    Definition: cons_linear.c:139
    static void findOperators(const char *str, char **firstoperator, char **secondoperator, SCIP_Bool *success)
    static INFERINFO getInferInfo(PROPRULE proprule, int pos)
    Definition: cons_linear.c:413
    #define MAXTIGHTENROUNDS
    Definition: cons_linear.c:6976
    Constraint handler for linear constraints in their most general form, .
    constraint handler for nonlinear constraints specified by algebraic expressions
    defines macros for basic operations in double-double arithmetic giving roughly twice the precision of...
    #define QUAD_MEMBER(x)
    Definition: dbldblarith.h:48
    #define SCIPquadprecSumQD(r, a, b)
    Definition: dbldblarith.h:62
    #define QUAD_ASSIGN(a, constant)
    Definition: dbldblarith.h:51
    #define QUAD(x)
    Definition: dbldblarith.h:47
    #define QUAD_ASSIGN_Q(a, b)
    Definition: dbldblarith.h:52
    #define QUAD_TO_DBL(x)
    Definition: dbldblarith.h:49
    methods for debugging
    #define SCIPdebugGetSolVal(scip, var, val)
    Definition: debug.h:313
    #define SCIPdebugAddSolVal(scip, var, val)
    Definition: debug.h:312
    #define NULL
    Definition: def.h:257
    #define SCIP_MAXSTRLEN
    Definition: def.h:278
    #define COPYSIGN
    Definition: def.h:248
    #define SCIP_Longint
    Definition: def.h:150
    #define SCIP_MAXTREEDEPTH
    Definition: def.h:306
    #define SCIP_REAL_MAX
    Definition: def.h:167
    #define SCIP_INVALID
    Definition: def.h:187
    #define SCIP_Bool
    Definition: def.h:100
    #define MIN(x, y)
    Definition: def.h:233
    #define MAX3(x, y, z)
    Definition: def.h:237
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define ABS(x)
    Definition: def.h:225
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define MAX(x, y)
    Definition: def.h:229
    #define SCIP_CALL_ABORT(x)
    Definition: def.h:343
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:157
    #define MIN3(x, y, z)
    Definition: def.h:241
    #define SCIPABORT()
    Definition: def.h:336
    #define REALABS(x)
    Definition: def.h:191
    #define EPSGT(x, y, eps)
    Definition: def.h:195
    #define SCIP_CALL(x)
    Definition: def.h:364
    SCIP_RETCODE SCIPcreateRowLinear(SCIP *scip, SCIP_CONS *cons)
    SCIP_Real SCIPgetDualsolLinear(SCIP *scip, SCIP_CONS *cons)
    SCIP_RETCODE SCIPincludeLinconsUpgrade(SCIP *scip, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority, const char *conshdlrname)
    SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
    SCIP_RETCODE SCIPupgradeConsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_CONS **upgdcons)
    SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
    SCIP_RETCODE SCIPchgRhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
    SCIP_RETCODE SCIPcleanupConssLinear(SCIP *scip, SCIP_Bool onlychecked, SCIP_Bool *infeasible, int *ndelconss)
    SCIP_RETCODE SCIPincludeConsUpgradeNonlinear(SCIP *scip, SCIP_DECL_NONLINCONSUPGD((*nlconsupgd)), int priority, SCIP_Bool active, const char *conshdlrname)
    SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
    SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
    int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
    SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
    SCIP_ROW * SCIPgetRowLinear(SCIP *scip, SCIP_CONS *cons)
    SCIP_RETCODE SCIPcreateConsBasicLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
    SCIP_EXPR * SCIPgetExprNonlinear(SCIP_CONS *cons)
    SCIP_RETCODE SCIPseparateRelaxedKnapsack(SCIP *scip, SCIP_CONS *cons, SCIP_SEPA *sepa, int nknapvars, SCIP_VAR **knapvars, SCIP_Real *knapvals, SCIP_Real valscale, SCIP_Real rhs, SCIP_SOL *sol, SCIP_Bool *cutoff, int *ncuts)
    SCIP_Real SCIPgetRhsNonlinear(SCIP_CONS *cons)
    SCIP_Real SCIPgetDualfarkasLinear(SCIP *scip, SCIP_CONS *cons)
    #define SCIP_DECL_LINCONSUPGD(x)
    Definition: cons_linear.h:120
    SCIP_RETCODE SCIPcopyConsLinear(SCIP *scip, SCIP_CONS **cons, SCIP *sourcescip, const char *name, int nvars, SCIP_VAR **sourcevars, SCIP_Real *sourcecoefs, SCIP_Real lhs, SCIP_Real rhs, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode, SCIP_Bool global, SCIP_Bool *valid)
    SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    SCIP_Real SCIPgetActivityLinear(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
    SCIP_Real SCIPgetFeasibilityLinear(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
    SCIP_RETCODE SCIPclassifyConstraintTypesLinear(SCIP *scip, SCIP_LINCONSSTATS *linconsstats)
    SCIP_RETCODE SCIPchgLhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
    SCIP_Real SCIPgetLhsNonlinear(SCIP_CONS *cons)
    SCIP_RETCODE SCIPchgCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
    SCIP_RETCODE SCIPdelCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
    SCIP_RETCODE SCIPincludeConshdlrLinear(SCIP *scip)
    SCIP_RETCODE SCIPconvertCutsToConss(SCIP *scip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, int *ncutsadded)
    Definition: scip_copy.c:2052
    SCIP_Bool SCIPisConsCompressionEnabled(SCIP *scip)
    Definition: scip_copy.c:662
    SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
    Definition: scip_copy.c:713
    SCIP_Bool SCIPisTransformed(SCIP *scip)
    Definition: scip_general.c:655
    SCIP_Bool SCIPisPresolveFinished(SCIP *scip)
    Definition: scip_general.c:676
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:767
    SCIP_STAGE SCIPgetStage(SCIP *scip)
    Definition: scip_general.c:444
    int SCIPgetNObjVars(SCIP *scip)
    Definition: scip_prob.c:2616
    SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_prob.c:1907
    SCIP_RETCODE SCIPaddConsUpgrade(SCIP *scip, SCIP_CONS *oldcons, SCIP_CONS **newcons)
    Definition: scip_prob.c:3368
    int SCIPgetNContVars(SCIP *scip)
    Definition: scip_prob.c:2569
    SCIP_CONS ** SCIPgetConss(SCIP *scip)
    Definition: scip_prob.c:3666
    SCIP_RETCODE SCIPaddObjoffset(SCIP *scip, SCIP_Real addval)
    Definition: scip_prob.c:1443
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:3420
    int SCIPgetNConss(SCIP *scip)
    Definition: scip_prob.c:3620
    SCIP_VAR ** SCIPgetVars(SCIP *scip)
    Definition: scip_prob.c:2201
    int SCIPgetNBinVars(SCIP *scip)
    Definition: scip_prob.c:2293
    void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
    Definition: misc.c:2348
    #define SCIPhashFour(a, b, c, d)
    Definition: pub_misc.h:573
    SCIP_RETCODE SCIPhashtableSafeInsert(SCIP_HASHTABLE *hashtable, void *element)
    Definition: misc.c:2567
    SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
    Definition: misc.c:2298
    void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
    Definition: misc.c:2596
    void SCIPhashtablePrintStatistics(SCIP_HASHTABLE *hashtable, SCIP_MESSAGEHDLR *messagehdlr)
    Definition: misc.c:2792
    SCIP_RETCODE SCIPhashtableRemove(SCIP_HASHTABLE *hashtable, void *element)
    Definition: misc.c:2665
    SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
    Definition: misc.c:2535
    #define SCIPhashSignature64(a)
    Definition: pub_misc.h:566
    SCIP_RETCODE SCIPupdateLocalLowerbound(SCIP *scip, SCIP_Real newbound)
    Definition: scip_prob.c:4289
    SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:4067
    SCIP_Real SCIPgetLocalLowerbound(SCIP *scip)
    Definition: scip_prob.c:4178
    SCIP_RETCODE SCIPaddConflict(SCIP *scip, SCIP_NODE *node, SCIP_CONS **cons, SCIP_NODE *validnode, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
    Definition: scip_prob.c:3806
    SCIP_RETCODE SCIPaddConsLocal(SCIP *scip, SCIP_CONS *cons, SCIP_NODE *validnode)
    Definition: scip_prob.c:3986
    void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:208
    void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:225
    #define SCIPdebugMsgPrint
    Definition: scip_message.h:79
    SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
    Definition: scip_message.c:88
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
    Definition: scip_message.c:120
    SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
    Definition: misc.c:9197
    SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
    Definition: misc.c:9449
    SCIP_Real SCIPselectSimpleValue(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom)
    Definition: misc.c:10041
    SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *numerator, SCIP_Longint *denominator)
    Definition: misc.c:9470
    SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
    Definition: misc.c:11162
    SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:83
    SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:139
    SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:57
    void SCIPswapPointers(void **pointer1, void **pointer2)
    Definition: misc.c:10511
    int SCIPgetNLPBranchCands(SCIP *scip)
    Definition: scip_branch.c:436
    SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
    SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
    SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
    const char * SCIPconflicthdlrGetName(SCIP_CONFLICTHDLR *conflicthdlr)
    SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
    SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
    SCIP_RETCODE SCIPincludeConflicthdlrBasic(SCIP *scip, SCIP_CONFLICTHDLR **conflicthdlrptr, const char *name, const char *desc, int priority, SCIP_DECL_CONFLICTEXEC((*conflictexec)), SCIP_CONFLICTHDLRDATA *conflicthdlrdata)
    int SCIPconshdlrGetNCheckConss(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4802
    SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
    Definition: scip_cons.c:808
    void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
    Definition: cons.c:4350
    SCIP_CONS ** SCIPconshdlrGetCheckConss(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4759
    SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
    Definition: scip_cons.c:540
    SCIP_RETCODE SCIPsetConshdlrInit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINIT((*consinit)))
    Definition: scip_cons.c:396
    SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
    Definition: scip_cons.c:831
    SCIP_RETCODE SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
    Definition: scip_cons.c:235
    SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
    Definition: scip_cons.c:281
    SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
    Definition: scip_cons.c:181
    SCIP_RETCODE SCIPsetConshdlrDeactive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDEACTIVE((*consdeactive)))
    Definition: scip_cons.c:693
    SCIP_RETCODE SCIPsetConshdlrGetPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETPERMSYMGRAPH((*consgetpermsymgraph)))
    Definition: scip_cons.c:900
    SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
    Definition: scip_cons.c:578
    SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
    Definition: scip_cons.c:372
    SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
    Definition: scip_cons.c:323
    int SCIPconshdlrGetPropFreq(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:5286
    int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4782
    const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4320
    SCIP_RETCODE SCIPsetConshdlrExit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXIT((*consexit)))
    Definition: scip_cons.c:420
    SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITPRE((*consexitpre)))
    Definition: scip_cons.c:516
    SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
    Definition: scip_cons.c:347
    SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
    Definition: scip_cons.c:940
    SCIP_RETCODE SCIPsetConshdlrGetSignedPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH((*consgetsignedpermsymgraph)))
    Definition: scip_cons.c:924
    SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
    Definition: scip_cons.c:468
    SCIP_RETCODE SCIPsetConshdlrDelvars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELVARS((*consdelvars)))
    Definition: scip_cons.c:762
    SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
    Definition: scip_cons.c:624
    SCIP_RETCODE SCIPsetConshdlrInitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITSOL((*consinitsol)))
    Definition: scip_cons.c:444
    SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4340
    SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
    Definition: scip_cons.c:601
    SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
    Definition: scip_cons.c:647
    int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4816
    SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
    Definition: scip_cons.c:854
    SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4739
    SCIP_RETCODE SCIPsetConshdlrActive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSACTIVE((*consactive)))
    Definition: scip_cons.c:670
    SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
    Definition: scip_cons.c:785
    SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
    Definition: cons.c:8423
    int SCIPconsGetPos(SCIP_CONS *cons)
    Definition: cons.c:8403
    SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
    Definition: cons.c:8652
    SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
    Definition: cons.c:8413
    SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
    Definition: cons.c:8562
    SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
    Definition: scip_cons.c:2536
    int SCIPconsGetNUpgradeLocks(SCIP_CONS *cons)
    Definition: cons.c:8845
    SCIP_RETCODE SCIPsetConsSeparated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool separate)
    Definition: scip_cons.c:1296
    SCIP_Bool SCIPconsIsMarkedPropagate(SCIP_CONS *cons)
    Definition: cons.c:8602
    SCIP_Bool SCIPconsIsOriginal(SCIP_CONS *cons)
    Definition: cons.c:8692
    SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
    Definition: cons.c:8592
    SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
    Definition: cons.c:8522
    SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
    Definition: cons.c:8702
    int SCIPconsGetNLocksPos(SCIP_CONS *cons)
    Definition: cons.c:8742
    SCIP_RETCODE SCIPsetConsInitial(SCIP *scip, SCIP_CONS *cons, SCIP_Bool initial)
    Definition: scip_cons.c:1271
    SCIP_RETCODE SCIPsetConsEnforced(SCIP *scip, SCIP_CONS *cons, SCIP_Bool enforce)
    Definition: scip_cons.c:1321
    SCIP_Bool SCIPconsIsLockedType(SCIP_CONS *cons, SCIP_LOCKTYPE locktype)
    Definition: cons.c:8786
    SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
    Definition: cons.c:8582
    SCIP_RETCODE SCIPunmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:2042
    SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
    Definition: cons.c:8454
    SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    Definition: scip_cons.c:997
    SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
    Definition: cons.c:8612
    SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
    Definition: cons.c:8632
    int SCIPconsGetNLocksNeg(SCIP_CONS *cons)
    Definition: cons.c:8752
    const char * SCIPconsGetName(SCIP_CONS *cons)
    Definition: cons.c:8393
    SCIP_Bool SCIPconsIsLocked(SCIP_CONS *cons)
    Definition: cons.c:8732
    SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:1812
    SCIP_RETCODE SCIPmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:2014
    SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
    Definition: cons.c:8642
    SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
    Definition: scip_cons.c:1524
    SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
    Definition: cons.c:8672
    SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    SCIP_RETCODE SCIPsetConsPropagated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool propagate)
    Definition: scip_cons.c:1371
    SCIP_RETCODE SCIPsetConsChecked(SCIP *scip, SCIP_CONS *cons, SCIP_Bool check)
    Definition: scip_cons.c:1346
    SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
    Definition: cons.c:8572
    SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:1784
    SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
    Definition: cons.c:8662
    SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
    Definition: scip_cut.c:225
    SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
    Definition: scip_event.c:111
    const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
    Definition: event.c:396
    SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
    Definition: event.c:1194
    SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
    Definition: scip_event.c:367
    SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
    Definition: scip_event.c:413
    SCIP_Real SCIPeventGetOldbound(SCIP_EVENT *event)
    Definition: event.c:1391
    SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
    Definition: event.c:1217
    SCIP_IMPLINTTYPE SCIPeventGetOldImpltype(SCIP_EVENT *event)
    Definition: event.c:1496
    SCIP_Real SCIPeventGetNewbound(SCIP_EVENT *event)
    Definition: event.c:1415
    SCIP_VARTYPE SCIPeventGetOldtype(SCIP_EVENT *event)
    Definition: event.c:1462
    int SCIPexprGetNChildren(SCIP_EXPR *expr)
    Definition: expr.c:3872
    SCIP_Bool SCIPisExprSum(SCIP *scip, SCIP_EXPR *expr)
    Definition: scip_expr.c:1479
    SCIP_Real * SCIPgetCoefsExprSum(SCIP_EXPR *expr)
    Definition: expr_sum.c:1554
    SCIP_Bool SCIPisExprVar(SCIP *scip, SCIP_EXPR *expr)
    Definition: scip_expr.c:1457
    SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
    Definition: expr.c:3882
    SCIP_Real SCIPgetConstantExprSum(SCIP_EXPR *expr)
    Definition: expr_sum.c:1569
    SCIP_VAR * SCIPgetVarExprVar(SCIP_EXPR *expr)
    Definition: expr_var.c:423
    SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
    Definition: scip_lp.c:87
    #define SCIPfreeBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:110
    BMS_BLKMEM * SCIPblkmem(SCIP *scip)
    Definition: scip_mem.c:57
    int SCIPcalcMemGrowSize(SCIP *scip, int num)
    Definition: scip_mem.c:139
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPreallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:128
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPduplicateBufferArray(scip, ptr, source, num)
    Definition: scip_mem.h:132
    #define SCIPallocBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:93
    #define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
    Definition: scip_mem.h:99
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
    Definition: scip_mem.h:111
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    #define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
    Definition: scip_mem.h:105
    SCIP_RETCODE SCIPdelNlRow(SCIP *scip, SCIP_NLROW *nlrow)
    Definition: scip_nlp.c:424
    SCIP_RETCODE SCIPaddNlRow(SCIP *scip, SCIP_NLROW *nlrow)
    Definition: scip_nlp.c:396
    SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
    Definition: scip_nlp.c:110
    SCIP_RETCODE SCIPreleaseNlRow(SCIP *scip, SCIP_NLROW **nlrow)
    Definition: scip_nlp.c:1058
    SCIP_Bool SCIPnlrowIsInNLP(SCIP_NLROW *nlrow)
    Definition: nlp.c:1953
    SCIP_RETCODE SCIPcreateNlRow(SCIP *scip, SCIP_NLROW **nlrow, const char *name, SCIP_Real constant, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, SCIP_EXPR *expr, SCIP_Real lhs, SCIP_Real rhs, SCIP_EXPRCURV curvature)
    Definition: scip_nlp.c:954
    SCIP_Bool SCIPinProbing(SCIP *scip)
    Definition: scip_probing.c:98
    void SCIPlinConsStatsIncTypeCount(SCIP_LINCONSSTATS *linconsstats, SCIP_LINCONSTYPE linconstype, int increment)
    Definition: cons.c:8288
    void SCIPlinConsStatsReset(SCIP_LINCONSSTATS *linconsstats)
    Definition: cons.c:8257
    SCIP_Bool SCIProwIsModifiable(SCIP_ROW *row)
    Definition: lp.c:17805
    SCIP_RETCODE SCIPchgRowLhs(SCIP *scip, SCIP_ROW *row, SCIP_Real lhs)
    Definition: scip_lp.c:1529
    SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONS *cons, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
    Definition: scip_lp.c:1398
    SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_lp.c:1646
    SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
    Definition: scip_lp.c:2176
    SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
    Definition: scip_lp.c:2131
    SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
    Definition: scip_lp.c:1508
    SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
    Definition: lp.c:17719
    SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
    Definition: scip_lp.c:1553
    SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
    Definition: lp.c:17917
    SCIP_RETCODE SCIPaddVarsToRow(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
    Definition: scip_lp.c:1672
    SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
    Definition: lp.c:17706
    SCIP_Real SCIPgetRowSolActivity(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
    Definition: scip_lp.c:2108
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1763
    void SCIPupdateSolLPConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
    Definition: scip_sol.c:467
    SCIP_RETCODE SCIPupdateCutoffbound(SCIP *scip, SCIP_Real cutoffbound)
    int SCIPgetNSepaRounds(SCIP *scip)
    SCIP_Real SCIPgetLowerbound(SCIP *scip)
    int SCIPgetNRuns(SCIP *scip)
    SCIP_Real SCIPgetCutoffbound(SCIP *scip)
    SCIP_Longint SCIPgetNConflictConssApplied(SCIP *scip)
    SCIP_Bool SCIPisUbBetter(SCIP *scip, SCIP_Real newub, SCIP_Real oldlb, SCIP_Real oldub)
    SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisSumRelLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisSumRelEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisLbBetter(SCIP *scip, SCIP_Real newlb, SCIP_Real oldlb, SCIP_Real oldub)
    SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisHugeValue(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPfeastol(SCIP *scip)
    SCIP_Real SCIPgetHugeValue(SCIP *scip)
    SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisSumRelGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisScalingIntegral(SCIP *scip, SCIP_Real val, SCIP_Real scalar)
    SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPcutoffbounddelta(SCIP *scip)
    SCIP_Bool SCIPisUpdateUnreliable(SCIP *scip, SCIP_Real newvalue, SCIP_Real oldvalue)
    SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPepsilon(SCIP *scip)
    SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisSumGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPparseReal(SCIP *scip, const char *str, SCIP_Real *value, char **endptr)
    SCIP_Bool SCIPinRepropagation(SCIP *scip)
    Definition: scip_tree.c:146
    int SCIPgetDepth(SCIP *scip)
    Definition: scip_tree.c:672
    SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
    Definition: var.c:23546
    SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
    Definition: scip_var.c:6401
    SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
    Definition: var.c:18365
    SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
    Definition: var.c:23566
    SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
    Definition: scip_var.c:5210
    SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
    Definition: var.c:23875
    SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
    Definition: var.c:23900
    SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
    Definition: var.c:23674
    SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
    Definition: var.c:23510
    SCIP_RETCODE SCIPaddClique(SCIP *scip, SCIP_VAR **vars, SCIP_Bool *values, int nvars, SCIP_Bool isequation, SCIP_Bool *infeasible, int *nbdchgs)
    Definition: scip_var.c:8882
    SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
    Definition: scip_var.c:2119
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23418
    int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4380
    SCIP_Bool SCIPdoNotAggr(SCIP *scip)
    Definition: scip_var.c:10909
    SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
    Definition: var.c:23530
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24300
    SCIP_Bool SCIPdoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:10942
    SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
    Definition: var.c:23462
    SCIP_RETCODE SCIPaggregateVars(SCIP *scip, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *redundant, SCIP_Bool *aggregated)
    Definition: scip_var.c:10550
    SCIP_RETCODE SCIPinferVarUbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
    Definition: scip_var.c:7069
    SCIP_Bool SCIPvarIsNonimpliedIntegral(SCIP_VAR *var)
    Definition: var.c:23538
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23932
    SCIP_RETCODE SCIPchgVarImplType(SCIP *scip, SCIP_VAR *var, SCIP_IMPLINTTYPE impltype, SCIP_Bool *infeasible)
    Definition: scip_var.c:10218
    SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
    Definition: scip_var.c:6651
    SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
    Definition: var.c:23485
    SCIP_RETCODE SCIPgetProbvarSum(SCIP *scip, SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
    Definition: scip_var.c:2499
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24174
    int SCIPvarGetIndex(SCIP_VAR *var)
    Definition: var.c:23684
    SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
    Definition: scip_var.c:5118
    SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
    Definition: scip_var.c:5296
    SCIP_RETCODE SCIPcreateVarImpl(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_IMPLINTTYPE impltype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
    Definition: scip_var.c:225
    SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
    Definition: scip_var.c:2872
    int SCIPvarGetProbindex(SCIP_VAR *var)
    Definition: var.c:23694
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23299
    SCIP_RETCODE SCIPmultiaggregateVar(SCIP *scip, SCIP_VAR *var, int naggvars, SCIP_VAR **aggvars, SCIP_Real *scalars, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
    Definition: scip_var.c:10834
    SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
    Definition: var.c:24961
    SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
    Definition: scip_var.c:1887
    SCIP_Real SCIPadjustedVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real ub)
    Definition: scip_var.c:5634
    SCIP_Real SCIPvarGetBestBoundLocal(SCIP_VAR *var)
    Definition: var.c:24344
    SCIP_RETCODE SCIPparseVarsLinearsum(SCIP *scip, const char *str, SCIP_VAR **vars, SCIP_Real *vals, int *nvars, int varssize, int *requiredsize, char **endptr, SCIP_Bool *success)
    Definition: scip_var.c:899
    SCIP_RETCODE SCIPgetProbvarLinearSum(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize)
    Definition: scip_var.c:2378
    SCIP_Real SCIPadjustedVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real lb)
    Definition: scip_var.c:5570
    SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
    Definition: var.c:23522
    SCIP_RETCODE SCIPchgVarType(SCIP *scip, SCIP_VAR *var, SCIP_VARTYPE vartype, SCIP_Bool *infeasible)
    Definition: scip_var.c:10113
    SCIP_RETCODE SCIPflattenVarAggregationGraph(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:2332
    SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
    Definition: var.c:23838
    int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
    Definition: var.c:23826
    SCIP_RETCODE SCIPaddVarImplication(SCIP *scip, SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *infeasible, int *nbdchgs)
    Definition: scip_var.c:8740
    SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
    Definition: var.c:23556
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24266
    SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
    Definition: var.c:23475
    SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
    Definition: var.c:23632
    SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
    Definition: var.c:23449
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24152
    SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
    Definition: scip_var.c:10318
    SCIP_RETCODE SCIPinferVarLbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
    Definition: scip_var.c:6964
    SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
    Definition: scip_var.c:2736
    SCIP_IMPLINTTYPE SCIPvarGetImplType(SCIP_VAR *var)
    Definition: var.c:23495
    int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
    Definition: var.c:17319
    SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
    Definition: scip_var.c:361
    SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
    Definition: scip_var.c:5372
    SCIP_RETCODE SCIPwriteVarsLinearsum(SCIP *scip, FILE *file, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_Bool type)
    Definition: scip_var.c:474
    SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
    Definition: var.c:24951
    int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4322
    SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
    Definition: scip_var.c:2078
    SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:1853
    SCIP_Bool SCIPallowStrongDualReds(SCIP *scip)
    Definition: scip_var.c:10984
    SCIP_RETCODE SCIPinferVarFixCons(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
    Definition: scip_var.c:6895
    SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
    Definition: var.c:23850
    void SCIPsortDownRealPtr(SCIP_Real *realarray, void **ptrarray, int len)
    void SCIPsortRealInt(SCIP_Real *realarray, int *intarray, int len)
    void SCIPsort(int *perm, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
    Definition: misc.c:5581
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    SCIP_RETCODE SCIPskipSpace(char **s)
    Definition: misc.c:10816
    SCIP_RETCODE SCIPgetSymActiveVariables(SCIP *scip, SYM_SYMTYPE symtype, SCIP_VAR ***vars, SCIP_Real **scalars, int *nvars, SCIP_Real *constant, SCIP_Bool transformed)
    SCIP_RETCODE SCIPextendPermsymDetectionGraphLinear(SCIP *scip, SYM_GRAPH *graph, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_CONS *cons, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool *success)
    static const SCIP_Real scalars[]
    Definition: lp.c:5959
    static const char * paramname[]
    Definition: lpi_msk.c:5172
    memory allocation routines
    #define BMScopyMemoryArray(ptr, source, num)
    Definition: memory.h:134
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    struct BMS_BlkMem BMS_BLKMEM
    Definition: memory.h:437
    void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
    Definition: message.c:618
    INLINE SCIP_Longint numerator(Rational &r)
    INLINE SCIP_Longint denominator(Rational &r)
    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
    Definition: pub_message.h:123
    #define SCIPdebug(x)
    Definition: pub_message.h:93
    #define SCIPdebugPrintCons(x, y, z)
    Definition: pub_message.h:102
    #define SCIPdebugMessage
    Definition: pub_message.h:96
    public data structures and miscellaneous methods
    #define SCIPisFinite(x)
    Definition: pub_misc.h:82
    methods for sorting joint arrays of various types
    public methods for problem variables
    public methods for branching rule plugins and branching
    public methods for conflict handler plugins and conflict analysis
    public methods for constraint handler plugins and constraints
    public methods for problem copies
    public methods for cuts and aggregation rows
    public methods for event handler plugins and event handlers
    general public methods
    public methods for the LP relaxation, rows and columns
    public methods for memory management
    public methods for message handling
    public methods for numerical tolerances
    public methods for SCIP parameter handling
    public methods for global and local (sub)problems
    public methods for the probing mode
    public methods for solutions
    public methods for querying solving statistics
    public methods for the branch-and-bound tree
    public methods for SCIP variables
    static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
    Main separation function.
    Definition: sepa_flower.c:1219
    SCIP_DECL_LINCONSUPGD((*linconsupgd))
    structs for symmetry computations
    methods for dealing with symmetry detection graphs
    @ SCIP_CONFTYPE_PROPAGATION
    Definition: type_conflict.h:62
    struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
    Definition: type_cons.h:64
    @ SCIP_LINCONSTYPE_BINPACKING
    Definition: type_cons.h:85
    @ SCIP_LINCONSTYPE_VARBOUND
    Definition: type_cons.h:78
    @ SCIP_LINCONSTYPE_EMPTY
    Definition: type_cons.h:73
    @ SCIP_LINCONSTYPE_INVKNAPSACK
    Definition: type_cons.h:83
    @ SCIP_LINCONSTYPE_PRECEDENCE
    Definition: type_cons.h:77
    @ SCIP_LINCONSTYPE_AGGREGATION
    Definition: type_cons.h:76
    @ SCIP_LINCONSTYPE_MIXEDBINARY
    Definition: type_cons.h:88
    @ SCIP_LINCONSTYPE_SINGLETON
    Definition: type_cons.h:75
    @ SCIP_LINCONSTYPE_SETCOVERING
    Definition: type_cons.h:81
    @ SCIP_LINCONSTYPE_EQKNAPSACK
    Definition: type_cons.h:84
    @ SCIP_LINCONSTYPE_FREE
    Definition: type_cons.h:74
    @ SCIP_LINCONSTYPE_KNAPSACK
    Definition: type_cons.h:86
    @ SCIP_LINCONSTYPE_SETPARTITION
    Definition: type_cons.h:79
    @ SCIP_LINCONSTYPE_INTKNAPSACK
    Definition: type_cons.h:87
    @ SCIP_LINCONSTYPE_SETPACKING
    Definition: type_cons.h:80
    @ SCIP_LINCONSTYPE_GENERAL
    Definition: type_cons.h:89
    @ SCIP_LINCONSTYPE_CARDINALITY
    Definition: type_cons.h:82
    struct SCIP_ConsData SCIP_CONSDATA
    Definition: type_cons.h:65
    #define SCIP_EVENTTYPE_BOUNDCHANGED
    Definition: type_event.h:127
    #define SCIP_EVENTTYPE_VARUNLOCKED
    Definition: type_event.h:73
    #define SCIP_EVENTTYPE_TYPECHANGED
    Definition: type_event.h:86
    #define SCIP_EVENTTYPE_GUBCHANGED
    Definition: type_event.h:76
    #define SCIP_EVENTTYPE_GBDCHANGED
    Definition: type_event.h:122
    struct SCIP_EventData SCIP_EVENTDATA
    Definition: type_event.h:179
    #define SCIP_EVENTTYPE_UBTIGHTENED
    Definition: type_event.h:79
    #define SCIP_EVENTTYPE_VARFIXED
    Definition: type_event.h:72
    #define SCIP_EVENTTYPE_VARDELETED
    Definition: type_event.h:71
    #define SCIP_EVENTTYPE_FORMAT
    Definition: type_event.h:157
    #define SCIP_EVENTTYPE_GLBCHANGED
    Definition: type_event.h:75
    #define SCIP_EVENTTYPE_BOUNDRELAXED
    Definition: type_event.h:126
    #define SCIP_EVENTTYPE_LBCHANGED
    Definition: type_event.h:123
    #define SCIP_EVENTTYPE_UBCHANGED
    Definition: type_event.h:124
    uint64_t SCIP_EVENTTYPE
    Definition: type_event.h:156
    #define SCIP_EVENTTYPE_IMPLTYPECHANGED
    Definition: type_event.h:87
    #define SCIP_EVENTTYPE_DISABLED
    Definition: type_event.h:67
    #define SCIP_EVENTTYPE_BOUNDTIGHTENED
    Definition: type_event.h:125
    #define SCIP_EVENTTYPE_LBTIGHTENED
    Definition: type_event.h:77
    @ SCIP_EXPRCURV_LINEAR
    Definition: type_expr.h:65
    @ SCIP_BOUNDTYPE_UPPER
    Definition: type_lp.h:58
    @ SCIP_BOUNDTYPE_LOWER
    Definition: type_lp.h:57
    enum SCIP_BoundType SCIP_BOUNDTYPE
    Definition: type_lp.h:60
    @ SCIP_VERBLEVEL_HIGH
    Definition: type_message.h:61
    @ 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
    Definition: type_retcode.h:45
    @ SCIP_INVALIDDATA
    Definition: type_retcode.h:52
    @ SCIP_PLUGINNOTFOUND
    Definition: type_retcode.h:54
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    @ SCIP_ERROR
    Definition: type_retcode.h:43
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_STAGE_PROBLEM
    Definition: type_set.h:45
    @ SCIP_STAGE_PRESOLVING
    Definition: type_set.h:49
    @ SCIP_STAGE_INITSOLVE
    Definition: type_set.h:52
    @ SCIP_STAGE_EXITPRESOLVE
    Definition: type_set.h:50
    @ SCIP_STAGE_SOLVING
    Definition: type_set.h:53
    @ SCIP_STAGE_TRANSFORMING
    Definition: type_set.h:46
    @ SCIP_STAGE_PRESOLVED
    Definition: type_set.h:51
    enum SYM_Symtype SYM_SYMTYPE
    Definition: type_symmetry.h:64
    @ SYM_SYMTYPE_SIGNPERM
    Definition: type_symmetry.h:62
    @ SYM_SYMTYPE_PERM
    Definition: type_symmetry.h:61
    #define SCIP_PRESOLTIMING_EXHAUSTIVE
    Definition: type_timing.h:54
    #define NLOCKTYPES
    Definition: type_var.h:138
    enum SCIP_ImplintType SCIP_IMPLINTTYPE
    Definition: type_var.h:117
    @ SCIP_IMPLINTTYPE_NONE
    Definition: type_var.h:90
    @ SCIP_IMPLINTTYPE_STRONG
    Definition: type_var.h:106
    @ SCIP_IMPLINTTYPE_WEAK
    Definition: type_var.h:91
    #define SCIP_DEPRECATED_VARTYPE_IMPLINT
    Definition: type_var.h:79
    @ SCIP_VARTYPE_INTEGER
    Definition: type_var.h:65
    @ SCIP_VARTYPE_CONTINUOUS
    Definition: type_var.h:71
    @ SCIP_VARTYPE_BINARY
    Definition: type_var.h:64
    @ SCIP_VARSTATUS_ORIGINAL
    Definition: type_var.h:51
    @ SCIP_VARSTATUS_FIXED
    Definition: type_var.h:54
    @ SCIP_VARSTATUS_COLUMN
    Definition: type_var.h:53
    @ SCIP_VARSTATUS_MULTAGGR
    Definition: type_var.h:56
    @ SCIP_VARSTATUS_NEGATED
    Definition: type_var.h:57
    @ SCIP_VARSTATUS_AGGREGATED
    Definition: type_var.h:55
    @ SCIP_VARSTATUS_LOOSE
    Definition: type_var.h:52
    enum SCIP_LockType SCIP_LOCKTYPE
    Definition: type_var.h:144
    @ SCIP_LOCKTYPE_MODEL
    Definition: type_var.h:141
    enum SCIP_Vartype SCIP_VARTYPE
    Definition: type_var.h:73
    enum SCIP_Varstatus SCIP_VARSTATUS
    Definition: type_var.h:59