Scippy

    SCIP

    Solving Constraint Integer Programs

    presol_tworowbnd.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 presol_tworowbnd.c
    26 * @ingroup DEFPLUGINS_PRESOL
    27 * @brief do bound tightening by using two rows
    28 * @author Dieter Weninger
    29 * @author Patrick Gemander
    30 *
    31 * Perform bound tightening on two inequalities with some common variables.
    32 * Two possible methods are being used.
    33 *
    34 * 1. LP-bound
    35 * Let two constraints be given:
    36 * \f{eqnarray*}{
    37 * A_{iR} x_R + A_{iS} x_S \geq b_i\\
    38 * A_{kR} x_R + A_{kT} x_T \geq b_k
    39 * \f}
    40 * with \f$N\f$ the set of variable indexes, \f$R \subseteq N\f$, \f$S \subseteq N\f$, \f$T \subseteq N\f$,
    41 * \f$R \cap S = \emptyset\f$, \f$R \cap T = \emptyset\f$, \f$S \cap T = \emptyset\f$ and row indices \f$i \not= k\f$.
    42 *
    43 * Let \f$\ell\f$ and \f$u\f$ be bound vectors for x and solve the following two LPs
    44 * \f{eqnarray*}{
    45 * L = \min \{ A_{kR} x_R : A_{iR} x_R + A_{iS} x_S \geq b_i, \ell \leq x \leq u \}\\
    46 * U = \max \{ A_{kR} x_R : A_{iR} x_R + A_{iS} x_S \geq b_i, \ell \leq x \leq u \}
    47 * \f}
    48 * and use \f$L\f$ and \f$U\f$ for getting bounds on \f$x_T\f$.
    49 *
    50 * If \f$L + \mbox{infimum}(A_{kT}x_T) \geq b_k\f$, then the second constraint above is redundant.
    51 *
    52 * More details can be found in
    53 * - Chen W. et. al "Two-row and two-column mixed-integer presolve using hashing-based pairing methods"
    54 */
    55
    56/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    57
    58/*
    59 * Additional debug defines in this presolver
    60 * SCIP_DEBUG_HASHING
    61 * SCIP_DEBUG_BOUNDS
    62 * SCIP_DEBUG_SINGLEROWLP
    63 */
    64
    65#include <assert.h>
    66
    67#include "scip/cons_linear.h"
    68#include "scip/scipdefplugins.h"
    69#include "scip/pub_matrix.h"
    71#include <string.h>
    72
    73#define PRESOL_NAME "tworowbnd"
    74#define PRESOL_DESC "do bound tigthening by using two rows"
    75#define PRESOL_PRIORITY -2000 /**< priority of the presolver (>= 0: before, < 0: after constraint handlers); combined with propagators */
    76#define PRESOL_MAXROUNDS 0 /**< maximal number of presolving rounds the presolver participates in (-1: no limit) */
    77#define PRESOL_TIMING SCIP_PRESOLTIMING_EXHAUSTIVE /* timing of the presolver (fast, medium, or exhaustive) */
    78
    79#define DEFAULT_ENABLECOPY TRUE /**< should tworowbnd presolver be copied to sub-SCIPs? */
    80#define DEFAULT_MAXCONSIDEREDNONZEROS 100 /**< maximal number of considered non-zeros within one row (-1: no limit) */
    81#define DEFAULT_MAXRETRIEVEFAILS 1000 /**< maximal number of consecutive useless hashtable retrieves */
    82#define DEFAULT_MAXCOMBINEFAILS 1000 /**< maximal number of consecutive useless row combines */
    83#define DEFAULT_MAXHASHFAC 10 /**< maximal number of hashlist entries as multiple of number of rows in the problem (-1: no limit) */
    84#define DEFAULT_MAXPAIRFAC 1 /**< maximal number of processed row pairs as multiple of the number of rows in the problem (-1: no limit) */
    85
    86/*
    87 * Data structures
    88 */
    89
    90/** presolver data */
    91struct SCIP_PresolData
    92{
    93 int maxpairfac; /**< maximal number of processed row pairs as multiple of the number of rows in the problem (-1: no limit) */
    94 int maxhashfac; /**< maximal number of hashlist entries as multiple of number of rows in the problem (-1: no limit) */
    95 int maxretrievefails; /**< maximal number of consecutive useless hashtable retrieves */
    96 int maxcombinefails; /**< maximal number of consecutive useless row combines */
    97 int maxconsiderednonzeros; /**< maximal number of considered non-zeros within one row (-1: no limit) */
    98 int nchgbnds; /**< number of variable bounds changed by this presolver */
    99 int nuselessruns; /**< number of runs where this presolver did not apply any changes */
    100 SCIP_Bool enablecopy; /**< should tworowbnd presolver be copied to sub-SCIPs? */
    101};
    102
    103/** structure representing a pair of row indices; used for lookup in a hashtable */
    105{
    106 int row1idx; /**< first row index */
    107 int row2idx; /**< second row index */
    108};
    109
    110typedef struct RowPair ROWPAIR;
    111
    112
    113/*
    114 * Local methods
    115 */
    116
    117/** encode contents of a rowpair as void* pointer */
    118static
    120 ROWPAIR* rowpair /**< pointer to rowpair */
    121 )
    122{
    123 uint64_t a = (uint64_t)(long)rowpair->row1idx;
    124 uint64_t b = (uint64_t)(long)rowpair->row2idx;
    125 return (void*)((a << 32) | b);
    126}
    127
    128/** compute single positive int hashvalue for two ints */
    129static
    131 int idx1, /**< first integer index */
    132 int idx2 /**< second integer index */
    133 )
    134{
    135 uint32_t hash = SCIPhashTwo(idx1, idx2);
    136 return (int)(hash >> 1);
    137}
    138
    139/** add hash/rowidx pair to hashlist/rowidxlist */
    140static
    142 SCIP* scip, /**< SCIP datastructure */
    143 int* pos, /**< position of last entry added */
    144 int* listsize, /**< size of hashlist and rowidxlist */
    145 int** hashlist, /**< block memory array containing hashes */
    146 int** rowidxlist, /**< block memory array containing row indices */
    147 int hash, /**< hash to be inserted */
    148 int rowidx /**< row index to be inserted */
    149 )
    150{
    151 if( (*pos) >= (*listsize) )
    152 {
    153 int newsize = SCIPcalcMemGrowSize(scip, (*pos) + 1);
    154 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, hashlist, (*listsize), newsize) );
    155 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, rowidxlist, (*listsize), newsize) );
    156 (*listsize) = newsize;
    157 }
    158
    159 (*hashlist)[(*pos)] = hash;
    160 (*rowidxlist)[(*pos)] = rowidx;
    161 (*pos)++;
    162
    163 return SCIP_OKAY;
    164}
    165
    166/* Within a sorted list, get next block with same value
    167 * E.g. for [h1, h1, h1, h2, h2, h2, h2, h3,...] and end = 0
    168 * returns start = 0, end = 3
    169 * and on a second call with end = 3 on the same list
    170 * returns start = 3, end = 7.
    171 */
    172static
    174 int* list, /**< list of integers */
    175 int len, /**< length of list */
    176 int* start, /**< variable to contain start index of found block */
    177 int* end /**< variable to contain end index of found block */
    178 )
    179{
    180 int i;
    181 (*start) = (*end);
    182 i = (*end) + 1;
    183 while( i < len && list[i] == list[i - 1] )
    184 i++;
    185
    186 (*end) = i;
    187}
    188
    189/* Solve single-row LP of the form
    190 * min c^T x
    191 * s.t. a^T x >= b
    192 * lbs <= x <= ubs
    193 *
    194 * First, the problem is transformed such that
    195 * SCIPselectWeightedReal() can be applied, which
    196 * then solves the problem as a continuous knapsack
    197 * in linear time.
    198 */
    199static
    201 SCIP* scip, /**< SCIP data structure */
    202 SCIP_Real* a, /**< constraint coefficients */
    203 SCIP_Real b, /**< right hand side */
    204 SCIP_Real* c, /**< objective coefficients */
    205 SCIP_Real* lbs, /**< lower variable bounds */
    206 SCIP_Real* ubs, /**< upper variable bounds */
    207 int len, /**< length of arrays */
    208 SCIP_Real* obj, /**< objective value of solution */
    209 SCIP_Bool* solvable /**< status whether LP was solvable */
    210 )
    211{
    212 int i;
    213 int k;
    214 int nvars;
    215 SCIP_Real lb;
    216 SCIP_Real ub;
    217 SCIP_Real mincost;
    218 SCIP_Real maxgain;
    219
    220#ifdef SCIP_DEBUG_SINGLEROWLP
    221 SCIPdebugMsg(scip, "solving single row LP with %d variables\n", len);
    222#endif
    223
    224 nvars = 0;
    225 (*obj) = 0;
    226 (*solvable) = TRUE;
    227 mincost = SCIPinfinity(scip);
    228 maxgain = 0;
    229 for( i = 0; i < len; i++)
    230 {
    231 /* Handle variables with zero weight */
    232 if( SCIPisZero(scip, a[i]) )
    233 {
    234 /* a[i] = 0, c[i] > 0 */
    235 if( SCIPisPositive(scip, c[i]) )
    236 {
    237 if( SCIPisInfinity(scip, -lbs[i]) )
    238 {
    239 (*solvable) = FALSE;
    240 return SCIP_OKAY;
    241 }
    242 else
    243 (*obj) += c[i] * lbs[i];
    244 }
    245 /* a[i] = 0, c[i] < 0 */
    246 else if( SCIPisNegative(scip, c[i]) )
    247 {
    248 if( SCIPisInfinity(scip, ubs[i]) )
    249 {
    250 (*solvable) = FALSE;
    251 return SCIP_OKAY;
    252 }
    253 else
    254 (*obj) += c[i] * ubs[i];
    255 }
    256 /* Note that variables with a[i] = 0, c[i] = 0 can be ignored */
    257 continue;
    258 }
    259
    260 /* Handle free variables */
    261 if( SCIPisInfinity(scip, -lbs[i]) && SCIPisInfinity(scip, ubs[i]) )
    262 {
    263 /* The problem is unbounded */
    264 if( (SCIPisPositive(scip, c[i]) && SCIPisNegative(scip, a[i])) ||
    265 (SCIPisNegative(scip, c[i]) && SCIPisPositive(scip, a[i])) )
    266 {
    267 (*solvable) = FALSE;
    268 return SCIP_OKAY;
    269 }
    270 else
    271 {
    272 mincost = MIN(mincost, c[i] / a[i]);
    273 maxgain = MAX(maxgain, c[i] / a[i]);
    274 }
    275 continue;
    276 }
    277
    278 /* Swap variable orientation if lower bound is infinite */
    279 if( SCIPisInfinity(scip, -lbs[i]) )
    280 {
    281 c[i] = -c[i];
    282 a[i] = -a[i];
    283 lb = -ubs[i];
    284 ub = -lbs[i];
    285 }
    286 else
    287 {
    288 lb = lbs[i];
    289 ub = ubs[i];
    290 }
    291
    292 /* Handle variables with infinite upper bound */
    293 if( SCIPisInfinity(scip, ub) )
    294 {
    295 if( SCIPisPositive(scip, a[i]) )
    296 {
    297 /* a[i] > 0, c[i] >= 0 */
    298 if( !SCIPisNegative(scip, c[i]) )
    299 {
    300 mincost = MIN(mincost, c[i]/a[i]);
    301 }
    302 /* a[i] > 0, c[i] < 0 */
    303 else
    304 {
    305 (*solvable) = FALSE;
    306 return SCIP_OKAY;
    307 }
    308 }
    309 /* a[i] < 0, c[i] < 0 */
    310 else if( SCIPisNegative(scip, c[i]) )
    311 {
    312 maxgain = MAX(maxgain, c[i] / a[i]);
    313 }
    314 /* a[i] < 0, c[i] >= 0 results in dual fixing of this variable, which is included in the bound shift below */
    315
    316 /* Shift lower bound to zero */
    317 if( !SCIPisZero(scip, lb) )
    318 {
    319 (*obj) += c[i] * lb;
    320 b -= a[i] * lb;
    321 }
    322 continue;
    323 }
    324
    325 /* Handle fixed variables */
    326 if( SCIPisEQ(scip, lb, ub) )
    327 {
    328 (*obj) += c[i] * lb;
    329 b -= a[i] * lb;
    330 continue;
    331 }
    332
    333 /* Dual fixing for variables with finite bounds */
    334 if( !SCIPisNegative(scip, c[i]) && SCIPisNegative(scip, a[i]) )
    335 {
    336 (*obj) += c[i] * lb;
    337 b -= a[i] * lb;
    338 continue;
    339 }
    340 else if( !SCIPisPositive(scip, c[i]) && SCIPisPositive(scip, a[i]) )
    341 {
    342 (*obj) += c[i] * ub;
    343 b -= a[i] * ub;
    344 continue;
    345 }
    346
    347 assert(!SCIPisInfinity(scip, -lb));
    348 assert(!SCIPisInfinity(scip, ub));
    349
    350 /* At this point the variable has finite bounds and a[i],c[i] are both positive or both negative.
    351 * Normalize variable such that
    352 * 1. x_i \in [0,1]
    353 * 2. a[i] > 0
    354 * 3. c[i] >= 0
    355 * and calculate its "unit price" c[i]/a[i].
    356 */
    357 if( SCIPisNegative(scip, a[i]) )
    358 {
    359 c[i] = -c[i];
    360 a[i] = -a[i];
    361 lb = -ubs[i];
    362 ub = -lbs[i];
    363 }
    364
    365 /* All variables with a <= 0 have been handled and variables with a[i] = 0, c[i] = 0 ignored */
    366 assert(SCIPisPositive(scip, a[i]) && SCIPisPositive(scip, c[i]));
    367
    368 /* Adjust objective offset and b to shift lower bound to zero */
    369 (*obj) += c[i] * lb;
    370 b -= a[i] * lb;
    371
    372 /* Calculate unit price */
    373 c[nvars] = c[i] / a[i];
    374
    375 /* Normalize bound [0, ub] to [0,1] */
    376 a[nvars] = (ub - lb) * a[i];
    377 nvars++;
    378 }
    379
    380#ifdef SCIP_DEBUG_SINGLEROWLP
    381 SCIPdebugMsg(scip, "After preprocessing: obj = %g, b = %g, nvars = %d, mincost = %g, maxgain = %g\n", (*obj), b, nvars, mincost, maxgain);
    382#endif
    383
    384 /* Actual solving starts here.
    385 * If maxgain > 0 holds, we have a variable that can relax the constraint to an arbitrary degree while yielding
    386 * a certain profit per unit. This will be called downslack. If mincost < inf holds, we have a variable that can
    387 * always satisfy the constraint at a certain unit price. This will be called upslack.
    388 */
    389
    390 /* Problem is unbounded since the downslack variable yields higher gains than the upslack variable costs */
    391 if( SCIPisLT(scip, mincost, maxgain) )
    392 {
    393 (*solvable) = FALSE;
    394 return SCIP_OKAY;
    395 }
    396 /* Solution is trivial as we have slack variables of equal price for both directions */
    397 else if( SCIPisEQ(scip, mincost, maxgain) )
    398 {
    399 /* Use all elements with cost smaller than maxgain */
    400 for( i = 0; i < nvars; i++ )
    401 {
    402 if( SCIPisLT(scip, c[i], maxgain) )
    403 {
    404 (*obj) += c[i] * a[i];
    405 b -= a[i];
    406 }
    407 }
    408 /* Use slack variable to satisfy constraint */
    409 (*obj) += mincost * b;
    410 return SCIP_OKAY;
    411 }
    412 /* mincost > maxgain
    413 * In this case we need to solve the problem for the remaining variables with mincost > c[i] > maxgain.
    414 */
    415 else
    416 {
    417 /* Only keep variables that are cheaper than the upslack variable */
    418 if( !SCIPisInfinity(scip, mincost) )
    419 {
    420 k = 0;
    421 for( i = 0; i < nvars; i++ )
    422 {
    423 if( SCIPisLT(scip, c[i], mincost) )
    424 {
    425 c[k] = c[i];
    426 a[k] = a[i];
    427 k++;
    428 }
    429 }
    430 nvars = k;
    431 }
    432
    433 /* Exploit all variables that are cheaper than the downslack variable */
    434 if( !SCIPisZero(scip, maxgain) )
    435 {
    436 k = 0;
    437 for( i = 0; i < nvars; i++ )
    438 {
    439 if( SCIPisLE(scip, c[i], maxgain) )
    440 {
    441 (*obj) += c[i] * a[i];
    442 b -= a[i];
    443 }
    444 else
    445 {
    446 c[k] = c[i];
    447 a[k] = a[i];
    448 k++;
    449 }
    450 }
    451 if( !SCIPisPositive(scip, b) )
    452 {
    453 (*obj) += maxgain * b;
    454 return SCIP_OKAY;
    455 }
    456 nvars = k;
    457 }
    458
    459#ifdef SCIP_DEBUG_SINGLEROWLP
    460 SCIPdebugMsg(scip, "After exploiting slacks: obj = %g, nvars = %d\n", (*obj), nvars);
    461#endif
    462
    463 /* If there are no variables left we can trivially put together a solution or determine infeasibility */
    464 if( nvars == 0 )
    465 {
    466 if( !SCIPisInfinity(scip, mincost) )
    467 {
    468 (*obj) += mincost * b;
    469 return SCIP_OKAY;
    470 }
    471 else
    472 {
    473 (*solvable) = FALSE;
    474 return SCIP_OKAY;
    475 }
    476 }
    477 /* Solve the remaining part of the problem */
    478 else
    479 {
    480 assert(nvars > 0);
    481#ifdef SCIP_DEBUG_SINGLEROWLP
    482 for( i = 0; i < nvars; i++ )
    483 SCIPdebugMsg(scip, "c[%d] = %g, a[%d] = %g\n", i, c[i], i, a[i]);
    484#endif
    485
    486 SCIPselectWeightedReal(c, a, b, nvars, &k);
    487
    488#ifdef SCIP_DEBUG_SINGLEROWLP
    489 SCIPdebugMsg(scip, "k-mean = %g at index %d\n", c[k], k, b);
    490 for( i = 0; i < nvars; i++ )
    491 SCIPdebugMsg(scip, "c[%d] = %g, a[%d] = %g\n", i, c[i], i, a[i]);
    492#endif
    493
    494 /* Finalize objective value of solution. First we use all elements cheaper than the k-median */
    495 for( i = 0; i < k; i++ )
    496 {
    497 (*obj) += c[i] * a[i];
    498 b -= a[i];
    499 }
    500
    501#ifdef SCIP_DEBUG_SINGLEROWLP
    502 SCIPdebugMsg(scip, "LP is solved: b = %g\n", b);
    503#endif
    504
    505 /* If the constraint is not yet satisfied, we have to fix that */
    506 if( SCIPisPositive(scip, b) )
    507 {
    508 /* There exists an element to satisfy the constraint */
    509 if( k < nvars )
    510 {
    511 (*obj) += c[k] * b;
    512 return SCIP_OKAY;
    513 }
    514 /* There is an upslack variable to satisfy the constraint */
    515 else if( !SCIPisInfinity(scip, mincost) )
    516 {
    517#ifdef SCIP_DEBUG_SINGLEROWLP
    518 SCIPdebugMsg(scip, "We use %g units of upslack to satisfy the constraint\n", b);
    519#endif
    520 (*obj) += mincost * b;
    521 return SCIP_OKAY;
    522 }
    523 /* We cannot satisfy the constraint so the problem is infeasible */
    524 else
    525 {
    526 (*solvable) = FALSE;
    527 return SCIP_OKAY;
    528 }
    529 }
    530 /* The constraint is already satisfied, i.e. b <= 0 */
    531 else
    532 {
    533 return SCIP_OKAY;
    534 }
    535 }
    536 }
    537}
    538
    539/** Transform rows into single row LPs, solve them and and tighten bounds
    540 *
    541 * During transformation, create coefficient arrays where variables with a zero coefficient in both rows are ignored
    542 * and bring the LP in the form min c^T x, s.t. a^T x >= b, lbs <= x <= ubs.
    543 * These LPs are then solved and bounds tightened as described in LP-bound (see above).
    544 */
    545static
    547 SCIP* scip, /**< SCIP data structure */
    548 SCIP_MATRIX* matrix, /**< constraint matrix object, rows specified by row1idx/row2idx must be sorted */
    549 int row1idx, /**< index of first row */
    550 int row2idx, /**< index of second row */
    551 SCIP_Bool swaprow1, /**< should row1 <= rhs be used in addition to lhs <= row1 */
    552 SCIP_Bool swaprow2, /**< should row2 <= rhs be used in addition to lhs <= row2 */
    553 SCIP_Real* aoriginal, /**< buffer array for original constraint coefficients */
    554 SCIP_Real* acopy, /**< buffer array for coefficients adjusted to single-row LP to be solved */
    555 SCIP_Real* coriginal, /**< buffer array for original objective coefficients */
    556 SCIP_Real* ccopy, /**< buffer array for coefficients adjusted to single-row LP to be solved */
    557 SCIP_Bool* cangetbnd, /**< buffer array for flags of which variables a bound can be generated */
    558 SCIP_Real* lbs, /**< buffer array for lower bounds for single-row LP */
    559 SCIP_Real* ubs, /**< buffer array for upper bounds for single-row LP */
    560 SCIP_Real* newlbsoriginal, /**< buffer array for new lower bounds not adjusted to individual single-row LPs */
    561 SCIP_Real* newlbscopy, /**< buffer array for adjusted lower bounds */
    562 SCIP_Real* newubsoriginal, /**< buffer array for new upper bounds not adjusted to individual single-row LPs */
    563 SCIP_Real* newubscopy, /**< buffer array for adjusted upper bounds */
    564 SCIP_Bool* success, /**< return (success || "found better bounds") */
    565 SCIP_Bool* infeasible /**< we return (infeasible || "detected infeasibility") */
    566 )
    567{
    568 int i;
    569 int j;
    570 int idx1;
    571 int idx2;
    572 int row1len;
    573 int row2len;
    574 int* row1idxptr;
    575 int* row2idxptr;
    576 SCIP_Real* row1valptr;
    577 SCIP_Real* row2valptr;
    578 int nvars;
    579 SCIP_Real minact;
    580 SCIP_Real maxact;
    581 int maxinfs;
    582 int mininfs;
    583
    584 SCIP_Bool minsolvable;
    585 SCIP_Real minobj = SCIP_INVALID;
    586 SCIP_Bool maxsolvable;
    587 SCIP_Real maxobj;
    588 SCIP_Bool minswapsolvable;
    589 SCIP_Real minswapobj = 0.0;
    590 SCIP_Bool maxswapsolvable;
    591 SCIP_Real maxswapobj;
    592
    593 SCIP_Real newbnd;
    594
    595 assert(!swaprow1 || !SCIPisInfinity(scip, SCIPmatrixGetRowRhs(matrix, row1idx)));
    596 assert(!swaprow2 || !SCIPisInfinity(scip, SCIPmatrixGetRowRhs(matrix, row2idx)));
    597
    598 row1len = SCIPmatrixGetRowNNonzs(matrix, row1idx);
    599 row2len = SCIPmatrixGetRowNNonzs(matrix, row2idx);
    600 row1idxptr = SCIPmatrixGetRowIdxPtr(matrix, row1idx);
    601 row2idxptr = SCIPmatrixGetRowIdxPtr(matrix, row2idx);
    602 row1valptr = SCIPmatrixGetRowValPtr(matrix, row1idx);
    603 row2valptr = SCIPmatrixGetRowValPtr(matrix, row2idx);
    604
    605 /* Preprocess rows:
    606 * 1. Calculate minimal and maximal activity of variables not appearing in both rows,
    607 * as this represents the right-hand sides of the single-row LPs to be solved.
    608 * 2. Transform rows into format required by solveSingleRowLP where
    609 * first row represents the objective vector c and second row represents the constraint vector a.
    610 * 3. Determine for which variables new bounds can be calculated.
    611 */
    612 i = 0;
    613 j = 0;
    614 nvars = 0;
    615 mininfs = 0;
    616 maxinfs = 0;
    617 minact = 0;
    618 maxact = 0;
    619 while( i < row1len && j < row2len )
    620 {
    621 idx1 = row1idxptr[i];
    622 idx2 = row2idxptr[j];
    623
    624 if( idx1 == idx2 )
    625 {
    626 coriginal[nvars] = row1valptr[i];
    627 aoriginal[nvars] = row2valptr[j];
    628 newlbsoriginal[nvars] = lbs[idx1];
    629 newubsoriginal[nvars] = ubs[idx1];
    630 cangetbnd[idx1] = FALSE;
    631 nvars++;
    632#ifdef SCIP_DEBUG_2RB
    633 SCIPdebugMsg(scip, "%g <= (%s) <= %g has coefs %g and %g, %d LP vars\n",
    634 lbs[idx1], SCIPvarGetName(SCIPmatrixGetVar(matrix, idx1)),
    635 ubs[idx1], row1valptr[i], row2valptr[j], nvars);
    636#endif
    637 i++;
    638 j++;
    639 }
    640 else if( idx1 < idx2 )
    641 {
    642 if( SCIPisPositive(scip, row1valptr[i]) )
    643 {
    644 if( SCIPisInfinity(scip, ubs[idx1]) )
    645 maxinfs++;
    646 else
    647 maxact -= row1valptr[i] * ubs[idx1];
    648
    649 if( SCIPisInfinity(scip, -lbs[idx1]) )
    650 mininfs++;
    651 else
    652 minact -= row1valptr[i] * lbs[idx1];
    653 }
    654 else
    655 {
    656 if( SCIPisInfinity(scip, -lbs[idx1]) )
    657 maxinfs++;
    658 else
    659 maxact -= row1valptr[i] * lbs[idx1];
    660
    661 if( SCIPisInfinity(scip, ubs[idx1]) )
    662 mininfs++;
    663 else
    664 minact -= row1valptr[i] * ubs[idx1];
    665
    666 cangetbnd[idx1] = TRUE;
    667 }
    668 if( maxinfs > 1 && mininfs > 1 )
    669 {
    670 (*success) = FALSE;
    671 return SCIP_OKAY;
    672 }
    673 i++;
    674#ifdef SCIP_DEBUG_2RB
    675 SCIPdebugMsg(scip, "%g <= (%s) <= %g has coefs %g and 0.0, minact = %g, maxact = %g\n",
    676 lbs[idx1], SCIPvarGetName(SCIPmatrixGetVar(matrix, idx1)),
    677 ubs[idx1], row1valptr[i], minact, maxact);
    678#endif
    679 }
    680 else
    681 {
    682 coriginal[nvars] = 0.0;
    683 aoriginal[nvars] = row2valptr[j];
    684 newlbsoriginal[nvars] = lbs[idx2];
    685 newubsoriginal[nvars] = ubs[idx2];
    686 cangetbnd[idx2] = FALSE;
    687 nvars++;
    688#ifdef SCIP_DEBUG_2RB
    689 SCIPdebugMsg(scip, "%g <= (%s) <= %g has coefs 0.0 and %g, %d LP vars\n",
    690 lbs[idx2], SCIPvarGetName(SCIPmatrixGetVar(matrix, idx2)),
    691 ubs[idx2], row2valptr[j], nvars);
    692#endif
    693 j++;
    694 }
    695 }
    696 while( i < row1len )
    697 {
    698 idx1 = row1idxptr[i];
    699 if( SCIPisPositive(scip, row1valptr[i]) )
    700 {
    701 if( SCIPisInfinity(scip, ubs[idx1]) )
    702 maxinfs++;
    703 else
    704 maxact -= row1valptr[i] * ubs[idx1];
    705
    706 if( SCIPisInfinity(scip, -lbs[idx1]) )
    707 mininfs++;
    708 else
    709 minact -= row1valptr[i] * lbs[idx1];
    710 }
    711 else
    712 {
    713 if( SCIPisInfinity(scip, -lbs[idx1]) )
    714 maxinfs++;
    715 else
    716 maxact -= row1valptr[i] * lbs[idx1];
    717
    718 if( SCIPisInfinity(scip, ubs[idx1]) )
    719 mininfs++;
    720 else
    721 minact -= row1valptr[i] * ubs[idx1];
    722 }
    723 cangetbnd[idx1] = TRUE;
    724#ifdef SCIP_DEBUG_2RB
    725 SCIPdebugMsg(scip, "%g <= (%s) <= %g has coefs %g and 0.0, minact = %g, maxact = %g\n",
    726 lbs[idx1], SCIPvarGetName(SCIPmatrixGetVar(matrix, idx1)),
    727 ubs[idx1], row1valptr[i], minact, maxact);
    728#endif
    729 i++;
    730 }
    731 while( j < row2len )
    732 {
    733 idx2 = row2idxptr[j];
    734 coriginal[nvars] = 0.0;
    735 aoriginal[nvars] = row2valptr[j];
    736 newlbsoriginal[nvars] = lbs[idx2];
    737 newubsoriginal[nvars] = ubs[idx2];
    738 nvars++;
    739#ifdef SCIP_DEBUG_2RB
    740 SCIPdebugMsg(scip, "%g <= (%s) <= %g has coefs 0.0 and %g, %d LP vars\n",
    741 lbs[idx2], SCIPvarGetName(SCIPmatrixGetVar(matrix, idx2)),
    742 ubs[idx2], row2valptr[j], nvars);
    743#endif
    744 j++;
    745 }
    746
    747#ifdef SCIP_DEBUG_2RB
    748 SCIPdebugMsg(scip, "right hand sides: %g and %g\n",
    750#endif
    751
    752 /* solve single-row LPs */
    753 maxsolvable = FALSE;
    754 minsolvable = FALSE;
    755 maxswapsolvable = FALSE;
    756 minswapsolvable = FALSE;
    757 /* maximize overlap in first row with lhs <= row2 as constraint */
    758 if( maxinfs <= 1 )
    759 {
    760 for( i = 0; i < nvars; i++ )
    761 {
    762 acopy[i] = aoriginal[i];
    763 ccopy[i] = -coriginal[i];
    764 newlbscopy[i] = newlbsoriginal[i];
    765 newubscopy[i] = newubsoriginal[i];
    766 }
    768 ccopy, newlbscopy, newubscopy, nvars, &maxobj, &maxsolvable) );
    769#ifdef SCIP_DEBUG_2RB
    770 SCIPdebugMsg(scip, "max-LP solved: obj = %g\n", maxobj);
    771#endif
    772 }
    773
    774 /* minimize overlap in first row with lhs <= row2 as constraint */
    775 if( mininfs == 0 || (mininfs == 1 && swaprow1) )
    776 {
    777 /* copy coefficients */
    778 for( i = 0; i < nvars; i++ )
    779 {
    780 acopy[i] = aoriginal[i];
    781 ccopy[i] = coriginal[i];
    782 newlbscopy[i] = newlbsoriginal[i];
    783 newubscopy[i] = newubsoriginal[i];
    784 }
    786 ccopy, newlbscopy, newubscopy, nvars, &minobj, &minsolvable) );
    787#ifdef SCIP_DEBUG_2RB
    788 SCIPdebugMsg(scip, "min-LP solved: obj = %g\n", minobj);
    789#endif
    790 }
    791
    792 if( swaprow2 )
    793 {
    794 /* maximize overlap in first row with row2 <= rhs as constraint */
    795 if( maxinfs <= 1 )
    796 {
    797 /* copy coefficients */
    798 for( i = 0; i < nvars; i++ )
    799 {
    800 acopy[i] = -aoriginal[i];
    801 ccopy[i] = -coriginal[i];
    802 newlbscopy[i] = newlbsoriginal[i];
    803 newubscopy[i] = newubsoriginal[i];
    804 }
    806 ccopy, newlbscopy, newubscopy, nvars, &maxswapobj, &maxswapsolvable) );
    807#ifdef SCIP_DEBUG_2RB
    808 SCIPdebugMsg(scip, "maxswap-LP solved: obj = %g\n", maxswapobj);
    809#endif
    810 }
    811
    812 /* minimize overlap in first row with row2 <= rhs as constraint */
    813 if( mininfs == 0 || (mininfs == 1 && swaprow1) )
    814 {
    815 /* copy coefficients */
    816 for( i = 0; i < nvars; i++ )
    817 {
    818 acopy[i] = -aoriginal[i];
    819 ccopy[i] = coriginal[i];
    820 newlbscopy[i] = newlbsoriginal[i];
    821 newubscopy[i] = newubsoriginal[i];
    822 }
    824 ccopy, newlbscopy, newubscopy, nvars, &minswapobj, &minswapsolvable) );
    825#ifdef SCIP_DEBUG_2RB
    826 SCIPdebugMsg(scip, "minswap-LP solved: obj = %g\n", minswapobj);
    827#endif
    828 }
    829 }
    830
    831 /* perform bound tightening, infeasibility checks and redundancy checks */
    832 if( maxinfs <= 1 && (maxsolvable || maxswapsolvable) )
    833 {
    834 SCIP_Real activity;
    835
    836 if( maxsolvable && maxswapsolvable )
    837 activity = MAX(maxobj, maxswapobj) + SCIPmatrixGetRowLhs(matrix, row1idx) + maxact; /*lint !e644*/
    838 else if( maxsolvable )
    839 activity = maxobj + SCIPmatrixGetRowLhs(matrix, row1idx) + maxact; /*lint !e644*/
    840 else
    841 activity = maxswapobj + SCIPmatrixGetRowLhs(matrix, row1idx) + maxact; /*lint !e644*/
    842
    843 /* infeasibility check */
    844 if( maxinfs == 0 && SCIPisPositive(scip, activity) )
    845 {
    846 (*infeasible) = TRUE;
    847 (*success) = TRUE;
    848 return SCIP_OKAY;
    849 }
    850 /* strengthen bounds of all variables outside overlap */
    851 else if( maxinfs == 0 )
    852 {
    853 for( i = 0; i < row1len; i++ )
    854 {
    855 idx1 = row1idxptr[i];
    856 if( cangetbnd[idx1] )
    857 {
    858 if( SCIPisPositive(scip, row1valptr[i]) )
    859 {
    860 if( SCIPvarIsIntegral(SCIPmatrixGetVar(matrix, idx1)) )
    861 newbnd = SCIPceil(scip, (activity + row1valptr[i] * ubs[idx1]) / row1valptr[i]);
    862 else
    863 newbnd = (activity + row1valptr[i] * ubs[idx1]) / row1valptr[i];
    864
    865 if( SCIPisGT(scip, newbnd, lbs[idx1]) )
    866 {
    867#ifdef SCIP_DEBUG_BOUNDS
    868 SCIPdebugMsg(scip, "%g <= %g <= %s <= %g\n",
    869 lbs[idx1], newbnd, SCIPmatrixGetColName(matrix, idx1), ubs[idx1]);
    870#endif
    871 lbs[idx1] = newbnd;
    872 (*success) = TRUE;
    873 }
    874 }
    875 else
    876 {
    877 assert(SCIPisNegative(scip, row1valptr[i]));
    878 if( SCIPvarIsIntegral(SCIPmatrixGetVar(matrix, idx1)) )
    879 newbnd = SCIPfloor(scip, (activity + row1valptr[i] * lbs[idx1]) / row1valptr[i]);
    880 else
    881 newbnd = (activity + row1valptr[i] * lbs[idx1]) / row1valptr[i];
    882
    883 if( SCIPisLT(scip, newbnd, ubs[idx1]) )
    884 {
    885#ifdef SCIP_DEBUG_BOUNDS
    886 SCIPdebugMsg(scip, "%g <= %s <= %g <= %g\n",
    887 lbs[idx1], SCIPmatrixGetColName(matrix, idx1), newbnd, ubs[idx1]);
    888#endif
    889 ubs[idx1] = newbnd;
    890 (*success) = TRUE;
    891 }
    892 }
    893 }
    894 }
    895 }
    896 /* strengthen bound of the single variable contributing the infinity */
    897 else
    898 {
    899 assert(maxinfs == 1);
    900 for( i = 0; i < row1len; i++ )
    901 {
    902 idx1 = row1idxptr[i];
    903 if( cangetbnd[idx1] )
    904 {
    905 if( SCIPisPositive(scip, row1valptr[i]) && SCIPisInfinity(scip, ubs[idx1]) )
    906 {
    907 if( SCIPvarIsIntegral(SCIPmatrixGetVar(matrix, idx1)) )
    908 newbnd = SCIPceil(scip, activity / row1valptr[i]);
    909 else
    910 newbnd = activity / row1valptr[i];
    911
    912 if( SCIPisGT(scip, newbnd, lbs[idx1]) )
    913 {
    914#ifdef SCIP_DEBUG_BOUNDS
    915 SCIPdebugMsg(scip, "%g <= %g <= %s <= %g\n",
    916 lbs[idx1], newbnd, SCIPmatrixGetColName(matrix, idx1), ubs[idx1]);
    917#endif
    918 lbs[idx1] = newbnd;
    919 (*success) = TRUE;
    920 }
    921 }
    922 else if( SCIPisInfinity(scip, -lbs[idx1]) )
    923 {
    924 assert(SCIPisNegative(scip, row1valptr[i]));
    925 if( SCIPvarIsIntegral(SCIPmatrixGetVar(matrix, idx1)) )
    926 newbnd = SCIPfloor(scip, activity / row1valptr[i]);
    927 else
    928 newbnd = activity / row1valptr[i];
    929
    930 if( SCIPisLT(scip, newbnd, ubs[idx1]) )
    931 {
    932#ifdef SCIP_DEBUG_BOUNDS
    933 SCIPdebugMsg(scip, "%g <= %s <= %g <= %g\n",
    934 lbs[idx1], SCIPmatrixGetColName(matrix, idx1), newbnd, ubs[idx1]);
    935#endif
    936 ubs[idx1] = newbnd;
    937 (*success) = TRUE;
    938 }
    939 }
    940 }
    941 }
    942 }
    943 }
    944
    945 /* in this case the objective is swapped. therefore the minimum and the maximum of the support switch roles */
    946 if( swaprow1 )
    947 {
    948 /* perform bound tightening, infeasibility checks and redundancy checks */
    949 if( mininfs <= 1 && (minsolvable || minswapsolvable) )
    950 {
    951 SCIP_Real activity;
    952
    953 assert(minobj != SCIP_INVALID); /*lint !e777*/
    954 if( minsolvable && minswapsolvable )
    955 activity = MAX(minobj, minswapobj) - SCIPmatrixGetRowRhs(matrix, row1idx) - minact;
    956 else if( minsolvable )
    957 activity = minobj - SCIPmatrixGetRowRhs(matrix, row1idx) - minact;
    958 else
    959 activity = minswapobj - SCIPmatrixGetRowRhs(matrix, row1idx) - minact;
    960
    961 /* infeasibility check */
    962 if( mininfs == 0 && SCIPisPositive(scip, activity) )
    963 {
    964 (*infeasible) = TRUE;
    965 (*success) = TRUE;
    966 return SCIP_OKAY;
    967 }
    968 /* strengthen bounds of all variables outside overlap */
    969 else if( mininfs == 0 )
    970 {
    971 for( i = 0; i < row1len; i++ )
    972 {
    973 idx1 = row1idxptr[i];
    974 if( cangetbnd[idx1] )
    975 {
    976 if( SCIPisNegative(scip, row1valptr[i]) ) /* since we look at the swapped case, this represents a positive coefficient */
    977 {
    978 if( SCIPvarIsIntegral(SCIPmatrixGetVar(matrix, idx1)) )
    979 newbnd = SCIPceil(scip, (activity - row1valptr[i] * ubs[idx1]) / (-row1valptr[i]));
    980 else
    981 newbnd = (activity - row1valptr[i] * ubs[idx1]) / (-row1valptr[i]);
    982
    983 if( SCIPisGT(scip, newbnd, lbs[idx1]) )
    984 {
    985#ifdef SCIP_DEBUG_BOUNDS
    986 SCIPdebugMsg(scip, "%g <= %g <= %s <= %g\n",
    987 lbs[idx1], newbnd, SCIPmatrixGetColName(matrix, idx1), ubs[idx1]);
    988#endif
    989 lbs[idx1] = newbnd;
    990 (*success) = TRUE;
    991 }
    992 }
    993 else
    994 {
    995 /* since we look at the swapped case, this represents a negative coefficient */
    996 assert(SCIPisPositive(scip, row1valptr[i]));
    997 if( SCIPvarIsIntegral(SCIPmatrixGetVar(matrix, idx1)) )
    998 newbnd = SCIPfloor(scip, (activity - row1valptr[i] * lbs[idx1]) / (-row1valptr[i]));
    999 else
    1000 newbnd = (activity - row1valptr[i] * lbs[idx1]) / (-row1valptr[i]);
    1001
    1002 if( SCIPisLT(scip, newbnd, ubs[idx1]) )
    1003 {
    1004#ifdef SCIP_DEBUG_BOUNDS
    1005 SCIPdebugMsg(scip, "%g <= %s <= %g <= %g\n",
    1006 lbs[idx1], SCIPmatrixGetColName(matrix, idx1), newbnd, ubs[idx1]);
    1007#endif
    1008 ubs[idx1] = newbnd;
    1009 (*success) = TRUE;
    1010 }
    1011 }
    1012 }
    1013 }
    1014 }
    1015 /* strengthen bound of the single variable contributing the infinity */
    1016 else
    1017 {
    1018 assert(mininfs == 1);
    1019 for( i = 0; i < row1len; i++ )
    1020 {
    1021 idx1 = row1idxptr[i];
    1022 if( cangetbnd[idx1] )
    1023 {
    1024 /* since we look at the swapped case, this represents a positive coefficient */
    1025 if( SCIPisNegative(scip, row1valptr[i]) && SCIPisInfinity(scip, ubs[idx1]) )
    1026 {
    1027 if( SCIPvarIsIntegral(SCIPmatrixGetVar(matrix, idx1)) )
    1028 newbnd = SCIPceil(scip, activity / (-row1valptr[i]));
    1029 else
    1030 newbnd = activity / (-row1valptr[i]);
    1031
    1032 if( SCIPisGT(scip, newbnd, lbs[idx1]) )
    1033 {
    1034#ifdef SCIP_DEBUG_BOUNDS
    1035 SCIPdebugMsg(scip, "%g <= %g <= %s <= %g\n", lbs[idx1], newbnd, SCIPmatrixGetColName(matrix, idx1), ubs[idx1]);
    1036#endif
    1037 lbs[idx1] = newbnd;
    1038 (*success) = TRUE;
    1039 }
    1040 }
    1041 else if( SCIPisInfinity(scip, -lbs[idx1]) )
    1042 {
    1043 /* since we look at the swapped case, this represents a negative coefficient */
    1044 assert(SCIPisPositive(scip, row1valptr[i]));
    1045 if( SCIPvarIsIntegral(SCIPmatrixGetVar(matrix, idx1)) )
    1046 newbnd = SCIPfloor(scip, activity / (-row1valptr[i]));
    1047 else
    1048 newbnd = activity / (-row1valptr[i]);
    1049
    1050 if( SCIPisLT(scip, newbnd, ubs[idx1]) )
    1051 {
    1052#ifdef SCIP_DEBUG_BOUNDS
    1053 SCIPdebugMsg(scip, "%g <= %s <= %g <= %g\n",
    1054 lbs[idx1], SCIPmatrixGetColName(matrix, idx1), newbnd, ubs[idx1]);
    1055#endif
    1056 ubs[idx1] = newbnd;
    1057 (*success) = TRUE;
    1058 }
    1059 }
    1060 }
    1061 }
    1062 }
    1063 }
    1064 }
    1065
    1066 return SCIP_OKAY;
    1067}
    1068
    1069/** create required buffer arrays and apply LP-based bound tightening in both directions */
    1070static
    1072 SCIP* scip, /**< SCIP data structure */
    1073 SCIP_MATRIX* matrix, /**< constraint matrix object */
    1074 int row1, /**< index of first row */
    1075 int row2, /**< index of seond row */
    1076 SCIP_Bool swaprow1, /**< should row1 <= rhs be used in addition to lhs <= row1 */
    1077 SCIP_Bool swaprow2, /**< should row2 <= rhs be used in addition to lhs <= row2 */
    1078 SCIP_Real* lbs, /**< lower variable bounds */
    1079 SCIP_Real* ubs, /**< upper variable bounds */
    1080 SCIP_Bool* success /**< return (success || "found better bounds") */
    1081 )
    1082{
    1083 SCIP_Real* aoriginal;
    1084 SCIP_Real* acopy;
    1085 SCIP_Real* coriginal;
    1086 SCIP_Real* ccopy;
    1087 SCIP_Real* newlbsoriginal;
    1088 SCIP_Real* newlbscopy;
    1089 SCIP_Real* newubsoriginal;
    1090 SCIP_Real* newubscopy;
    1091 SCIP_Bool* cangetbnd;
    1092 SCIP_Bool infeasible;
    1093
    1094#ifdef SCIP_DEBUG_2RB
    1095 SCIPdebugMsg(scip, "combining rows %d (%s) and %d (%s)\n",
    1096 row1, SCIPmatrixGetRowName(matrix, row1), row2, SCIPmatrixGetRowName(matrix, row2));
    1097#endif
    1098
    1103 SCIP_CALL( SCIPallocBufferArray(scip, &newlbsoriginal, SCIPmatrixGetNColumns(matrix)) );
    1104 SCIP_CALL( SCIPallocBufferArray(scip, &newlbscopy, SCIPmatrixGetNColumns(matrix)) );
    1105 SCIP_CALL( SCIPallocBufferArray(scip, &newubsoriginal, SCIPmatrixGetNColumns(matrix)) );
    1106 SCIP_CALL( SCIPallocBufferArray(scip, &newubscopy, SCIPmatrixGetNColumns(matrix)) );
    1108
    1109 /* Sort matrix rows */
    1111 SCIPmatrixGetRowNNonzs(matrix, row1));
    1113 SCIPmatrixGetRowNNonzs(matrix, row2));
    1114
    1115 /* Use row2 to strengthen row1 */
    1116 infeasible = FALSE;
    1117 SCIP_CALL( transformAndSolve(scip, matrix, row1, row2, swaprow1, swaprow2, aoriginal, acopy,
    1118 coriginal, ccopy, cangetbnd, lbs, ubs, newlbsoriginal, newlbscopy,
    1119 newubsoriginal, newubscopy, success, &infeasible) );
    1120
    1121 /* Switch roles and use row1 to strengthen row2 */
    1122 SCIP_CALL( transformAndSolve(scip, matrix, row2, row1, swaprow2, swaprow1, aoriginal, acopy,
    1123 coriginal, ccopy, cangetbnd, lbs, ubs, newlbsoriginal, newlbscopy,
    1124 newubsoriginal, newubscopy, success, &infeasible) );
    1125
    1126 SCIPfreeBufferArray(scip, &cangetbnd);
    1127 SCIPfreeBufferArray(scip, &newubscopy);
    1128 SCIPfreeBufferArray(scip, &newubsoriginal);
    1129 SCIPfreeBufferArray(scip, &newlbscopy);
    1130 SCIPfreeBufferArray(scip, &newlbsoriginal);
    1131 SCIPfreeBufferArray(scip, &ccopy);
    1132 SCIPfreeBufferArray(scip, &coriginal);
    1133 SCIPfreeBufferArray(scip, &acopy);
    1134 SCIPfreeBufferArray(scip, &aoriginal);
    1135
    1136 return SCIP_OKAY;
    1137}
    1138
    1139/* Find hashes contained in both hashlists, and apply LP-bound
    1140 * on their corresponding rows. Both hashlists must be sorted.
    1141 */
    1142static
    1144 SCIP* scip, /**< SCIP data structure */
    1145 SCIP_PRESOLDATA* presoldata, /**< presolver data structure */
    1146 SCIP_MATRIX* matrix, /**< constraint matrix object */
    1147 int* hashlist1, /**< first list of hashes */
    1148 int* hashlist2, /**< second list of hashes */
    1149 int lenhashlist1, /**< length of first hashlist */
    1150 int lenhashlist2, /**< length of second hashlist */
    1151 int* rowidxlist1, /**< list of row indices corresponding to hashes in hashlist1 */
    1152 int* rowidxlist2, /**< list of row indices corresponding to hashes in hashlist2 */
    1153 SCIP_Real* newlbs, /**< lower variable bounds, new bounds will be written here */
    1154 SCIP_Real* newubs /**< upper variable bounds, new bound will be written here */
    1155 )
    1156{
    1157 int i;
    1158 int j;
    1159 int block1start;
    1160 int block1end;
    1161 int block2start;
    1162 int block2end;
    1163 SCIP_Longint maxcombines;
    1164 SCIP_Bool finished;
    1165 SCIP_Bool success;
    1166 SCIP_Bool swaprow1;
    1167 SCIP_Bool swaprow2;
    1168 int ncombines;
    1169 int combinefails;
    1170 int retrievefails;
    1171 ROWPAIR rowpair;
    1172 SCIP_HASHSET* pairhashset;
    1173
    1174 SCIP_CALL( SCIPhashsetCreate(&pairhashset, SCIPblkmem(scip), 1) );
    1175
    1176 finished = FALSE;
    1177 block1start = 0;
    1178 block1end = 0;
    1179 block2start = 0;
    1180 block2end = 0;
    1181 maxcombines = presoldata->maxpairfac == -1 ? SCIP_LONGINT_MAX : (((SCIP_Longint)SCIPmatrixGetNRows(matrix)) * presoldata->maxpairfac);
    1182
    1183 ncombines = 0;
    1184 combinefails = 0;
    1185 retrievefails = 0;
    1186 findNextBlock(hashlist1, lenhashlist1, &block1start, &block1end);
    1187 findNextBlock(hashlist2, lenhashlist2, &block2start, &block2end);
    1188 while( !finished )
    1189 {
    1190 if( hashlist1[block1start] == hashlist2[block2start] )
    1191 {
    1192 for( i = block1start; i < block1end; i++ )
    1193 {
    1194 for( j = block2start; j < block2end; j++ )
    1195 {
    1196 if( rowidxlist1[i] != rowidxlist2[j] )
    1197 {
    1198 rowpair.row1idx = MIN(rowidxlist1[i], rowidxlist2[j]);
    1199 rowpair.row2idx = MAX(rowidxlist1[i], rowidxlist2[j]);
    1200 if( !SCIPhashsetExists(pairhashset, encodeRowPair(&rowpair)) )
    1201 {
    1202 assert(!SCIPisInfinity(scip, -SCIPmatrixGetRowLhs(matrix, rowpair.row1idx)));
    1203 assert(!SCIPisInfinity(scip, -SCIPmatrixGetRowLhs(matrix, rowpair.row2idx)));
    1204
    1205 success = FALSE;
    1206
    1207 /* apply lp-based bound tightening */
    1208 swaprow1 = !SCIPisInfinity(scip, SCIPmatrixGetRowRhs(matrix, rowpair.row1idx));
    1209 swaprow2 = !SCIPisInfinity(scip, SCIPmatrixGetRowRhs(matrix, rowpair.row2idx));
    1210
    1211 SCIP_CALL( applyLPboundTightening(scip, matrix, rowpair.row1idx, rowpair.row2idx,
    1212 swaprow1, swaprow2, newlbs, newubs, &success) );
    1213
    1214 if( success )
    1215 combinefails = 0;
    1216 else
    1217 combinefails++;
    1218
    1219 SCIP_CALL( SCIPhashsetInsert(pairhashset, SCIPblkmem(scip), encodeRowPair(&rowpair)) );
    1220 ncombines++;
    1221
    1222 if( ncombines >= maxcombines || combinefails >= presoldata->maxcombinefails )
    1223 finished = TRUE;
    1224
    1225 retrievefails = 0;
    1226 }
    1227 else if( retrievefails < presoldata->maxretrievefails )
    1228 retrievefails++;
    1229 else
    1230 finished = TRUE;
    1231 }
    1232 /* check if SCIP ran into a time limit already */
    1233 if( j % 10 == 0 && SCIPisStopped(scip) )
    1234 finished = TRUE;
    1235 if( finished )
    1236 break;
    1237 }
    1238 /* check if SCIP ran into a time limit already */
    1239 if( SCIPisStopped(scip) )
    1240 finished = TRUE;
    1241 if( finished )
    1242 break;
    1243 }
    1244
    1245 if( block1end < lenhashlist1 && block2end < lenhashlist2 )
    1246 {
    1247 findNextBlock(hashlist1, lenhashlist1, &block1start, &block1end);
    1248 findNextBlock(hashlist2, lenhashlist2, &block2start, &block2end);
    1249 }
    1250 else
    1251 finished = TRUE;
    1252 }
    1253 else if( hashlist1[block1start] < hashlist2[block2start] && block1end < lenhashlist1 )
    1254 findNextBlock(hashlist1, lenhashlist1, &block1start, &block1end);
    1255 else if( hashlist1[block1start] > hashlist2[block2start] && block2end < lenhashlist2 )
    1256 findNextBlock(hashlist2, lenhashlist2, &block2start, &block2end);
    1257 else
    1258 finished = TRUE;
    1259 }
    1260
    1261 SCIPhashsetFree(&pairhashset, SCIPblkmem(scip));
    1262
    1263 return SCIP_OKAY;
    1264}
    1265
    1266
    1267/*
    1268 * Callback methods of presolver
    1269 */
    1270
    1271/** copy method for constraint handler plugins (called when SCIP copies plugins) */
    1272static
    1273SCIP_DECL_PRESOLCOPY(presolCopyTworowbnd)
    1274{
    1275 SCIP_PRESOLDATA* presoldata;
    1276
    1277 assert(scip != NULL);
    1278 assert(presol != NULL);
    1279 assert(strcmp(SCIPpresolGetName(presol), PRESOL_NAME) == 0);
    1280
    1281 /* call inclusion method of presolver if copying is enabled */
    1282 presoldata = SCIPpresolGetData(presol);
    1283 assert(presoldata != NULL);
    1284 if( presoldata->enablecopy )
    1285 {
    1287 }
    1288
    1289 return SCIP_OKAY;
    1290}
    1291
    1292/** destructor of presolver to free user data (called when SCIP is exiting) */
    1293static
    1294SCIP_DECL_PRESOLFREE(presolFreeTworowbnd)
    1295{ /*lint --e{715}*/
    1296 SCIP_PRESOLDATA* presoldata;
    1297
    1298 /* free presolver data */
    1299 presoldata = SCIPpresolGetData(presol);
    1300 assert(presoldata != NULL);
    1301
    1302 SCIPfreeBlockMemory(scip, &presoldata);
    1303 SCIPpresolSetData(presol, NULL);
    1304
    1305 return SCIP_OKAY;
    1306}
    1307
    1308/** initialization method of presolver (called after problem was transformed) */
    1309static
    1310SCIP_DECL_PRESOLINIT(presolInitTworowbnd)
    1311{
    1312 SCIP_PRESOLDATA* presoldata;
    1313
    1314 presoldata = SCIPpresolGetData(presol);
    1315 presoldata->nchgbnds = 0;
    1316 presoldata->nuselessruns = 0;
    1317
    1318 return SCIP_OKAY;
    1319}
    1320
    1321/** execution method of presolver */
    1322static
    1323SCIP_DECL_PRESOLEXEC(presolExecTworowbnd)
    1324{ /*lint --e{715}*/
    1325 SCIP_MATRIX* matrix;
    1326 SCIP_Bool initialized;
    1327 SCIP_Bool complete;
    1328 SCIP_Bool infeasible;
    1329 SCIP_PRESOLDATA* presoldata;
    1330 int oldnchgbds;
    1331 int oldnfixedvars;
    1332 int nrows;
    1333 int ncols;
    1334 SCIP_Real* oldlbs;
    1335 SCIP_Real* oldubs;
    1336 SCIP_Real* newlbs;
    1337 SCIP_Real* newubs;
    1338 int* rowidxptr;
    1339 SCIP_Real* rowvalptr;
    1340 SCIP_VAR* var;
    1341
    1342 SCIP_Longint maxhashes;
    1343
    1344 int maxlen;
    1345 int pospp;
    1346 int listsizepp;
    1347 int posmm;
    1348 int listsizemm;
    1349 int pospm;
    1350 int listsizepm;
    1351 int posmp;
    1352 int listsizemp;
    1353
    1354 int* hashlistpp;
    1355 int* hashlistmm;
    1356 int* hashlistpm;
    1357 int* hashlistmp;
    1358
    1359 int* rowidxlistpp;
    1360 int* rowidxlistmm;
    1361 int* rowidxlistpm;
    1362 int* rowidxlistmp;
    1363
    1364 SCIP_Bool finiterhs;
    1365
    1366 int i;
    1367 int j;
    1368 int k;
    1369
    1370 assert(result != NULL);
    1371 *result = SCIP_DIDNOTRUN;
    1372 infeasible = FALSE;
    1373
    1374 if( SCIPisStopped(scip) )
    1375 return SCIP_OKAY;
    1376
    1377 presoldata = SCIPpresolGetData(presol);
    1378 assert(presoldata != NULL);
    1379
    1380 if( presoldata->nuselessruns >= 5 )
    1381 return SCIP_OKAY;
    1382
    1383 *result = SCIP_DIDNOTFIND;
    1384
    1385 matrix = NULL;
    1386 SCIP_CALL( SCIPmatrixCreate(scip, &matrix, TRUE, &initialized, &complete, &infeasible,
    1387 naddconss, ndelconss, nchgcoefs, nchgbds, nfixedvars) );
    1388
    1389 /* if infeasibility was detected during matrix creation, return here */
    1390 if( infeasible )
    1391 {
    1392 if( initialized )
    1393 SCIPmatrixFree(scip, &matrix);
    1394
    1395 *result = SCIP_CUTOFF;
    1396 return SCIP_OKAY;
    1397 }
    1398
    1399 if( !initialized )
    1400 return SCIP_OKAY;
    1401
    1402 nrows = SCIPmatrixGetNRows(matrix);
    1403 ncols = SCIPmatrixGetNColumns(matrix);
    1404
    1405 if( nrows <= 1 )
    1406 {
    1407 SCIPmatrixFree(scip, &matrix);
    1408 return SCIP_OKAY;
    1409 }
    1410
    1411 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &hashlistpp, nrows) );
    1412 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &hashlistmm, nrows) );
    1413 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &hashlistpm, nrows) );
    1414 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &hashlistmp, nrows) );
    1415
    1416 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &rowidxlistpp, nrows) );
    1417 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &rowidxlistmm, nrows) );
    1418 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &rowidxlistpm, nrows) );
    1419 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &rowidxlistmp, nrows) );
    1420
    1421 pospp = 0;
    1422 posmm = 0;
    1423 pospm = 0;
    1424 posmp = 0;
    1425 listsizepp = nrows;
    1426 listsizemm = nrows;
    1427 listsizepm = nrows;
    1428 listsizemp = nrows;
    1429 maxhashes = presoldata->maxhashfac == -1 ? SCIP_LONGINT_MAX : (((SCIP_Longint)nrows) * presoldata->maxhashfac);
    1430
    1431 /* skim through the problem and create hashlists for combination candidates */
    1432 for( i = 0; i < nrows; i++)
    1433 {
    1434 if( ((SCIP_Longint)pospp) + posmm + pospm + posmp > maxhashes )
    1435 break;
    1436
    1437 rowvalptr = SCIPmatrixGetRowValPtr(matrix, i);
    1438 rowidxptr = SCIPmatrixGetRowIdxPtr(matrix, i);
    1439 finiterhs = !SCIPisInfinity(scip, SCIPmatrixGetRowRhs(matrix, i));
    1440 maxlen = MIN(presoldata->maxconsiderednonzeros, SCIPmatrixGetRowNNonzs(matrix, i)); /*lint !e666*/
    1441 for( j = 0; j < maxlen; j++)
    1442 {
    1443 for( k = j+1; k < maxlen; k++)
    1444 {
    1445 if( SCIPisPositive(scip, rowvalptr[j]) )
    1446 {
    1447 if(SCIPisPositive(scip, rowvalptr[k]) )
    1448 {
    1449 SCIP_CALL( addEntry(scip, &pospp, &listsizepp, &hashlistpp, &rowidxlistpp,
    1450 hashIndexPair(rowidxptr[j],rowidxptr[k]), i) );
    1451 if( finiterhs )
    1452 SCIP_CALL( addEntry(scip, &posmm, &listsizemm, &hashlistmm, &rowidxlistmm,
    1453 hashIndexPair(rowidxptr[j],rowidxptr[k]), i) );
    1454 }
    1455 else
    1456 {
    1457 SCIP_CALL( addEntry(scip, &pospm, &listsizepm, &hashlistpm, &rowidxlistpm,
    1458 hashIndexPair(rowidxptr[j],rowidxptr[k]), i) );
    1459 if( finiterhs )
    1460 SCIP_CALL( addEntry(scip, &posmp, &listsizemp, &hashlistmp, &rowidxlistmp,
    1461 hashIndexPair(rowidxptr[j],rowidxptr[k]), i) );
    1462 }
    1463 }
    1464 else
    1465 {
    1466 if(SCIPisPositive(scip, rowvalptr[k]) )
    1467 {
    1468 SCIP_CALL( addEntry(scip, &posmp, &listsizemp, &hashlistmp, &rowidxlistmp,
    1469 hashIndexPair(rowidxptr[j],rowidxptr[k]), i) );
    1470 if( finiterhs )
    1471 SCIP_CALL( addEntry(scip, &pospm, &listsizepm, &hashlistpm, &rowidxlistpm,
    1472 hashIndexPair(rowidxptr[j],rowidxptr[k]), i) );
    1473 }
    1474 else
    1475 {
    1476 SCIP_CALL( addEntry(scip, &posmm, &listsizemm, &hashlistmm, &rowidxlistmm,
    1477 hashIndexPair(rowidxptr[j],rowidxptr[k]), i) );
    1478 if( finiterhs )
    1479 SCIP_CALL( addEntry(scip, &pospp, &listsizepp, &hashlistpp, &rowidxlistpp,
    1480 hashIndexPair(rowidxptr[j],rowidxptr[k]), i) );
    1481 }
    1482 }
    1483 }
    1484 }
    1485 }
    1486
    1487#ifdef SCIP_DEBUG_HASHING
    1488 SCIPdebugMsg(scip, "pp\n");
    1489 for( i = 0; i < pospp; i++)
    1490 SCIPdebugMsg(scip, "%d: hash = %d, rowidx = %d\n", i, hashlistpp[i], rowidxlistpp[i]);
    1491 SCIPdebugMsg(scip, "mm\n");
    1492 for( i = 0; i < posmm; i++)
    1493 SCIPdebugMsg(scip, "%d: hash = %d, rowidx = %d\n", i, hashlistmm[i], rowidxlistmm[i]);
    1494 SCIPdebugMsg(scip, "pm\n");
    1495 for( i = 0; i < pospm; i++)
    1496 SCIPdebugMsg(scip, "%d: hash = %d, rowidx = %d\n", i, hashlistpm[i], rowidxlistpm[i]);
    1497 SCIPdebugMsg(scip, "mp\n");
    1498 for( i = 0; i < posmp; i++)
    1499 SCIPdebugMsg(scip, "%d: hash = %d, rowidx = %d\n", i, hashlistmp[i], rowidxlistmp[i]);
    1500#endif
    1501 SCIPdebugMsg(scip, "hashlist sizes: pp %d, mm %d, pm %d, mp %d \n", pospp, posmm, pospm, posmp);
    1502
    1503 SCIPsortIntInt(hashlistpp, rowidxlistpp, pospp);
    1504 SCIPsortIntInt(hashlistmm, rowidxlistmm, posmm);
    1505 SCIPsortIntInt(hashlistpm, rowidxlistpm, pospm);
    1506 SCIPsortIntInt(hashlistmp, rowidxlistmp, posmp);
    1507
    1508#ifdef SCIP_DEBUG_HASHING
    1509 SCIPdebugMsg(scip, "sorted pp\n");
    1510 for( i = 0; i < pospp; i++)
    1511 SCIPdebugMsg(scip, "%d: hash = %d, rowidx = %d\n", i, hashlistpp[i], rowidxlistpp[i]);
    1512 SCIPdebugMsg(scip, "sorted mm\n");
    1513 for( i = 0; i < posmm; i++)
    1514 SCIPdebugMsg(scip, "%d: hash = %d, rowidx = %d\n", i, hashlistmm[i], rowidxlistmm[i]);
    1515 SCIPdebugMsg(scip, "sorted pm\n");
    1516 for( i = 0; i < pospm; i++)
    1517 SCIPdebugMsg(scip, "%d: hash = %d, rowidx = %d\n", i, hashlistpm[i], rowidxlistpm[i]);
    1518 SCIPdebugMsg(scip, "sorted mp\n");
    1519 for( i = 0; i < posmp; i++)
    1520 SCIPdebugMsg(scip, "%d: hash = %d, rowidx = %d\n", i, hashlistmp[i], rowidxlistmp[i]);
    1521#endif
    1522
    1523 SCIP_CALL( SCIPallocBufferArray(scip, &oldlbs, ncols) );
    1524 SCIP_CALL( SCIPallocBufferArray(scip, &oldubs, ncols) );
    1525 SCIP_CALL( SCIPallocBufferArray(scip, &newlbs, ncols) );
    1526 SCIP_CALL( SCIPallocBufferArray(scip, &newubs, ncols) );
    1527
    1528 for( i = 0; i < SCIPmatrixGetNColumns(matrix); i++ )
    1529 {
    1530 var = SCIPmatrixGetVar(matrix, i);
    1531 oldlbs[i] = SCIPvarGetLbLocal(var);
    1532 oldubs[i] = SCIPvarGetUbLocal(var);
    1533 newlbs[i] = oldlbs[i];
    1534 newubs[i] = oldubs[i];
    1535 }
    1536
    1537 /* Process pp and mm hashlists */
    1538 if( pospp > 0 && posmm > 0 )
    1539 {
    1540 SCIPdebugMsg(scip, "processing pp and mm\n");
    1541 SCIP_CALL( processHashlists(scip, presoldata, matrix, hashlistpp, hashlistmm, pospp, posmm, rowidxlistpp,
    1542 rowidxlistmm, newlbs, newubs) );
    1543 }
    1544
    1545 /* Process pm and mp hashlists */
    1546 if( pospm > 0 && posmp > 0 )
    1547 {
    1548 SCIPdebugMsg(scip, "processing pm and mp\n");
    1549 SCIP_CALL( processHashlists(scip, presoldata, matrix, hashlistpm, hashlistmp, pospm, posmp, rowidxlistpm,
    1550 rowidxlistmp, newlbs, newubs) );
    1551 }
    1552
    1553 /* Apply reductions */
    1554 oldnchgbds = *nchgbds;
    1555 oldnfixedvars = *nfixedvars;
    1556 for( i = 0; i < SCIPmatrixGetNColumns(matrix); i++ )
    1557 {
    1558 SCIP_Bool bndwastightened;
    1559 SCIP_Bool fixed;
    1560
    1561 var = SCIPmatrixGetVar(matrix, i);
    1562
    1563 assert(!SCIPvarIsNonimpliedIntegral(var)
    1564 || (SCIPisEQ(scip, newlbs[i], SCIPceil(scip, newlbs[i])) && SCIPisEQ(scip, newubs[i], SCIPfloor(scip, newubs[i]))));
    1565
    1566 if( SCIPisEQ(scip, newlbs[i], newubs[i]) )
    1567 {
    1568 SCIP_CALL( SCIPfixVar(scip, var, newlbs[i], &infeasible, &fixed) );
    1569
    1570 if( infeasible )
    1571 {
    1572 SCIPdebugMessage(" -> infeasible fixing of variable %s\n", SCIPvarGetName(var));
    1573 break;
    1574 }
    1575
    1576 if( fixed )
    1577 {
    1578 SCIPdebugMessage("variable %s fixed to %g\n", SCIPvarGetName(var), newlbs[i]);
    1579 (*nfixedvars)++;
    1580 }
    1581 }
    1582
    1583 if( SCIPisLT(scip, oldlbs[i], newlbs[i]) )
    1584 {
    1585 SCIP_CALL( SCIPtightenVarLb(scip, var, newlbs[i], FALSE, &infeasible, &bndwastightened) );
    1586
    1587 if( infeasible )
    1588 {
    1589 SCIPdebugMessage(" -> infeasible lower bound tightening: %s >= %g\n", SCIPvarGetName(var), newlbs[i]);
    1590 break;
    1591 }
    1592
    1593 if( bndwastightened )
    1594 {
    1595 SCIPdebugMessage("lower bound of %s changed from %g to %g\n", SCIPvarGetName(var), oldlbs[i], newlbs[i]);
    1596 (*nchgbds)++;
    1597 }
    1598 }
    1599
    1600 if( SCIPisGT(scip, oldubs[i], newubs[i]) )
    1601 {
    1602 SCIP_CALL( SCIPtightenVarUb(scip, var, newubs[i], FALSE, &infeasible, &bndwastightened) );
    1603
    1604 if( infeasible )
    1605 {
    1606 SCIPdebugMessage(" -> infeasible upper bound tightening: %s <= %g\n", SCIPvarGetName(var), newubs[i]);
    1607 break;
    1608 }
    1609
    1610 if( bndwastightened )
    1611 {
    1612 SCIPdebugMessage("upper bound of %s changed from %g to %g\n", SCIPvarGetName(var), oldubs[i], newubs[i]);
    1613 (*nchgbds)++;
    1614 }
    1615 }
    1616 }
    1617
    1618 /* set result */
    1619 if( *nchgbds > oldnchgbds || *nfixedvars > oldnfixedvars )
    1620 {
    1621 *result = SCIP_SUCCESS;
    1622 presoldata->nuselessruns = 0;
    1623 }
    1624 else if( infeasible )
    1625 {
    1626 *result = SCIP_CUTOFF;
    1627 }
    1628 else
    1629 {
    1630 presoldata->nuselessruns++;
    1631 }
    1632
    1633 SCIPfreeBufferArray(scip, &newubs);
    1634 SCIPfreeBufferArray(scip, &newlbs);
    1635 SCIPfreeBufferArray(scip, &oldubs);
    1636 SCIPfreeBufferArray(scip, &oldlbs);
    1637 SCIPfreeBlockMemoryArray(scip, &rowidxlistmp, listsizemp);
    1638 SCIPfreeBlockMemoryArray(scip, &rowidxlistpm, listsizepm);
    1639 SCIPfreeBlockMemoryArray(scip, &rowidxlistmm, listsizemm);
    1640 SCIPfreeBlockMemoryArray(scip, &rowidxlistpp, listsizepp);
    1641 SCIPfreeBlockMemoryArray(scip, &hashlistmp, listsizemp);
    1642 SCIPfreeBlockMemoryArray(scip, &hashlistpm, listsizepm);
    1643 SCIPfreeBlockMemoryArray(scip, &hashlistmm, listsizemm);
    1644 SCIPfreeBlockMemoryArray(scip, &hashlistpp, listsizepp);
    1645
    1646 SCIPmatrixFree(scip, &matrix);
    1647
    1648 return SCIP_OKAY;
    1649}
    1650
    1651
    1652/*
    1653 * presolver specific interface methods
    1654 */
    1655
    1656/** creates the tworowbndb presolver and includes it in SCIP */
    1658 SCIP* scip /**< SCIP data structure */
    1659 )
    1660{
    1661 SCIP_PRESOLDATA* presoldata;
    1662 SCIP_PRESOL* presol;
    1663
    1664 /* create tworowbnd presolver data */
    1665 SCIP_CALL( SCIPallocBlockMemory(scip, &presoldata) );
    1666
    1667 presol = NULL;
    1668
    1669 /* include presolver */
    1671 presolExecTworowbnd,
    1672 presoldata) );
    1673
    1674 assert(presol != NULL);
    1675
    1676 SCIP_CALL( SCIPsetPresolCopy(scip, presol, presolCopyTworowbnd) );
    1677 SCIP_CALL( SCIPsetPresolFree(scip, presol, presolFreeTworowbnd) );
    1678 SCIP_CALL( SCIPsetPresolInit(scip, presol, presolInitTworowbnd) );
    1679
    1680 /* add tworowbnd presolver parameters */
    1682 "presolving/tworowbnd/enablecopy",
    1683 "should tworowbnd presolver be copied to sub-SCIPs?",
    1684 &presoldata->enablecopy, TRUE, DEFAULT_ENABLECOPY, NULL, NULL) );
    1686 "presolving/tworowbnd/maxconsiderednonzeros",
    1687 "maximal number of considered non-zeros within one row (-1: no limit)",
    1688 &presoldata->maxconsiderednonzeros, FALSE, DEFAULT_MAXCONSIDEREDNONZEROS, -1, INT_MAX, NULL, NULL) );
    1690 "presolving/tworowbnd/maxretrievefails",
    1691 "maximal number of consecutive useless hashtable retrieves",
    1692 &presoldata->maxretrievefails, FALSE, DEFAULT_MAXRETRIEVEFAILS, -1, INT_MAX, NULL, NULL) );
    1694 "presolving/tworowbnd/maxcombinefails",
    1695 "maximal number of consecutive useless row combines",
    1696 &presoldata->maxcombinefails, FALSE, DEFAULT_MAXCOMBINEFAILS, -1, INT_MAX, NULL, NULL) );
    1698 "presolving/tworowbnd/maxhashfac",
    1699 "Maximum number of hashlist entries as multiple of number of rows in the problem (-1: no limit)",
    1700 &presoldata->maxhashfac, FALSE, DEFAULT_MAXHASHFAC, -1, INT_MAX, NULL, NULL) );
    1702 "presolving/tworowbnd/maxpairfac",
    1703 "Maximum number of processed row pairs as multiple of the number of rows in the problem (-1: no limit)",
    1704 &presoldata->maxpairfac, FALSE, DEFAULT_MAXPAIRFAC, -1, INT_MAX, NULL, NULL) );
    1705
    1706 return SCIP_OKAY;
    1707}
    SCIP_VAR * a
    Definition: circlepacking.c:66
    SCIP_VAR ** b
    Definition: circlepacking.c:65
    Constraint handler for linear constraints in their most general form, .
    #define NULL
    Definition: def.h:248
    #define SCIP_Longint
    Definition: def.h:141
    #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 MAX(x, y)
    Definition: def.h:220
    #define SCIP_LONGINT_MAX
    Definition: def.h:142
    #define SCIP_CALL(x)
    Definition: def.h:355
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:759
    void SCIPhashsetFree(SCIP_HASHSET **hashset, BMS_BLKMEM *blkmem)
    Definition: misc.c:3833
    SCIP_Bool SCIPhashsetExists(SCIP_HASHSET *hashset, void *element)
    Definition: misc.c:3860
    SCIP_RETCODE SCIPhashsetInsert(SCIP_HASHSET *hashset, BMS_BLKMEM *blkmem, void *element)
    Definition: misc.c:3843
    SCIP_RETCODE SCIPhashsetCreate(SCIP_HASHSET **hashset, BMS_BLKMEM *blkmem, int size)
    Definition: misc.c:3802
    #define SCIPhashTwo(a, b)
    Definition: pub_misc.h:568
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    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 SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:57
    SCIP_RETCODE SCIPincludePresolTworowbnd(SCIP *scip)
    #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 SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #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 SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    void SCIPpresolSetData(SCIP_PRESOL *presol, SCIP_PRESOLDATA *presoldata)
    Definition: presol.c:538
    SCIP_PRESOLDATA * SCIPpresolGetData(SCIP_PRESOL *presol)
    Definition: presol.c:528
    SCIP_RETCODE SCIPsetPresolInit(SCIP *scip, SCIP_PRESOL *presol, SCIP_DECL_PRESOLINIT((*presolinit)))
    Definition: scip_presol.c:180
    SCIP_RETCODE SCIPsetPresolFree(SCIP *scip, SCIP_PRESOL *presol, SCIP_DECL_PRESOLFREE((*presolfree)))
    Definition: scip_presol.c:164
    SCIP_RETCODE SCIPsetPresolCopy(SCIP *scip, SCIP_PRESOL *presol, SCIP_DECL_PRESOLCOPY((*presolcopy)))
    Definition: scip_presol.c:148
    SCIP_RETCODE SCIPincludePresolBasic(SCIP *scip, SCIP_PRESOL **presolptr, const char *name, const char *desc, int priority, int maxrounds, SCIP_PRESOLTIMING timing, SCIP_DECL_PRESOLEXEC((*presolexec)), SCIP_PRESOLDATA *presoldata)
    Definition: scip_presol.c:113
    const char * SCIPpresolGetName(SCIP_PRESOL *presol)
    Definition: presol.c:625
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    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 SCIPisEQ(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)
    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_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24268
    SCIP_Bool SCIPvarIsNonimpliedIntegral(SCIP_VAR *var)
    Definition: var.c:23506
    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
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
    Definition: var.c:23490
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24234
    SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
    Definition: scip_var.c:10318
    void SCIPselectWeightedReal(SCIP_Real *realarray, SCIP_Real *weights, SCIP_Real capacity, int len, int *medianpos)
    void SCIPsortIntInt(int *intarray1, int *intarray2, int len)
    void SCIPsortIntReal(int *intarray, SCIP_Real *realarray, int len)
    int SCIPmatrixGetRowNNonzs(SCIP_MATRIX *matrix, int row)
    Definition: matrix.c:2013
    const char * SCIPmatrixGetRowName(SCIP_MATRIX *matrix, int row)
    Definition: matrix.c:2025
    SCIP_Real SCIPmatrixGetRowLhs(SCIP_MATRIX *matrix, int row)
    Definition: matrix.c:2047
    const char * SCIPmatrixGetColName(SCIP_MATRIX *matrix, int col)
    Definition: matrix.c:1965
    SCIP_Real * SCIPmatrixGetRowValPtr(SCIP_MATRIX *matrix, int row)
    Definition: matrix.c:1977
    SCIP_Real SCIPmatrixGetRowRhs(SCIP_MATRIX *matrix, int row)
    Definition: matrix.c:2059
    SCIP_RETCODE SCIPmatrixCreate(SCIP *scip, SCIP_MATRIX **matrixptr, SCIP_Bool onlyifcomplete, SCIP_Bool *initialized, SCIP_Bool *complete, SCIP_Bool *infeasible, int *naddconss, int *ndelconss, int *nchgcoefs, int *nchgbds, int *nfixedvars)
    Definition: matrix.c:703
    int SCIPmatrixGetNColumns(SCIP_MATRIX *matrix)
    Definition: matrix.c:1897
    void SCIPmatrixFree(SCIP *scip, SCIP_MATRIX **matrix)
    Definition: matrix.c:1348
    SCIP_VAR * SCIPmatrixGetVar(SCIP_MATRIX *matrix, int col)
    Definition: matrix.c:1953
    int * SCIPmatrixGetRowIdxPtr(SCIP_MATRIX *matrix, int row)
    Definition: matrix.c:2001
    int SCIPmatrixGetNRows(SCIP_MATRIX *matrix)
    Definition: matrix.c:2037
    static SCIP_DECL_PRESOLINIT(presolInitTworowbnd)
    static SCIP_RETCODE addEntry(SCIP *scip, int *pos, int *listsize, int **hashlist, int **rowidxlist, int hash, int rowidx)
    static SCIP_RETCODE transformAndSolve(SCIP *scip, SCIP_MATRIX *matrix, int row1idx, int row2idx, SCIP_Bool swaprow1, SCIP_Bool swaprow2, SCIP_Real *aoriginal, SCIP_Real *acopy, SCIP_Real *coriginal, SCIP_Real *ccopy, SCIP_Bool *cangetbnd, SCIP_Real *lbs, SCIP_Real *ubs, SCIP_Real *newlbsoriginal, SCIP_Real *newlbscopy, SCIP_Real *newubsoriginal, SCIP_Real *newubscopy, SCIP_Bool *success, SCIP_Bool *infeasible)
    #define DEFAULT_MAXCONSIDEREDNONZEROS
    #define PRESOL_NAME
    static SCIP_DECL_PRESOLFREE(presolFreeTworowbnd)
    static int hashIndexPair(int idx1, int idx2)
    static SCIP_RETCODE solveSingleRowLP(SCIP *scip, SCIP_Real *a, SCIP_Real b, SCIP_Real *c, SCIP_Real *lbs, SCIP_Real *ubs, int len, SCIP_Real *obj, SCIP_Bool *solvable)
    static SCIP_DECL_PRESOLCOPY(presolCopyTworowbnd)
    static SCIP_RETCODE processHashlists(SCIP *scip, SCIP_PRESOLDATA *presoldata, SCIP_MATRIX *matrix, int *hashlist1, int *hashlist2, int lenhashlist1, int lenhashlist2, int *rowidxlist1, int *rowidxlist2, SCIP_Real *newlbs, SCIP_Real *newubs)
    #define PRESOL_PRIORITY
    static void * encodeRowPair(ROWPAIR *rowpair)
    static void findNextBlock(int *list, int len, int *start, int *end)
    static SCIP_RETCODE applyLPboundTightening(SCIP *scip, SCIP_MATRIX *matrix, int row1, int row2, SCIP_Bool swaprow1, SCIP_Bool swaprow2, SCIP_Real *lbs, SCIP_Real *ubs, SCIP_Bool *success)
    static SCIP_DECL_PRESOLEXEC(presolExecTworowbnd)
    #define DEFAULT_ENABLECOPY
    #define DEFAULT_MAXHASHFAC
    #define DEFAULT_MAXCOMBINEFAILS
    #define DEFAULT_MAXRETRIEVEFAILS
    #define DEFAULT_MAXPAIRFAC
    #define PRESOL_MAXROUNDS
    #define PRESOL_TIMING
    #define PRESOL_DESC
    do bound tightening by using two rows
    public methods for matrix
    #define SCIPdebugMessage
    Definition: pub_message.h:96
    default SCIP plugins
    struct SCIP_PresolData SCIP_PRESOLDATA
    Definition: type_presol.h:51
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_CUTOFF
    Definition: type_result.h:48
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_SUCCESS
    Definition: type_result.h:58
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63