Scippy

    SCIP

    Solving Constraint Integer Programs

    presolve.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-2025 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 presolve.c
    26 * @ingroup OTHER_CFILES
    27 * @brief methods for presolving
    28 * @author Michael Winkler
    29 */
    30
    31/* all general presolving methods (not working on any specific kind of data(, e.g. consdata) should be implemented here */
    32
    33/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    34
    36#include "scip/presolve.h"
    37#include "scip/prob.h"
    38#include "scip/pub_implics.h"
    39#include "scip/pub_message.h"
    40#include "scip/pub_var.h"
    41#include "scip/scip_mem.h"
    42#include "scip/scip_message.h"
    43#include "scip/scip_numerics.h"
    44#include "scip/scip_tree.h"
    45#include "scip/struct_mem.h"
    46#include "scip/struct_scip.h"
    47#include "scip/tree.h"
    48
    49/*
    50 * Local methods
    51 */
    52
    53/** collect variable bound information for a variable set reduction and global implication; only variable which have the
    54 * vartype != SCIP_VARTYPE_BINARY have variable bounds
    55 */
    56static
    58 SCIP* scip, /**< SCIP data structure */
    59 SCIP_VAR* var, /**< set variable */
    60 int varidx, /**< for lower bound set variable index, for upper bound set variable index
    61 * + number of variables
    62 */
    63 int pos, /**< variables's position in bdchinfos */
    64 int nredvars, /**< number of reduced variables so far */
    65 SCIP_Real* bounds, /**< array of bounds where one of them must be fullfilled */
    66 SCIP_Bool* boundtypes, /**< array of bound types */
    67 SCIP_Real* newbounds, /**< array of implied bounds(, size is two times number of variables, first
    68 * half for implied lower bounds, second for implied upper bounds)
    69 */
    70 int* counts, /**< array of number of implication on a bound (, size is two times number
    71 * of variables, first half for implied lower bounds, second for implied
    72 * upper bounds)
    73 */
    74 int* countnonzeros, /**< array to store the indices of non-zero entries in the counts array */
    75 int* ncountnonzeros, /**< pointer to store the number of non-zero entries in the counts array */
    76 int* issetvar, /**< array containing for set variables the position in the current set, or
    77 * 0 if it is not a set variable or -1, if it is a redundant(i.e. implies
    78 * another set variable) set variables(, size is two times number of
    79 * variables, first half for implied lower bounds, second for implied
    80 * upper bounds) */
    81 int nvars, /**< number of problem variables */
    82 int* foundbin, /**< pointer to store the lowest index of a binary implication variable
    83 * when found
    84 */
    85 int* foundnonbin, /**< pointer to store the lowest index of a non-binary implication variable
    86 * when found
    87 */
    88 int* implidx, /**< array to store the variable indices (for upper bound 'nvars' is added
    89 * to the index) which are implied
    90 */
    91 int* nimplidx, /**< pointer to store the number of implied variables */
    92 SCIP_Real* lastbounds /**< array to remember last implied bounds before taken the current
    93 * variable into account, first nvars for lower bound, second nvars for
    94 * upper bound
    95 *
    96 * this array is used when a set variable got redundant, because it
    97 * implies another set variable, and we need to correct the counts array
    98 */
    99 )
    100{
    101 SCIP_VAR** implvars;
    102 SCIP_Real* implcoefs;
    103 SCIP_Real* implconsts;
    104 int nimpls;
    105 int idx;
    106 int w;
    107
    108 assert(scip != NULL);
    109 assert(var != NULL);
    111 assert(varidx >= 0);
    112 assert(pos >= 0);
    113 assert(bounds != NULL);
    114 assert(boundtypes != NULL);
    115 assert(newbounds != NULL);
    116 assert(counts != NULL);
    117 assert(issetvar != NULL);
    118 assert(2 * nvars > varidx);
    119 assert(foundbin != NULL);
    120 assert(foundnonbin != NULL);
    121 assert(implidx != NULL);
    122 assert(nimplidx != NULL);
    123 assert(lastbounds != NULL);
    124
    125 /* 1. case: lower bound in set */
    126 if( !boundtypes[pos] )
    127 {
    128 assert(counts[varidx] <= pos - nredvars + 1);
    129
    130 /* update implication counter of set variable */
    131 if( counts[varidx] == pos - nredvars )
    132 {
    133 ++counts[varidx];
    134
    135 if( counts[varidx] == 1 )
    136 {
    137 assert(*ncountnonzeros < 2*nvars);
    138 countnonzeros[*ncountnonzeros] = varidx;
    139 ++(*ncountnonzeros);
    140 newbounds[varidx] = bounds[pos];
    141 lastbounds[*nimplidx] = SCIP_INVALID;
    142 }
    143 else if( newbounds[varidx] > bounds[pos] )
    144 {
    145 lastbounds[*nimplidx] = newbounds[varidx];
    146 newbounds[varidx] = bounds[pos];
    147 }
    148 else
    149 {
    150 lastbounds[*nimplidx] = SCIP_INVALID;
    151 }
    152
    153 *foundnonbin = MIN(*foundnonbin, varidx);
    154
    155 implidx[*nimplidx] = varidx;
    156 ++(*nimplidx);
    157 }
    158
    159 nimpls = SCIPvarGetNVubs(var);
    160 implvars = SCIPvarGetVubVars(var);
    161 implcoefs = SCIPvarGetVubCoefs(var);
    162 implconsts = SCIPvarGetVubConstants(var);
    163
    164 for( w = nimpls - 1; w >= 0; --w )
    165 {
    166 assert(!SCIPisZero(scip, implcoefs[w]));
    167 idx = SCIPvarGetProbindex(implvars[w]);
    168
    169 /* do not use inactive variables */
    170 /* @todo if implvars[x] is aggregated, we could transform the variable into the active representation */
    171 if( idx < 0 || SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(implvars[w]), SCIPvarGetUbGlobal(implvars[w])) )
    172 continue;
    173
    174 /* the upper bound of implvars[w] is bounding upper bound of var */
    175 if( implcoefs[w] < 0.0 )
    176 {
    177 /* update the counters and implied bounds */
    178 idx += nvars;
    179
    180 if( counts[idx] == pos - nredvars )
    181 {
    182 if( SCIPvarIsBinary(implvars[w]) )
    183 {
    184 /* do not look at fixed variables */
    185 if( SCIPvarGetLbGlobal(implvars[w]) > 0.5 || SCIPvarGetUbGlobal(implvars[w]) < 0.5 )
    186 continue;
    187
    188 /* (implvars[w] = 1 ===> var <= implcoefs[w] + implconsts[w] and if implcoefs[w] +
    189 * implconsts[w] < bounds[pos]) ===> (because var => bounds[v] ===> implvars[w] = 0)
    190 */
    191 if( SCIPisFeasLT(scip, implcoefs[w] + implconsts[w], bounds[pos]) )
    192 {
    193 /* set variable 'var' with bound implies other set variable 'implvars[w]' with corresponding bound
    194 * so we can remove the set variable 'var'
    195 */
    196 if( issetvar[idx] > 0 )
    197 {
    198 SCIPdebugMsg(scip, "set variable <%s> %s %g implies other set variable <%s> %s %g\n",
    199 SCIPvarGetName(var), ">=", bounds[pos], SCIPvarGetName(implvars[w]), "<=", 0.0);
    200
    201 issetvar[varidx] = -1;
    202 break;
    203 }
    204
    205 ++counts[idx];
    206 *foundbin = MIN(*foundbin, idx);
    207
    208 if( counts[idx] == 1 )
    209 {
    210 assert(*ncountnonzeros < 2*nvars);
    211 countnonzeros[*ncountnonzeros] = idx;
    212 ++(*ncountnonzeros);
    213 }
    214
    215 implidx[*nimplidx] = idx;
    216 ++(*nimplidx);
    217 }
    218 }
    219 /* if (implvars[w] = ub(implvars[w]) ==> var <= implcoefs[w]*SCIPvarGetUbGlobal(implvars[w]) +
    220 * implconsts[w]) but (var >= bounds[pos] with bounds[pos] >
    221 * implcoefs[w]*SCIPvarGetUbGlobal(implvars[w]) + implconsts[w]) it follows (new_ub(var) <
    222 * ub(var))
    223 */
    224 else if( SCIPisFeasLT(scip, implcoefs[w] * SCIPvarGetUbGlobal(implvars[w]) + implconsts[w], bounds[pos]) )
    225 {
    226 SCIP_Real newub;
    227
    228 newub = (bounds[pos] - implconsts[w]) / implcoefs[w];
    229
    230 /* set variable 'var' with bound implies other set variable 'implvars[w]' with corresponding bound so
    231 * we can remove the set variable 'var'
    232 */
    233 if( issetvar[idx] > 0 && newub <= bounds[issetvar[idx] - 1] )
    234 {
    235 SCIPdebugMsg(scip, "set variable <%s> %s %g implies other set variable <%s> %s %g (%g)\n",
    236 SCIPvarGetName(var), ">=", bounds[pos], SCIPvarGetName(implvars[w]), "<=", newub, bounds[issetvar[idx] - 1] );
    237
    238 issetvar[varidx] = -1;
    239 break;
    240 }
    241
    242 ++counts[idx];
    243
    244 if( counts[idx] == 1 )
    245 {
    246 assert(*ncountnonzeros < 2*nvars);
    247 countnonzeros[*ncountnonzeros] = idx;
    248 ++(*ncountnonzeros);
    249 newbounds[idx] = newub;
    250 lastbounds[*nimplidx] = SCIP_INVALID;
    251 }
    252 else if( newbounds[idx] < newub )
    253 {
    254 lastbounds[*nimplidx] = newbounds[idx];
    255 newbounds[idx] = newub;
    256 }
    257 else
    258 lastbounds[*nimplidx] = SCIP_INVALID;
    259
    260 *foundnonbin = MIN(*foundnonbin, idx);
    261
    262 implidx[*nimplidx] = idx;
    263 ++(*nimplidx);
    264 }
    265 }
    266 }
    267 else
    268 {
    269 assert(counts[varidx] <= pos - nredvars + 1);
    270
    271 /* update the counters and implied bounds */
    272 if( counts[idx] == pos - nredvars )
    273 {
    274 if( SCIPvarIsBinary(implvars[w]) )
    275 {
    276 /* do not look at fixed variables */
    277 if( SCIPvarGetLbGlobal(implvars[w]) > 0.5 || SCIPvarGetUbGlobal(implvars[w]) < 0.5 )
    278 continue;
    279
    280 /* (implvars[w] = 0 ===> var <= implconsts[w] and if implconsts[w] < bounds[pos]) ===> (because
    281 * var >= bounds[pos] ===> implvars[w] = 1)
    282 */
    283 if( SCIPisFeasLT(scip, implconsts[w], bounds[pos]) )
    284 {
    285 /* set variable 'var' with bound implies other set variable 'implvars[w]' with corresponding bound
    286 * so we can remove the set variable 'var'
    287 */
    288 if( issetvar[idx] > 0 )
    289 {
    290 SCIPdebugMsg(scip, "set variable <%s> %s %g implies other set variable <%s> %s %g\n",
    291 SCIPvarGetName(var), ">=", bounds[pos], SCIPvarGetName(implvars[w]), ">=", 1.0);
    292
    293 issetvar[varidx] = -1;
    294 break;
    295 }
    296
    297 ++counts[idx];
    298 *foundbin = MIN(*foundbin, idx);
    299
    300 if( counts[idx] == 1 )
    301 {
    302 assert(*ncountnonzeros < 2*nvars);
    303 countnonzeros[*ncountnonzeros] = idx;
    304 ++(*ncountnonzeros);
    305 }
    306
    307 implidx[*nimplidx] = idx;
    308 ++(*nimplidx);
    309 }
    310 }
    311 /* if (implvars[w] = lb(implvars[w]) => var <= implcoefs[w]*SCIPvarGetLbGlobal(implvars[w]) +
    312 * implconsts[w]) but (var >= bounds[pos] with bounds[pos] >
    313 * implcoefs[w]*SCIPvarGetLbGlobal(implvars[w]) + implconsts[w]) it follows (new_lb(var) >
    314 * lb(var))
    315 */
    316 else if( SCIPisFeasLT(scip, implcoefs[w]*SCIPvarGetLbGlobal(implvars[w]) + implconsts[w], bounds[pos]) )
    317 {
    318 SCIP_Real newlb;
    319
    320 newlb = (bounds[pos] - implconsts[w]) / implcoefs[w];
    321
    322 /* set variable 'var' with bound implies other set variable 'implvars[w]' with corresponding bound so
    323 * we can remove the set variable 'var'
    324 */
    325 if( issetvar[idx] > 0 && newlb >= bounds[issetvar[idx] - 1] )
    326 {
    327 SCIPdebugMsg(scip, "set variable <%s> %s %g implies other set variable <%s> %s %g (%g)\n",
    328 SCIPvarGetName(var), ">=", bounds[pos], SCIPvarGetName(implvars[w]), ">=", newlb, bounds[issetvar[idx] - 1] );
    329
    330 issetvar[varidx] = -1;
    331 break;
    332 }
    333
    334 ++counts[idx];
    335
    336 if( counts[idx] == 1 )
    337 {
    338 assert(*ncountnonzeros < 2*nvars);
    339 countnonzeros[*ncountnonzeros] = idx;
    340 ++(*ncountnonzeros);
    341 lastbounds[*nimplidx] = SCIP_INVALID;
    342 newbounds[idx] = newlb;
    343 }
    344 else if( newbounds[idx] > newlb )
    345 {
    346 lastbounds[*nimplidx] = newbounds[idx];
    347 newbounds[idx] = newlb;
    348 }
    349 else
    350 lastbounds[*nimplidx] = SCIP_INVALID;
    351
    352 *foundnonbin = MIN(*foundnonbin, idx);
    353
    354 implidx[*nimplidx] = idx;
    355 ++(*nimplidx);
    356 }
    357 }
    358 }
    359 }
    360 }
    361 /* 2.case: upper bound in set */
    362 else
    363 {
    364 assert(boundtypes[pos]);
    365 assert(counts[varidx] <= pos - nredvars + 1);
    366
    367 /* update implication counter of set variable */
    368 if( counts[varidx] == pos - nredvars )
    369 {
    370 ++counts[varidx];
    371
    372 if( counts[varidx] == 1 )
    373 {
    374 assert(*ncountnonzeros < 2*nvars);
    375 countnonzeros[*ncountnonzeros] = varidx;
    376 ++(*ncountnonzeros);
    377 newbounds[varidx] = bounds[pos];
    378 lastbounds[*nimplidx] = SCIP_INVALID;
    379 }
    380 else if( newbounds[varidx] < bounds[pos] )
    381 {
    382 lastbounds[*nimplidx] = newbounds[varidx];
    383 newbounds[varidx] = bounds[pos];
    384 }
    385 else
    386 {
    387 lastbounds[*nimplidx] = SCIP_INVALID;
    388 }
    389
    390 *foundnonbin = MIN(*foundnonbin, varidx);
    391
    392 implidx[*nimplidx] = varidx;
    393 ++(*nimplidx);
    394 }
    395
    396 nimpls = SCIPvarGetNVlbs(var);
    397 implvars = SCIPvarGetVlbVars(var);
    398 implcoefs = SCIPvarGetVlbCoefs(var);
    399 implconsts = SCIPvarGetVlbConstants(var);
    400
    401 for( w = nimpls - 1; w >= 0; --w )
    402 {
    403 assert(!SCIPisZero(scip, implcoefs[w]));
    404 idx = SCIPvarGetProbindex(implvars[w]);
    405
    406 /* do not use inactive variables */
    407 /* @todo if implvars[x] is aggregated, we could transform the variable into the active representation */
    408 if( idx < 0 || SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(implvars[w]), SCIPvarGetUbGlobal(implvars[w])) )
    409 continue;
    410
    411 /* the lower bound of implvars[w] is bounding lower bound of var */
    412 if( implcoefs[w] < 0.0 )
    413 {
    414 assert(counts[idx] <= pos - nredvars + 1);
    415
    416 /* update the counters and implied bounds */
    417 if( counts[idx] == pos - nredvars )
    418 {
    419 if( SCIPvarIsBinary(implvars[w]) )
    420 {
    421 /* do not look at fixed variables */
    422 if( SCIPvarGetLbGlobal(implvars[w]) > 0.5 || SCIPvarGetUbGlobal(implvars[w]) < 0.5 )
    423 continue;
    424
    425 /* (implvars[w] = 0 ===> var >= implconsts[w] and if implconsts[w] > bounds[pos]) ===> (because
    426 * var <= bounds[pos] ===> implvars[w] = 1)
    427 */
    428 if( SCIPisFeasGT(scip, implconsts[w], bounds[pos]) )
    429 {
    430 if( issetvar[idx] > 0 )
    431 {
    432 SCIPdebugMsg(scip, "set variable <%s> %s %g implies other set variable <%s> %s %g\n",
    433 SCIPvarGetName(var), "<=", bounds[pos], SCIPvarGetName(implvars[w]), ">=", 1.0);
    434
    435 issetvar[varidx] = -1;
    436 break;
    437 }
    438
    439 ++counts[idx];
    440 *foundbin = MIN(*foundbin, idx);
    441
    442 if( counts[idx] == 1 )
    443 {
    444 assert(*ncountnonzeros < 2*nvars);
    445 countnonzeros[*ncountnonzeros] = idx;
    446 ++(*ncountnonzeros);
    447 }
    448
    449 implidx[*nimplidx] = idx;
    450 ++(*nimplidx);
    451 }
    452 }
    453 /* if (implvars[w] = lb(implvars[w]) ==> var <= implcoefs[w]*SCIPvarGetLbGlobal(implvars[w]) +
    454 * implconsts[w]) but (var <= bounds[pos] with bounds[pos] <
    455 * implcoefs[w]*SCIPvarGetLbGlobal(implvars[w]) + implconsts[w]) it follows (new_lb(var) >
    456 * ub(var))
    457 */
    458 else if( SCIPisFeasGT(scip, implcoefs[w]*SCIPvarGetLbGlobal(implvars[w]) + implconsts[w], bounds[pos]) )
    459 {
    460 SCIP_Real newlb;
    461
    462 newlb = (bounds[pos] - implconsts[w]) / implcoefs[w];
    463
    464 if( issetvar[idx] > 0 && newlb >= bounds[issetvar[idx] - 1] )
    465 {
    466 SCIPdebugMsg(scip, "set variable <%s> %s %g implies other set variable <%s> %s %g (%g)\n",
    467 SCIPvarGetName(var), "<=", bounds[pos], SCIPvarGetName(implvars[w]), ">=", newlb, bounds[issetvar[idx] - 1]);
    468
    469 issetvar[varidx] = -1;
    470 break;
    471 }
    472
    473 ++counts[idx];
    474
    475 if( counts[idx] == 1 )
    476 {
    477 assert(*ncountnonzeros < 2*nvars);
    478 countnonzeros[*ncountnonzeros] = idx;
    479 ++(*ncountnonzeros);
    480 lastbounds[*nimplidx] = SCIP_INVALID;
    481 newbounds[idx] = newlb;
    482 }
    483 else if( newbounds[idx] > newlb )
    484 {
    485 lastbounds[*nimplidx] = newbounds[idx];
    486 newbounds[idx] = newlb;
    487 }
    488 else
    489 lastbounds[*nimplidx] = SCIP_INVALID;
    490
    491 *foundnonbin = MIN(*foundnonbin, idx);
    492
    493 implidx[*nimplidx] = idx;
    494 ++(*nimplidx);
    495 }
    496 }
    497 }
    498 else
    499 {
    500 /* update the counters and implied bounds */
    501 idx += nvars;
    502
    503 assert(counts[idx] <= pos - nredvars + 1);
    504
    505 if( counts[idx] == pos - nredvars )
    506 {
    507 if( SCIPvarIsBinary(implvars[w]) )
    508 {
    509 /* do not look at fixed variables */
    510 if( SCIPvarGetLbGlobal(implvars[w]) > 0.5 || SCIPvarGetUbGlobal(implvars[w]) < 0.5 )
    511 continue;
    512
    513 /* (implvars[w] = 1 ===> var >= implcoefs[w] + implconsts[w] and if implcoefs[w] +
    514 * implconsts[w] > bounds[pos]) ===> (because var <= bounds[pos] ===> implvars[w] = 0)
    515 */
    516 if( SCIPisFeasGT(scip, implcoefs[w] + implconsts[w], bounds[pos]) )
    517 {
    518 if( issetvar[idx] > 0 )
    519 {
    520 SCIPdebugMsg(scip, "set variable <%s> %s %g implies other set variable <%s> %s %g\n",
    521 SCIPvarGetName(var), "<=", bounds[pos], SCIPvarGetName(implvars[w]), "<=", 0.0);
    522
    523 issetvar[varidx] = -1;
    524 break;
    525 }
    526
    527 ++counts[idx];
    528 *foundbin = MIN(*foundbin, idx);
    529
    530 if( counts[idx] == 1 )
    531 {
    532 assert(*ncountnonzeros < 2*nvars);
    533 countnonzeros[*ncountnonzeros] = idx;
    534 ++(*ncountnonzeros);
    535 }
    536
    537 implidx[*nimplidx] = idx;
    538 ++(*nimplidx);
    539 }
    540 }
    541 /* if (implvars[w] = ub(implvars[w]) => var <= implcoefs[w]*SCIPvarGetUbGlobal(implvars[w]) +
    542 * implconsts[w]) but (var <= bounds[pos] with bounds[pos] <
    543 * implcoefs[w]*SCIPvarGetUbGlobal(implvars[w]) + implconsts[w]) it follows (new_ub(var) <
    544 * ub(var))
    545 */
    546 else if( SCIPisFeasGT(scip, implcoefs[w]*SCIPvarGetUbGlobal(implvars[w]) + implconsts[w], bounds[pos]) )
    547 {
    548 SCIP_Real newub;
    549
    550 newub = (bounds[pos] - implconsts[w]) / implcoefs[w];
    551
    552 if( issetvar[idx] > 0 && newub <= bounds[issetvar[idx] - 1] )
    553 {
    554 SCIPdebugMsg(scip, "set variable <%s> %s %g implies other set variable <%s> %s %g (%g)\n",
    555 SCIPvarGetName(var), "<=", bounds[pos], SCIPvarGetName(implvars[w]), "<=", newub, bounds[issetvar[idx] - 1]);
    556
    557 issetvar[varidx] = -1;
    558 break;
    559 }
    560
    561 ++counts[idx];
    562
    563 if( counts[idx] == 1 )
    564 {
    565 assert(*ncountnonzeros < 2*nvars);
    566 countnonzeros[*ncountnonzeros] = idx;
    567 ++(*ncountnonzeros);
    568 lastbounds[*nimplidx] = SCIP_INVALID;
    569 newbounds[idx] = newub;
    570 }
    571 else if( newbounds[idx] < newub )
    572 {
    573 lastbounds[*nimplidx] = newbounds[idx];
    574 newbounds[idx] = newub;
    575 }
    576 else
    577 lastbounds[*nimplidx] = SCIP_INVALID;
    578
    579 *foundnonbin = MIN(*foundnonbin, idx);
    580
    581 implidx[*nimplidx] = idx;
    582 ++(*nimplidx);
    583 }
    584 }
    585 }
    586 }
    587 }
    588}
    589
    590
    591/** collect non-binary implication data for variable set reduction and global bound implications; only variable which
    592 * have the vartype SCIP_VARTYPE_BINARY have implications, otherwise the implications are saved as variable bounds
    593 */
    594static
    596 SCIP* scip, /**< SCIP data structure */
    597 SCIP_VAR* var, /**< set variable */
    598 int varidx, /**< for lower bound set variable index, for upper bound set
    599 * variable index + number of variables
    600 */
    601 int pos, /**< variables's position in bdchinfos */
    602 int nredvars, /**< number of reduced variables so far */
    603 SCIP_Bool value, /**< value used for clique and implication info */
    604 SCIP_Real* bounds, /**< array of bounds where one of them must be fullfilled */
    605 SCIP_Bool* boundtypes, /**< array of bound types */
    606 SCIP_Real* newbounds, /**< array of implied bounds(, size is two times number of variables, first
    607 * half for implied lower bounds, second for implied upper bounds)
    608 */
    609 int* counts, /**< array of number of implication on a bound (, size is two times number
    610 * of variables, first half for implied lower bounds, second for implied
    611 * upper bounds)
    612 */
    613 int* countnonzeros, /**< array to store the indices of non-zero entries in the counts array */
    614 int* ncountnonzeros, /**< pointer to store the number of non-zero entries in the counts array */
    615 int* issetvar, /**< array containing for set variables the position in the current set, or
    616 * 0 if it is not a set variable or -1, if it is a redundant(i.e. implies
    617 * another set variable) set variables(, size is two times number of
    618 * variables, first half for implied lower bounds, second for implied
    619 * upper bounds) */
    620 int nvars, /**< number of problem variables */
    621 int* foundbin, /**< pointer to store the lowest index of a binary implication variable
    622 * when found
    623 */
    624 int* foundnonbin, /**< pointer to store the lowest index of a non-binary implication variable
    625 * when found
    626 */
    627 int* implidx, /**< array to store the variable indices (for upper bound 'nvars' is added
    628 * to the index) which are implied
    629 */
    630 int* nimplidx, /**< pointer to store the number of implied variables */
    631 SCIP_Real* lastbounds /**< array to remember last implied bounds before taken the current
    632 * variable into account, first nvars for lower bound, second nvars for
    633 * upper bound
    634 *
    635 * this array is used when a set variable got redundant, because it
    636 * implies another set variable, and we need to correct the counts array
    637 */
    638 )
    639{
    640 assert(scip != NULL);
    641 assert(var != NULL);
    643 assert(varidx >= 0);
    644 assert(pos >= 0);
    645 assert(bounds != NULL);
    646 assert(boundtypes != NULL);
    647 assert(newbounds != NULL);
    648 assert(counts != NULL);
    649 assert(issetvar != NULL);
    650 assert(2 * nvars > varidx);
    651 assert(foundbin != NULL);
    652 assert(foundnonbin != NULL);
    653 assert(implidx != NULL);
    654 assert(nimplidx != NULL);
    655 assert(lastbounds != NULL);
    656
    657 if( issetvar[varidx] > 0 )
    658 {
    659 SCIP_VAR** implvars;
    660 SCIP_Real* implbounds;
    661 SCIP_BOUNDTYPE* implboundtypes;
    662 int idx;
    663 int w;
    664
    665 /* get implication information */
    666 implvars = SCIPvarGetImplVars(var, value);
    667 implboundtypes = SCIPvarGetImplTypes(var, value);
    668 implbounds = SCIPvarGetImplBounds(var, value);
    669
    670 for( w = SCIPvarGetNImpls(var, value) - 1; w >= 0; --w )
    671 {
    672 assert(implvars != NULL);
    673 assert(implboundtypes != NULL);
    674
    675 /* no self implication should exist in the implication data structure */
    676 assert(implvars[w] != var);
    677
    678 idx = SCIPvarGetProbindex(implvars[w]);
    679
    680 /* do not use inactive variables */
    681 /* @todo if implvars[x] is aggregated, we could transform the variable into the active representation */
    682 if( idx < 0 || SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(implvars[w]), SCIPvarGetUbGlobal(implvars[w])) )
    683 continue;
    684
    685 if( implboundtypes[w] == SCIP_BOUNDTYPE_UPPER )
    686 {
    687 SCIP_Bool redundant;
    688
    689 idx += nvars;
    690
    691 assert(counts[idx] <= pos - nredvars + 1);
    692
    693 /* set variable 'var' with bound implies other set variable 'implvars[w]' with a non-worse bound than the
    694 * bound so we can remove the set variable 'var'
    695 */
    696 if( issetvar[idx] > 0 && bounds[issetvar[idx] - 1] >= implbounds[w] )
    697 {
    698 SCIPdebugMsg(scip, "set variable <%s> %s %g implies other set variable <%s> %s %g (%g)\n",
    699 SCIPvarGetName(var), boundtypes[pos] ? "<=" : ">=", bounds[pos], SCIPvarGetName(implvars[w]),
    700 "<=", implbounds[w], bounds[issetvar[idx] - 1]);
    701
    702 issetvar[varidx] = -1;
    703 break;
    704 }
    705
    706 /* ignore implications that are redundant with respect to the current global bounds (see #2888) */
    707 redundant = SCIPisLE(scip, SCIPvarGetUbGlobal(implvars[w]), implbounds[w]);
    708
    709 /* update implication counter and implied upper bound */
    710 if( counts[idx] == pos - nredvars && !redundant )
    711 {
    712 ++counts[idx];
    713
    714 if( SCIPvarIsBinary(implvars[w]) )
    715 {
    716 /* the implied upper bound on a binary variable should not be trivial, otherwise we might globally fix
    717 * this variable to a wrong value
    718 *
    719 * @note it is possible that the implied bound is lower than zero, when the implied variable has
    720 * become binary during the search
    721 */
    722 assert(SCIPisFeasLE(scip, implbounds[w], 0.0));
    723 *foundbin = MIN(*foundbin, idx);
    724
    725 if( counts[idx] == 1 )
    726 {
    727 assert(*ncountnonzeros < 2*nvars);
    728 countnonzeros[*ncountnonzeros] = idx;
    729 ++(*ncountnonzeros);
    730 }
    731 }
    732 else
    733 {
    734 *foundnonbin = MIN(*foundnonbin, idx);
    735
    736 if( counts[idx] == 1 )
    737 {
    738 assert(*ncountnonzeros < 2*nvars);
    739 countnonzeros[*ncountnonzeros] = idx;
    740 ++(*ncountnonzeros);
    741 newbounds[idx] = implbounds[w];
    742 lastbounds[*nimplidx] = SCIP_INVALID;
    743 }
    744 else if( newbounds[idx] < implbounds[w] )
    745 {
    746 lastbounds[*nimplidx] = newbounds[idx];
    747 newbounds[idx] = implbounds[w];
    748 }
    749 else
    750 lastbounds[*nimplidx] = SCIP_INVALID;
    751 }
    752
    753 implidx[*nimplidx] = idx;
    754 ++(*nimplidx);
    755 }
    756 }
    757 else
    758 {
    759 SCIP_Bool redundant;
    760
    761 assert(counts[idx] <= pos - nredvars + 1);
    762
    763 /* set variable 'var' with bound implies other set variable 'implvars[w]' with a non-worse bound than the
    764 * bound so we can remove the set variable 'var'
    765 */
    766 if( issetvar[idx] > 0 && bounds[issetvar[idx] - 1] <= implbounds[w] )
    767 {
    768 SCIPdebugMsg(scip, "set variable <%s> %s %g implies other set variable <%s> %s %g (%g)\n",
    769 SCIPvarGetName(var), boundtypes[pos] ? "<=" : ">=", bounds[pos], SCIPvarGetName(implvars[w]),
    770 ">=", implbounds[w], bounds[issetvar[idx] - 1]);
    771
    772 issetvar[varidx] = -1;
    773 break;
    774 }
    775
    776 /* ignore implications that are redundant with respect to the current global bounds (see #2888) */
    777 redundant = SCIPisGE(scip, SCIPvarGetLbGlobal(implvars[w]), implbounds[w]);
    778
    779 /* update implication counter */
    780 if( counts[idx] == pos - nredvars && !redundant )
    781 {
    782 ++counts[idx];
    783
    784 if( SCIPvarIsBinary(implvars[w]) )
    785 {
    786 /* the implied lower bound on a binary variable should not be trivial, otherwise we might globally fix
    787 * this variable to a wrong value
    788 *
    789 * @note is is possible that the implied bound is greater than one, when the implied variable has
    790 * become binary during the search
    791 */
    792 assert(SCIPisFeasGE(scip, implbounds[w], 1.0));
    793 *foundbin = MIN(*foundbin, idx);
    794
    795 if( counts[idx] == 1 )
    796 {
    797 assert(*ncountnonzeros < 2*nvars);
    798 countnonzeros[*ncountnonzeros] = idx;
    799 ++(*ncountnonzeros);
    800 }
    801 }
    802 else
    803 {
    804 *foundnonbin = MIN(*foundnonbin, idx);
    805
    806 if( counts[idx] == 1 )
    807 {
    808 assert(*ncountnonzeros < 2*nvars);
    809 countnonzeros[*ncountnonzeros] = idx;
    810 ++(*ncountnonzeros);
    811 newbounds[idx] = implbounds[w];
    812 lastbounds[*nimplidx] = SCIP_INVALID;
    813 }
    814 else if( newbounds[idx] > implbounds[w] )
    815 {
    816 lastbounds[*nimplidx] = newbounds[idx];
    817 newbounds[idx] = implbounds[w];
    818 }
    819 else
    820 lastbounds[*nimplidx] = SCIP_INVALID;
    821 }
    822
    823 implidx[*nimplidx] = idx;
    824 ++(*nimplidx);
    825 }
    826 }
    827 }
    828 }
    829}
    830
    831/** collect clique data on binary variables for variable set reduction and global bound implications */
    832static
    834 SCIP_VAR* var, /**< set variable */
    835 int varidx, /**< for lower bound set variable index, for upper bound set variable index
    836 * + number of variables
    837 */
    838 int pos, /**< variables's position in bdchinfos */
    839 int nredvars, /**< number of reduced variables so far */
    840 SCIP_Bool value, /**< value used for clique and implication info */
    841 SCIP_Real* bounds, /**< array of bounds where one of them must be fullfilled */
    842 SCIP_Bool* boundtypes, /**< array of bound types */
    843 SCIP_Real* newbounds, /**< array of implied bounds(, size is two times number of variables, first
    844 * half for implied lower bounds, second for implied upper bounds)
    845 */
    846 int* counts, /**< array of number of implication on a bound (, size is two times number of
    847 * variables, first half for implied lower bounds, second for implied upper
    848 * bounds)
    849 */
    850 int* countnonzeros, /**< array to store the indices of non-zero entries in the counts array */
    851 int* ncountnonzeros, /**< pointer to store the number of non-zero entries in the counts array */
    852 int* issetvar, /**< array containing for set variables the position in the current set, or
    853 * 0 if it is not a set variable, or -1, if it is a redundant (i.e. implies
    854 * another set variable) set variable
    855 * (the size of the array is two times the number of variables, first half
    856 * for implied lower bounds, second for implied upper bounds)
    857 */
    858 int nvars, /**< number of problem variables */
    859 int* foundbin, /**< pointer to store the lowest index of a binary implication variable when found */
    860 int* implidx, /**< array to store the variable indices (for upper bound 'nvars' is added
    861 * to the index) which are implied
    862 */
    863 int* nimplidx /**< pointer to store the number of implied variables */
    864 )
    865{
    866 SCIP_CLIQUE** cliques;
    867 SCIP_VAR** clqvars;
    868 SCIP_Bool* clqvalues;
    869 int idx;
    870 int c;
    871 int w;
    872
    873 assert(var != NULL);
    874 assert(SCIPvarIsBinary(var));
    875 assert(varidx >= 0);
    876 assert(pos >= 0);
    877 assert(bounds != NULL);
    878 assert(boundtypes != NULL);
    879 assert(newbounds != NULL);
    880 assert(counts != NULL);
    881 assert(issetvar != NULL);
    882 assert(2 * nvars > varidx);
    883 assert(foundbin != NULL);
    884 assert(implidx != NULL);
    885 assert(nimplidx != NULL);
    886
    887 /* implication counter cannot exceed number implication variables */
    888 assert(counts[varidx] <= pos - nredvars);
    889
    890 /* if the set variable is not yet redundant we might increase the self implication counter */
    891 if( issetvar[varidx] > 0 )
    892 {
    893 /* update implication counter for set variables */
    894 if( counts[varidx] == pos - nredvars )
    895 {
    896 ++counts[varidx];
    897 *foundbin = MIN(*foundbin, varidx);
    898
    899 if( counts[varidx] == 1 )
    900 {
    901 assert(*ncountnonzeros < 2*nvars);
    902 countnonzeros[*ncountnonzeros] = varidx;
    903 ++(*ncountnonzeros);
    904 }
    905
    906 implidx[*nimplidx] = varidx;
    907 ++(*nimplidx);
    908 }
    909 }
    910
    911 cliques = SCIPvarGetCliques(var, value);
    912
    913 /* update implication counter on all by cliques implied variables */
    914 for( c = SCIPvarGetNCliques(var, value) - 1; c >= 0; --c )
    915 {
    916 clqvars = SCIPcliqueGetVars(cliques[c]);
    917 clqvalues = SCIPcliqueGetValues(cliques[c]);
    918
    919 for( w = SCIPcliqueGetNVars(cliques[c]) - 1; w >= 0; --w )
    920 {
    921 /* already handle self-implication and do not look at fixed variables */
    922 if( clqvars[w] == var || SCIPvarGetLbGlobal(clqvars[w]) > 0.5 || SCIPvarGetUbGlobal(clqvars[w]) < 0.5 )
    923 continue;
    924
    925 idx = SCIPvarGetProbindex(clqvars[w]);
    926 assert(idx >= 0);
    927
    928 if( clqvalues[w] )
    929 idx += nvars;
    930
    931 assert(counts[idx] <= pos - nredvars + 1);
    932
    933 /* set variable 'var' with bound implies other set variable 'clqvars[w]' with corresponding set bound so we can
    934 * remove the set variable 'var'
    935 */
    936 if( issetvar[idx] > 0 )
    937 {
    938 SCIPdebugMessage("set variable <%s> %s %g implies other set variable <%s> %s %g\n",
    939 SCIPvarGetName(var), boundtypes[pos] ? "<=" : ">=", bounds[pos], SCIPvarGetName(clqvars[w]),
    940 clqvalues[w] ? "<=" : ">=", clqvalues[w] ? 0.0 : 1.0);
    941
    942 issetvar[varidx] = -1;
    943 break;
    944 }
    945
    946 /* update implication counter */
    947 if( counts[idx] == pos - nredvars )
    948 {
    949 ++counts[idx];
    950 *foundbin = MIN(*foundbin, idx);
    951
    952 if( counts[idx] == 1 )
    953 {
    954 assert(*ncountnonzeros < 2*nvars);
    955 countnonzeros[*ncountnonzeros] = idx;
    956 ++(*ncountnonzeros);
    957 }
    958
    959 implidx[*nimplidx] = idx;
    960 ++(*nimplidx);
    961 }
    962 }
    963 }
    964}
    965
    966
    967
    968/*
    969 * presolving methods
    970 */
    971
    972#define CLEARRATIO 0.8
    973
    974/** try to reduce the necessary variable in a set of variables with corresponding bounds and boundtypes for which one
    975 * must be fulfilled
    976 *
    977 * e.g. a set of logicor or bounddisjunctive constraint variables would be such a set
    978 *
    979 * consider the following set:
    980 *
    981 * x1 >= 1, x2 >= 3, x3 >= 1, x4 <= 0
    982 *
    983 * by (global) implication data (cliques, implications, and variable bounds) we have also the following implications
    984 * given:
    985 *
    986 * x1 >= 1 => x3 >= 1
    987 * x2 >= 2 => x3 >= 1
    988 * x4 <= 0 => x1 >= 1
    989 *
    990 * Because of the last implication x4 is redundant, because x1 >= 1 would also be fulfilled in the variable set, so we
    991 * can reduce the set by x4.
    992 * Also, the both other implications and x3 >= 1 (in the given variable set) all imply exactly x3 >= 1, so we tighten
    993 * the global lower bound of x3 to 1 and the set of variables gets redundant.
    994 */
    996 SCIP* scip, /**< SCIP data structure */
    997 SCIP_VAR** vars, /**< variables array for which at least one must be fulfilled in the
    998 * following bounds and boundtypes */
    999 SCIP_Real* bounds, /**< bounds array for which at least one must be fulfilled */
    1000 SCIP_Bool* boundtypes, /**< boundtypes array (TRUE == SCIP_BOUNDTYPE_UPPER, FALSE == SCIP_BOUNDTYPE_LOWER)
    1001 * for which at least one must be fulfilled */
    1002 SCIP_Bool* redundants, /**< array which be filled and then indicate if a variable in the set is redundant */
    1003 int nvars, /**< number of variables */
    1004 int* nredvars, /**< pointer to store how many variables can be removed */
    1005 int* nglobalred, /**< pointer to store number of global reductions on variable bounds found
    1006 * through this set of variables */
    1007 SCIP_Bool* setredundant, /**< pointer to store if we found a global reduction on a variable which was part
    1008 * of the given set of variables, this makes this disjunction redundant */
    1009 SCIP_Bool* glbinfeas, /**< pointer to store if global infeasibility was detected */
    1010 SCIP_Bool fullshortening /**< do we want to try the shortening procedure over the whole set (which might be expensive) */
    1011 )
    1012{
    1013 SCIP_Real* newbounds; /* array saving all overall implied global bounds, first nprobvars for lower bound, second
    1014 * nprobvars for upper bound
    1015 */
    1016 SCIP_Real* lastbounds;/* temporary array to remember last implied bounds before taken the current variable into
    1017 * account, first nprobvars for lower bound, second nprobvars for upper bound
    1018 *
    1019 * this array is used when a set variable got redundant, because it implies another set
    1020 * variable, and we need to correct the counts array
    1021 */
    1022 int* issetvar; /* array for mapping from a problem variable to the position in the variable set (,pos + 1 in
    1023 * the variable set, 0 for no set variable, and -1 if this variable was removed from the set),
    1024 * first nprobvars for lower bound, second nprobvars for upper bound
    1025 */
    1026 int* counts; /* array saving number of implication by set variables, first nprobvars for lower bound, second
    1027 * nprobvars for upper bound
    1028 */
    1029 int* implidx; /* temporary array to remember all indices of implied variables by the current set variable
    1030 * looked at, first nprobvars for lower bound, second nprobvars for upper bound
    1031 *
    1032 * this array is used when a set variable got redundant, because it implies another set
    1033 * variable, and we need to correct the counts array
    1034 */
    1035 int* countnonzeros;
    1036
    1037 SCIP_VAR** probvars;
    1038 SCIP_VAR* var;
    1039 SCIP_Bool usebin = TRUE;
    1040 SCIP_Bool usenonbin = TRUE;
    1041 SCIP_Bool globalred = TRUE;
    1042 SCIP_Bool reducedset;
    1043 SCIP_Bool value;
    1044 SCIP_Bool implbinvarsexist;
    1045 int start = INT_MAX;
    1046 int nimplidx;
    1047 int foundbin;
    1048 int foundnonbin;
    1049 int varidx;
    1050 int nprobvars;
    1051 int nbinvars;
    1052 int nintegers;
    1053 int ncountnonzeros;
    1054 int maxcountnonzeros;
    1055 int w;
    1056 int v;
    1057
    1058 if( nvars == 0 )
    1059 return SCIP_OKAY;
    1060
    1061 assert(scip != NULL);
    1062 assert(vars != NULL);
    1063 assert(bounds != NULL);
    1064 assert(boundtypes != NULL);
    1065 assert(redundants != NULL);
    1066 assert(nredvars != NULL);
    1067 assert(nglobalred != NULL);
    1068 assert(setredundant != NULL);
    1069 assert(glbinfeas != NULL);
    1070 assert(scip->transprob != NULL);
    1071 nprobvars = SCIPprobGetNVars(scip->transprob);
    1072
    1073 /* allocate temporary memory */
    1074 SCIP_CALL( SCIPallocCleanBufferArray(scip, &issetvar, 2*nprobvars) ); /*lint !e647*/
    1075 SCIP_CALL( SCIPallocCleanBufferArray(scip, &counts, 2*nprobvars) ); /*lint !e647*/
    1076 SCIP_CALL( SCIPallocBufferArray(scip, &newbounds, 2*nprobvars) );
    1077 SCIP_CALL( SCIPallocBufferArray(scip, &lastbounds, 2*nprobvars) );
    1078 SCIP_CALL( SCIPallocBufferArray(scip, &implidx, 2*nprobvars) );
    1079 SCIP_CALL( SCIPallocBufferArray(scip, &countnonzeros, 2*nprobvars) );
    1080
    1081 *nredvars = 0;
    1082 *glbinfeas = FALSE;
    1083 ncountnonzeros = 0;
    1084
    1085 maxcountnonzeros = (int)(2*nprobvars*CLEARRATIO); /*lint !e790*/
    1086
    1087 /* initialize variable indices data */
    1088 for( v = 0; v < nvars; ++v )
    1089 {
    1090 varidx = SCIPvarGetProbindex(vars[v]);
    1091 assert(varidx >= 0);
    1092
    1093 if( boundtypes[v] )
    1094 varidx += nprobvars;
    1095
    1096 /* initialize issetvar array */
    1097 issetvar[varidx] = v+1;
    1098 }
    1099
    1100 /* check if implicit binary variables exist, because for these variables the implications can be stored in the
    1101 * variable bounds instead of the 'normal' implications
    1102 */
    1103 probvars = SCIPprobGetVars(scip->transprob);
    1104 assert(probvars != NULL);
    1105 nbinvars = SCIPprobGetNBinVars(scip->transprob);
    1106 nintegers = SCIPprobGetNVars(scip->transprob) - SCIPprobGetNContVars(scip->transprob);
    1107 assert(nintegers >= nbinvars);
    1108 implbinvarsexist = FALSE;
    1109
    1110 for( v = nintegers - 1; v >= nbinvars; --v )
    1111 {
    1112 if( SCIPvarIsBinary(probvars[v]) )
    1113 {
    1114 implbinvarsexist = TRUE;
    1115 break;
    1116 }
    1117 }
    1118
    1119#ifdef SCIP_DISABLED_CODE
    1120 /* @todo do the cleanup here rather than before calling SCIPshrinkDisjunctiveVarSet()? */
    1121 if( usebin )
    1122 {
    1123 SCIP_Bool infeasible;
    1124
    1125 SCIP_CALL( SCIPcleanupCliques(scip, &infeasible) );
    1126 }
    1127#endif
    1128
    1129 /* check for same implicit binary variables */
    1130 for( v = 0; v < nvars; ++v )
    1131 {
    1132 var = vars[v];
    1133
    1134 foundbin = INT_MAX;
    1135 foundnonbin = INT_MAX;
    1136 reducedset = FALSE;
    1137 nimplidx = 0;
    1138
    1139 value = (!boundtypes[v]);
    1140
    1141 varidx = SCIPvarGetProbindex(var);
    1142 assert(varidx >= 0);
    1143
    1144 if( !value )
    1145 varidx += nprobvars;
    1146
    1147 if( usebin )
    1148 {
    1149 /* collect clique data on binary variables */
    1150 if( SCIPvarIsBinary(var) )
    1151 {
    1152 collectBinaryCliqueData(var, varidx, v, *nredvars, value, bounds, boundtypes, newbounds, counts, countnonzeros,
    1153 &ncountnonzeros, issetvar, nprobvars, &foundbin, implidx, &nimplidx);
    1154 }
    1155 }
    1156
    1157 /* only variable which have the vartype SCIP_VARTYPE_BINARY have implications, otherwise the implications are
    1158 * saved as variable bounds
    1159 *
    1160 * we only check binary to non-binary implications if we can detect further implications which either lead to
    1161 * global reductions or to redundant set variables
    1162 */
    1163 if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && !SCIPvarIsImpliedIntegral(var) && ( usenonbin || ( usebin && implbinvarsexist ) ) )
    1164 {
    1165 collectNonBinaryImplicationData(scip, var, varidx, v, *nredvars, value, bounds, boundtypes, newbounds, counts,
    1166 countnonzeros, &ncountnonzeros, issetvar, nprobvars, &foundbin, &foundnonbin, implidx, &nimplidx, lastbounds);
    1167 }
    1168 /* only variable which have the vartype != SCIP_VARTYPE_BINARY have variable bounds
    1169 *
    1170 * we only check the variable bounds if we can detect further implications which either lead to global reductions
    1171 * or to redundant set variables
    1172 */
    1173 else if( ( SCIPvarGetType(var) != SCIP_VARTYPE_BINARY || SCIPvarIsImpliedIntegral(var) ) && ( usenonbin || ( usebin && implbinvarsexist ) ) )
    1174 {
    1175 collectNonBinaryVBoundData(scip, var, varidx, v, *nredvars, bounds, boundtypes, newbounds, counts, countnonzeros,
    1176 &ncountnonzeros, issetvar, nprobvars, &foundbin, &foundnonbin, implidx, &nimplidx, lastbounds);
    1177 }
    1178
    1179 /* reduce implication counters on all variables which are implied by a variable now marked as redundant */
    1180 if( issetvar[varidx] < 0 )
    1181 {
    1182 int probidx;
    1183
    1184 SCIPdebugMsg(scip, "marked variable <%s> as redundant variable in variable set\n", SCIPvarGetName(var));
    1185
    1186 /* correct implication counters and bounds, if the redundant variable implies other variables we need to reduce
    1187 * the counter and get the last bounds before this implication
    1188 */
    1189 for( w = nimplidx - 1; w >= 0; --w )
    1190 {
    1191 assert(implidx[w] < 2 * nprobvars);
    1192 assert(counts[implidx[w]] == v - (*nredvars) + 1);
    1193
    1194 --counts[implidx[w]];
    1195
    1196 if( implidx[w] == countnonzeros[ncountnonzeros-1] && counts[implidx[w]] == 0 )
    1197 --ncountnonzeros;
    1198
    1199 probidx = implidx[w] < nprobvars ? implidx[w] : implidx[w] - nprobvars;
    1200 /* only for non-binary variables we need to correct the bounds */
    1201 if( !SCIPvarIsBinary(probvars[probidx]) && lastbounds[w] != SCIP_INVALID )/*lint !e777*/
    1202 newbounds[implidx[w]] = lastbounds[w];
    1203 }
    1204
    1205 reducedset = TRUE;
    1206 ++(*nredvars);
    1207 }
    1208
    1209 /* check if we want to shorten the whole set of variables, or terminate early if we did not find any further
    1210 * implication
    1211 */
    1212 if( !fullshortening )
    1213 {
    1214 /* check if it makes sense to look for further binary implications */
    1215 if( foundbin < INT_MAX && !reducedset )
    1216 usebin = FALSE;
    1217 /* check if it makes sense to look for further non-binary implications */
    1218 if( foundnonbin < INT_MAX && !reducedset )
    1219 usenonbin = FALSE;
    1220 }
    1221
    1222 /* are global reductions still possible */
    1223 globalred = globalred && (foundbin < INT_MAX || foundnonbin < INT_MAX);
    1224
    1225 /* remember the first possible position for a global bound change */
    1226 if( globalred )
    1227 {
    1228 /* get correct variable index(, we added nprobvars for the upper bound implication) */
    1229 if( foundbin < INT_MAX && foundbin >= nprobvars )
    1230 foundbin -= nprobvars;
    1231
    1232 /* get correct variable index(, we added nprobvars for the upper bound implication) */
    1233 if( foundnonbin < INT_MAX && foundnonbin >= nprobvars )
    1234 foundnonbin -= nprobvars;
    1235
    1236 if( start > foundbin )
    1237 start = foundbin;
    1238
    1239 if( start > foundnonbin )
    1240 start = foundnonbin;
    1241 }
    1242 else
    1243 start = INT_MAX;
    1244
    1245 /* check if it can find any global implications anymore */
    1246 if( !usebin && !usenonbin )
    1247 break;
    1248 }
    1249
    1250 /* remove redundant set variables */
    1251 if( *nredvars > 0 )
    1252 {
    1253#ifndef NDEBUG
    1254 int nreds = 0;
    1255#endif
    1256
    1257 for( v = nvars - 1; v >= 0; --v )
    1258 {
    1259 var = vars[v];
    1260
    1261 varidx = SCIPvarGetProbindex(var);
    1262 assert(varidx >= 0);
    1263
    1264 if( boundtypes[v] )
    1265 varidx += nprobvars;
    1266
    1267 /* if set variable was marked to be redundant remove it */
    1268 if( issetvar[varidx] < 0 )
    1269 {
    1270 SCIPdebugMsg(scip, "mark redundant variable <%s> to be removed from variable set\n", SCIPvarGetName(var));
    1271
    1272 redundants[v] = TRUE;
    1273#ifndef NDEBUG
    1274 ++nreds;
    1275#endif
    1276 }
    1277 }
    1278 assert((*nredvars) == nreds);
    1279 }
    1280
    1281 /* if we found some global boundchanges, we perform then now */
    1282 if( globalred )
    1283 {
    1284 SCIPdebugMsg(scip, "variable set led to global reductions (in %s)\n", SCIPprobGetName(scip->transprob));
    1285
    1286 assert(start < nprobvars);
    1287
    1288 /* check for same implicit binary variables */
    1289 for( v = start; v < nprobvars; ++v )
    1290 {
    1291 var = probvars[v];
    1292 assert(var != NULL);
    1293
    1294 assert(counts[v] <= nvars);
    1295 assert(counts[nprobvars + v] <= nvars);
    1296
    1297 if( counts[v] + (*nredvars) == nvars )
    1298 {
    1299 if( SCIPvarIsBinary(var) )
    1300 {
    1301 SCIPdebugMsg(scip, "can fix variable %s [%g, %g] to 1.0\n", SCIPvarGetName(var),
    1303
    1304 if( SCIPvarGetLbGlobal(var) < 0.5 )
    1305 {
    1306 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat,
    1307 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand,
    1308 scip->eventqueue, scip->eventfilter, scip->cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER,
    1309 FALSE) );
    1310
    1311 assert(SCIPvarGetLbGlobal(var) > 0.5 || scip->tree->npendingbdchgs > 0);
    1312
    1313 ++(*nglobalred);
    1314
    1315 if( issetvar[v] > 0 )
    1316 *setredundant = TRUE;
    1317 }
    1318 }
    1319 else
    1320 {
    1321 SCIPdebugMsg(scip, "can tighten lower bound variable %s [%g, %g] to %g\n", SCIPvarGetName(var),
    1322 SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var), newbounds[v]);
    1323
    1324 /* the new lower bound is greater than the global upper bound => the problem is global infeasible */
    1325 if( SCIPisLT(scip, SCIPvarGetUbGlobal(var), newbounds[v]) )
    1326 {
    1327 SCIPdebugMsg(scip, "-> global infeasibility proven.\n");
    1328
    1329 *glbinfeas = TRUE;
    1330 break;
    1331 }
    1332
    1333 if( SCIPisLT(scip, SCIPvarGetLbGlobal(var), newbounds[v]) )
    1334 {
    1335 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat,
    1336 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand,
    1337 scip->eventqueue, scip->eventfilter, scip->cliquetable, var, newbounds[v],
    1339
    1340 ++(*nglobalred);
    1341
    1342 if( issetvar[v] > 0 && newbounds[v] >= bounds[issetvar[v] - 1] )
    1343 *setredundant = TRUE;
    1344 }
    1345 }
    1346 }
    1347 else if( counts[nprobvars + v] + (*nredvars) == nvars )
    1348 {
    1349 if( SCIPvarIsBinary(var) )
    1350 {
    1351 SCIPdebugMsg(scip, "can fix variable %s [%g, %g] to 0.0\n", SCIPvarGetName(var),
    1353
    1354 if( SCIPvarGetUbGlobal(var) > 0.5 )
    1355 {
    1356 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat,
    1357 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue,
    1358 scip->eventfilter, scip->cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
    1359
    1360 assert(SCIPvarGetUbGlobal(var) < 0.5 || scip->tree->npendingbdchgs > 0);
    1361
    1362 ++(*nglobalred);
    1363
    1364 if( issetvar[nprobvars + v] > 0 )
    1365 *setredundant = TRUE;
    1366 }
    1367 }
    1368 else
    1369 {
    1370 int idx = nprobvars + v;
    1371
    1372 SCIPdebugMsg(scip, "can tighten upper bound variable %s [%g, %g] to %g\n", SCIPvarGetName(var),
    1373 SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var), newbounds[idx]);
    1374
    1375 /* the new upper bound is small than the global upper bound => the problem is global infeasible */
    1376 if( SCIPisGT(scip, SCIPvarGetLbGlobal(var), newbounds[idx]) )
    1377 {
    1378 SCIPdebugMsg(scip, "-> global infeasibility proven.\n");
    1379
    1380 *glbinfeas = TRUE;
    1381 break;
    1382 }
    1383
    1384 if( SCIPisGT(scip, SCIPvarGetUbGlobal(var), newbounds[idx]) )
    1385 {
    1386 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat,
    1387 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue,
    1388 scip->eventfilter, scip->cliquetable, var, newbounds[idx], SCIP_BOUNDTYPE_UPPER, FALSE) );
    1389
    1390 ++(*nglobalred);
    1391
    1392 if( issetvar[idx] > 0 && newbounds[idx] <= bounds[issetvar[idx] - 1] )
    1393 *setredundant = TRUE;
    1394 }
    1395 }
    1396 }
    1397 }
    1398 }
    1399
    1400 /* reset issetvar array to 0 */
    1401 for( v = 0; v < nvars; ++v )
    1402 {
    1403 varidx = SCIPvarGetProbindex(vars[v]);
    1404 assert(varidx >= 0);
    1405
    1406 if( boundtypes[v] )
    1407 varidx += nprobvars;
    1408
    1409 issetvar[varidx] = 0;
    1410 }
    1411
    1412 if( ncountnonzeros >= maxcountnonzeros )
    1413 {
    1414 BMSclearMemoryArray(counts, 2*nprobvars);
    1415 }
    1416 else
    1417 {
    1418 while( --ncountnonzeros >= 0 )
    1419 counts[countnonzeros[ncountnonzeros]] = 0;
    1420 }
    1421
    1422 SCIPfreeBufferArray(scip, &countnonzeros);
    1423 SCIPfreeBufferArray(scip, &implidx);
    1424 SCIPfreeBufferArray(scip, &lastbounds);
    1425 SCIPfreeBufferArray(scip, &newbounds);
    1427 SCIPfreeCleanBufferArray(scip, &issetvar);
    1428
    1429 return SCIP_OKAY;
    1430}
    SCIP_VAR * w
    Definition: circlepacking.c:67
    #define NULL
    Definition: def.h:248
    #define SCIP_INVALID
    Definition: def.h:178
    #define SCIP_Bool
    Definition: def.h:91
    #define MIN(x, y)
    Definition: def.h:224
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define SCIP_CALL(x)
    Definition: def.h:355
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    #define SCIPfreeCleanBufferArray(scip, ptr)
    Definition: scip_mem.h:146
    #define SCIPallocCleanBufferArray(scip, ptr, num)
    Definition: scip_mem.h:142
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    SCIP_RETCODE SCIPshrinkDisjunctiveVarSet(SCIP *scip, SCIP_VAR **vars, SCIP_Real *bounds, SCIP_Bool *boundtypes, SCIP_Bool *redundants, int nvars, int *nredvars, int *nglobalred, SCIP_Bool *setredundant, SCIP_Bool *glbinfeas, SCIP_Bool fullshortening)
    Definition: presolve.c:995
    SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    int SCIPvarGetNVlbs(SCIP_VAR *var)
    Definition: var.c:24482
    SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
    Definition: var.c:24504
    SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
    Definition: var.c:23478
    int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
    Definition: var.c:24568
    SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
    Definition: var.c:23498
    SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
    Definition: var.c:23453
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24142
    SCIP_VAR ** SCIPvarGetImplVars(SCIP_VAR *var, SCIP_Bool varfixing)
    Definition: var.c:24585
    int SCIPvarGetProbindex(SCIP_VAR *var)
    Definition: var.c:23662
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    SCIP_RETCODE SCIPcleanupCliques(SCIP *scip, SCIP_Bool *infeasible)
    Definition: scip_var.c:9469
    SCIP_Real * SCIPvarGetVlbConstants(SCIP_VAR *var)
    Definition: var.c:24514
    int SCIPvarGetNVubs(SCIP_VAR *var)
    Definition: var.c:24524
    SCIP_Real * SCIPvarGetImplBounds(SCIP_VAR *var, SCIP_Bool varfixing)
    Definition: var.c:24614
    int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
    Definition: var.c:24642
    SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
    Definition: var.c:24494
    SCIP_CLIQUE ** SCIPvarGetCliques(SCIP_VAR *var, SCIP_Bool varfixing)
    Definition: var.c:24653
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24120
    SCIP_Real * SCIPvarGetVubConstants(SCIP_VAR *var)
    Definition: var.c:24556
    SCIP_VAR ** SCIPvarGetVubVars(SCIP_VAR *var)
    Definition: var.c:24536
    SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
    Definition: var.c:24546
    SCIP_BOUNDTYPE * SCIPvarGetImplTypes(SCIP_VAR *var, SCIP_Bool varfixing)
    Definition: var.c:24600
    SCIP_VAR ** SCIPcliqueGetVars(SCIP_CLIQUE *clique)
    Definition: implics.c:3384
    int SCIPcliqueGetNVars(SCIP_CLIQUE *clique)
    Definition: implics.c:3374
    SCIP_Bool * SCIPcliqueGetValues(SCIP_CLIQUE *clique)
    Definition: implics.c:3396
    memory allocation routines
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    static void collectNonBinaryVBoundData(SCIP *scip, SCIP_VAR *var, int varidx, int pos, int nredvars, SCIP_Real *bounds, SCIP_Bool *boundtypes, SCIP_Real *newbounds, int *counts, int *countnonzeros, int *ncountnonzeros, int *issetvar, int nvars, int *foundbin, int *foundnonbin, int *implidx, int *nimplidx, SCIP_Real *lastbounds)
    Definition: presolve.c:57
    static void collectBinaryCliqueData(SCIP_VAR *var, int varidx, int pos, int nredvars, SCIP_Bool value, SCIP_Real *bounds, SCIP_Bool *boundtypes, SCIP_Real *newbounds, int *counts, int *countnonzeros, int *ncountnonzeros, int *issetvar, int nvars, int *foundbin, int *implidx, int *nimplidx)
    Definition: presolve.c:833
    #define CLEARRATIO
    Definition: presolve.c:972
    static void collectNonBinaryImplicationData(SCIP *scip, SCIP_VAR *var, int varidx, int pos, int nredvars, SCIP_Bool value, SCIP_Real *bounds, SCIP_Bool *boundtypes, SCIP_Real *newbounds, int *counts, int *countnonzeros, int *ncountnonzeros, int *issetvar, int nvars, int *foundbin, int *foundnonbin, int *implidx, int *nimplidx, SCIP_Real *lastbounds)
    Definition: presolve.c:595
    methods commonly used for presolving
    int SCIPprobGetNContVars(SCIP_PROB *prob)
    Definition: prob.c:2904
    const char * SCIPprobGetName(SCIP_PROB *prob)
    Definition: prob.c:2859
    int SCIPprobGetNVars(SCIP_PROB *prob)
    Definition: prob.c:2868
    int SCIPprobGetNBinVars(SCIP_PROB *prob)
    Definition: prob.c:2877
    SCIP_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
    Definition: prob.c:2913
    internal methods for storing and manipulating the main problem
    public methods for implications, variable bounds, and cliques
    public methods for message output
    #define SCIPdebugMessage
    Definition: pub_message.h:96
    public methods for problem variables
    public methods for memory management
    public methods for message handling
    public methods for numerical tolerances
    public methods for the branch-and-bound tree
    datastructures for block memory pools and memory buffers
    SCIP main data structure.
    SCIP_RETCODE SCIPnodeAddBoundchg(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype, SCIP_Bool probingchange)
    Definition: tree.c:2539
    internal methods for branch and bound tree
    @ 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_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_VARTYPE_BINARY
    Definition: type_var.h:64