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