Scippy

    SCIP

    Solving Constraint Integer Programs

    presol_dualinfer.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/**@file presol_dualinfer.c
    25 * @ingroup DEFPLUGINS_PRESOL
    26 * @brief dual inference presolver
    27 * @author Dieter Weninger
    28 * @author Patrick Gemander
    29 *
    30 * This presolver does bound strengthening on continuous variables (columns) for getting bounds on dual variables y.
    31 * The bounds of the dual variables are then used to fix primal variables or change the side of constraints.
    32 * For ranged rows one needs to decide which side (rhs or lhs) determines the equality.
    33 *
    34 * We distinguish two cases concerning complementary slackness:
    35 * i) reduced cost fixing: c_j - sup_y(y^T A_{.j}) > 0 => x_j = l_j
    36 * c_j - inf_y(y^T A_{.j}) < 0 => x_j = u_j
    37 * ii) positive dual lower bound: y_i > 0 => A_{i.}x = b_i
    38 *
    39 * Further information on this presolving approach are given in
    40 * Achterberg et al. "Presolve reductions in mixed integer programming"
    41 * and for a two-column extension in
    42 * Chen et al. "Two-row and two-column mixed-integer presolve using hasing-based pairing methods".
    43 */
    44
    45/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    46
    47#include <stdio.h>
    48#include <assert.h>
    49#include <string.h>
    50
    51#include "scip/scipdefplugins.h"
    52#include "scip/pub_matrix.h"
    54#include "scip/cons_linear.h"
    56#include "scip/pub_cons.h"
    57#include "scip/pub_matrix.h"
    58#include "scip/pub_message.h"
    59#include "scip/pub_presol.h"
    60#include "scip/pub_var.h"
    61#include "scip/scip_general.h"
    62#include "scip/scip_mem.h"
    63#include "scip/scip_message.h"
    64#include "scip/scip_numerics.h"
    65#include "scip/scip_presol.h"
    66#include "scip/scip_prob.h"
    67#include "scip/scip_probing.h"
    68#include "scip/scip_var.h"
    69
    70#define PRESOL_NAME "dualinfer"
    71#define PRESOL_DESC "exploit dual information for fixings and side changes"
    72#define PRESOL_PRIORITY (-3000) /**< priority of the presolver (>= 0: before, < 0: after constraint handlers) */
    73#define PRESOL_MAXROUNDS 0 /**< maximal number of presolving rounds the presolver participates in (-1: no limit) */
    74#define PRESOL_TIMING SCIP_PRESOLTIMING_EXHAUSTIVE /* timing of the presolver (fast, medium, or exhaustive) */
    75
    76#define DEFAULT_TWOCOLUMN_COMBINE TRUE /**< should two column convex combination be used per default */
    77#define DEFAULT_MAXLOOPS_DUALBNDSTR 12 /**< default maximal number of loops for dual bound strengthening */
    78#define DEFAULT_MAXCONSIDEREDNONZEROS 100 /**< default maximal number of considered non-zeros within one row */
    79#define DEFAULT_MAXRETRIEVEFAILS 1000 /**< default maximal number of consecutive useless hashtable retrieves */
    80#define DEFAULT_MAXCOMBINEFAILS 1000 /**< default maximal number of consecutive useless row combines */
    81#define DEFAULT_MAXHASHFAC 10 /**< default maximal number of hashlist entries as multiple of number of rows in the problem */
    82#define DEFAULT_MAXPAIRFAC 1 /**< default maximal number of processed row pairs as multiple of the number of rows in the problem */
    83#define DEFAULT_MAXROWSUPPORT 3 /**< default maximal number of non-zeros in one row for turning an inequality into an equality */
    84
    85
    86/*
    87 * Data structures
    88 */
    89
    90/** control parameters */
    91struct SCIP_PresolData
    92{
    93 SCIP_Bool usetwocolcombine; /**< use convex combination of two columns */
    94 int maxdualbndloops; /**< default number of dual bound strengthening loops */
    95 int maxpairfac; /**< maximal number of processed row pairs as multiple of the number of rows in the problem (-1: no limit) */
    96 int maxhashfac; /**< maximal number of hashlist entries as multiple of number of rows in the problem (-1: no limit) */
    97 int maxretrievefails; /**< maximal number of consecutive useless hashtable retrieves */
    98 int maxcombinefails; /**< maximal number of consecutive useless row combines */
    99 int maxconsiderednonzeros; /**< maximal number of considered non-zeros within one row (-1: no limit) */
    100 int maxrowsupport; /**< maximal number of non-zeros in one row for turning an inequality into an equality */
    101};
    102
    103/** type of variable fixing direction */
    105{
    106 FIXATLB = -1, /** fix variable at its lower bound */
    107 NOFIX = 0, /** no fixing */
    108 FIXATUB = 1 /** fix variable at its upper bound */
    111
    112/** type of constraint side change */
    114{
    115 RHSTOLHS = -1, /** set rhs to value of lhs */
    116 NOCHANGE = 0, /** no side change */
    117 LHSTORHS = 1 /** set lhs to value of rhs */
    120
    121/** Signum for convex-combined variable coefficients \f$(\lambda * A_{ri} + (1 - \lambda) * A_{si})\f$
    122 * UP - Coefficient changes from negative to positive for increasing lambda
    123 * DN - Coefficient changes from positive to negative for increasing lambda
    124 * POS - Coefficient is positive for all lambda in (0,1)
    125 * NEG - Coefficient is negative for all lambda in (0,1)
    126 */
    127enum signum {UP, DN, POS, NEG};
    128
    129/** structure representing a pair of column indices; used for lookup in a hashtable */
    131{
    132 int col1idx; /**< first row index */
    133 int col2idx; /**< second row index */
    134};
    135typedef struct ColPair COLPAIR;
    136
    137/*
    138 * Local methods
    139 */
    140
    141/** encode contents of a colpair as void* pointer */
    142static
    143void*
    145 COLPAIR* colpair /**< pointer to colpair */
    146 )
    147{
    148 uint64_t a;
    149 uint64_t b;
    150
    151 assert(colpair->col1idx >= 0);
    152 assert(colpair->col2idx >= 0);
    153
    154 a = (uint64_t)(long)colpair->col1idx;
    155 b = (uint64_t)(long)colpair->col2idx;
    156 return (void*)((a << 32) | b);
    157}
    158
    159/** compute single positive int hashvalue for two ints */
    160static
    161int
    163 int idx1, /**< first integer index */
    164 int idx2 /**< second integer index */
    165 )
    166{
    167 uint32_t hash = SCIPhashTwo(idx1, idx2);
    168 return (int)(hash>>1);
    169}
    170
    171/** add hash/rowidx pair to hashlist/rowidxlist **/
    172static
    174 SCIP* scip, /**< SCIP datastructure */
    175 int* pos, /**< position of last entry added */
    176 int* listsize, /**< size of hashlist and rowidxlist */
    177 int** hashlist, /**< block memory array containing hashes */
    178 int** colidxlist, /**< block memory array containing column indices */
    179 int hash, /**< hash to be inserted */
    180 int colidx /**< column index to be inserted */
    181 )
    182{
    183 if( (*pos) >= (*listsize) )
    184 {
    185 int newsize = SCIPcalcMemGrowSize(scip, (*pos) + 1);
    186 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, hashlist, (*listsize), newsize) );
    187 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, colidxlist, (*listsize), newsize) );
    188 (*listsize) = newsize;
    189 }
    190
    191 (*hashlist)[(*pos)] = hash;
    192 (*colidxlist)[(*pos)] = colidx;
    193 (*pos)++;
    194
    195 return SCIP_OKAY;
    196}
    197
    198/** Within a sorted list, get next block with same value
    199 * E.g. for [h1, h1, h1, h2, h2, h2, h2, h3,...] and end = 0
    200 * returns start = 0, end = 3
    201 * and on a second call with end = 3 on the same list
    202 * returns start = 3, end = 7.
    203 */
    204static
    206 const int* list, /**< list of integers */
    207 int len, /**< length of list */
    208 int* start, /**< variable to contain start index of found block */
    209 int* end /**< variable to contain end index of found block */
    210 )
    211{
    212 int i;
    213 (*start) = (*end);
    214 i = (*end) + 1;
    215 while( i < len && list[i] == list[i - 1] )
    216 i++;
    217
    218 (*end) = i;
    219}
    220
    221/**
    222 * The algorithm described in Belotti P. "Bound reduction using pairs of linear inequalities"
    223 * tries to derive upper and lower bounds for all variables via convex combinations of linear inequalities
    224 * We apply Belotti's algorithm to pairs of columns of continuous variables.
    225 */
    226static
    228 SCIP* scip, /**< SCIP datastructure */
    229 int* row1idxptr, /**< indices specifying bound positions in lbs and ubs for first row */
    230 int* row2idxptr, /**< indices specifying bound positions in lbs und ubs for second row */
    231 SCIP_Real* row1valptr, /**< first row coefficients */
    232 SCIP_Real* row2valptr, /**< second row coefficients */
    233 SCIP_Real b1, /**< rhs of first row */
    234 SCIP_Real b2, /**< rhs of second row*/
    235 int row1len, /**< length of first row (e.g. row1idxptr and row1valptr)*/
    236 int row2len, /**< length of second row (e.g. row2idxptr and row2valptr)*/
    237 int ncols, /**< length of bound arrays lbs and ubs */
    238 SCIP_Bool swaprow1, /**< should the sense of the first row be swapped to <= ? */
    239 SCIP_Bool swaprow2, /**< should the sense of the second row be swapped to <= ? */
    240 SCIP_Real* lbs, /**< lower bound array */
    241 SCIP_Real* ubs, /**< upper bound array */
    242 SCIP_Bool* success /**< we return (success || found better bounds") */
    243 )
    244{
    245 int i;
    246 int j;
    247 int nvars;
    248 int* varinds;
    249 int nbreakpoints;
    250 SCIP_Real* breakpoints;
    251 int idx;
    252 int idx1;
    253 int idx2;
    254 SCIP_Real* row1coefs;
    255 SCIP_Real* row2coefs;
    256 enum signum* signs;
    257 int ninfs;
    258 int l1infs;
    259 SCIP_Real l1;
    260 SCIP_Real l2;
    261 SCIP_Real* newlbs;
    262 SCIP_Real* newubs;
    263 SCIP_Real coef;
    264 int sign;
    265 int shift;
    266
    267 SCIP_CALL( SCIPallocBufferArray(scip, &row1coefs, ncols) );
    268 SCIP_CALL( SCIPallocBufferArray(scip, &row2coefs, ncols) );
    269
    270 SCIPsortIntReal(row1idxptr, row1valptr, row1len);
    271 SCIPsortIntReal(row2idxptr, row2valptr, row2len);
    272
    273 /* swap rows if necessary */
    274 if( swaprow1 )
    275 {
    276 for( i = 0; i < row1len; i++ )
    277 row1coefs[row1idxptr[i]] = -row1valptr[i];
    278 b1 = -b1;
    279 }
    280 else
    281 {
    282 for( i = 0; i < row1len; i++ )
    283 row1coefs[row1idxptr[i]] = row1valptr[i];
    284 }
    285
    286 if( swaprow2 )
    287 {
    288 for( i = 0; i < row2len; i++ )
    289 row2coefs[row2idxptr[i]] = -row2valptr[i];
    290 b2 = -b2;
    291 }
    292 else
    293 {
    294 for( i = 0; i < row2len; i++ )
    295 row2coefs[row2idxptr[i]] = row2valptr[i];
    296 }
    297
    298 SCIP_CALL( SCIPallocBufferArray(scip, &varinds, ncols) );
    299 SCIP_CALL( SCIPallocBufferArray(scip, &signs, ncols) );
    300 SCIP_CALL( SCIPallocBufferArray(scip, &breakpoints, ncols) );
    301
    302 /* calculate cancellation breakpoints and sign behaviour */
    303 i = 0;
    304 j = 0;
    305 nvars = 0;
    306 nbreakpoints = 0;
    307 while( i < row1len && j < row2len )
    308 {
    309 assert(i + 1 == row1len || row1idxptr[i] < row1idxptr[i + 1]);
    310 assert(j + 1 == row2len || row2idxptr[j] < row2idxptr[j + 1]);
    311
    312 idx1 = row1idxptr[i];
    313 idx2 = row2idxptr[j];
    314
    315 /* We use 2.0 as default value for "no cancellation". For cancellations, this will be replaced by values in (0,1).
    316 * A value larger than 1.0 is used because we sort the array and want to put non-cancellations to the end. */
    317 breakpoints[nvars] = 2.0;
    318
    319 if( idx1 == idx2 )
    320 {
    321 if( (SCIPisNegative(scip, row1coefs[idx1]) && SCIPisPositive(scip, row2coefs[idx2])) ||
    322 (SCIPisPositive(scip, row1coefs[idx1]) && SCIPisNegative(scip, row2coefs[idx2])) )
    323 {
    324 if( SCIPisNegative(scip, row2coefs[idx2]) )
    325 signs[idx1] = UP;
    326 else
    327 signs[idx1] = DN;
    328
    329 breakpoints[nvars] = row2coefs[idx2] / (row2coefs[idx2] - row1coefs[idx1]);
    330 nbreakpoints++;
    331 }
    332 else if( SCIPisPositive(scip, row1coefs[idx1]) )
    333 signs[idx1] = POS;
    334 else
    335 signs[idx1] = NEG;
    336
    337 varinds[nvars] = idx1;
    338 i++;
    339 j++;
    340 }
    341 else if( idx1 < idx2 )
    342 {
    343 if( SCIPisPositive(scip, row1coefs[idx1]) )
    344 signs[idx1] = POS;
    345 else
    346 signs[idx1] = NEG;
    347
    348 /* We will access this entry later on, so we explicitly write a zero here */
    349 row2coefs[idx1] = 0.0;
    350
    351 varinds[nvars] = idx1;
    352 i++;
    353 }
    354 else
    355 {
    356 assert(idx1 > idx2);
    357 if( SCIPisPositive(scip, row2coefs[idx2]) )
    358 signs[idx2] = POS;
    359 else
    360 signs[idx2] = NEG;
    361
    362 /* We will access this entry later on, so we explicitly write a zero here */
    363 row1coefs[idx2] = 0.0;
    364
    365 varinds[nvars] = idx2;
    366 j++;
    367 }
    368 nvars++;
    369 }
    370
    371 while( i < row1len )
    372 {
    373 idx1 = row1idxptr[i];
    374
    375 if( SCIPisPositive(scip, row1coefs[idx1]) )
    376 signs[idx1] = POS;
    377 else
    378 signs[idx1] = NEG;
    379
    380 /* We will access this entry later on, so we explicitly write a zero here */
    381 row2coefs[idx1] = 0.0;
    382
    383 varinds[nvars] = idx1;
    384 breakpoints[nvars] = 2.0;
    385 nvars++;
    386 i++;
    387 }
    388
    389 while( j < row2len )
    390 {
    391 idx2 = row2idxptr[j];
    392
    393 if( SCIPisPositive(scip, row2coefs[idx2]) )
    394 signs[idx2] = POS;
    395 else
    396 signs[idx2] = NEG;
    397
    398 /* We will access this entry later on, so we explicitly write a zero here */
    399 row1coefs[idx2] = 0.0;
    400
    401 varinds[nvars] = idx2;
    402 breakpoints[nvars] = 2.0;
    403 nvars++;
    404 j++;
    405 }
    406
    407 SCIPsortRealInt(breakpoints, varinds, nvars);
    408
    409 /* The obvious preconditions for bound tightenings are met, so we try to calculate new bounds. */
    410 if( nbreakpoints >= 1 )
    411 {
    412 SCIP_CALL( SCIPallocBufferArray(scip, &newlbs, nvars) );
    413 SCIP_CALL( SCIPallocBufferArray(scip, &newubs, nvars) );
    414
    415 for( i = 0; i < nvars; i++)
    416 {
    417 idx = varinds[i];
    418 newlbs[i] = lbs[idx];
    419 newubs[i] = ubs[idx];
    420 }
    421
    422 /* calculate activity contributions of each row */
    423 l1 = b1;
    424 l2 = b2;
    425 l1infs = 0;
    426 ninfs = 0;
    427 for( i = 0; i < nvars; i++ )
    428 {
    429 idx = varinds[i];
    430 if( !SCIPisZero(scip, row2coefs[idx]) )
    431 {
    432 if( SCIPisNegative(scip, row2coefs[idx]) )
    433 {
    434 if( !SCIPisInfinity(scip, -lbs[idx]) )
    435 {
    436 l1 -= row1coefs[idx] * lbs[idx];
    437 l2 -= row2coefs[idx] * lbs[idx];
    438 }
    439 else
    440 ninfs++;
    441 }
    442 else
    443 {
    444 /* coefficient of second row is positive */
    445 if( !SCIPisInfinity(scip, ubs[idx]) )
    446 {
    447 l1 -= row1coefs[idx] * ubs[idx];
    448 l2 -= row2coefs[idx] * ubs[idx];
    449 }
    450 else
    451 ninfs++;
    452 }
    453 }
    454 else
    455 {
    456 /* since row2coefs[idx] is zero, we have to choose the bound using row1coefs[idx] */
    457 assert(!SCIPisZero(scip, row1coefs[idx]) && SCIPisZero(scip, row2coefs[idx]));
    458 if( SCIPisNegative(scip, row1coefs[idx]) )
    459 {
    460 if( !SCIPisInfinity(scip, -lbs[idx]) )
    461 l1 -= row1coefs[idx] * lbs[idx];
    462 else
    463 l1infs++;
    464 }
    465 else
    466 {
    467 /* coefficient of first row is positive */
    468 if( !SCIPisInfinity(scip, ubs[idx]) )
    469 l1 -= row1coefs[idx] * ubs[idx];
    470 else
    471 l1infs++;
    472 }
    473 }
    474 }
    475
    476 /* Calculate bounds for lambda = 0 */
    477#ifdef SCIP_MORE_DEBUG
    478 SCIPdebugMsg(scip, "lambda = 0, l1 = %g, l2 = %g, ninfs = %d\n", i, breakpoints[i], l1, l2, ninfs);
    479#endif
    480
    481 if( ninfs <= 1 )
    482 {
    483#ifdef SCIP_MORE_DEBUG
    484 SCIP_Real oldlb;
    485 SCIP_Real oldub;
    486#endif
    487 for( i = 0; i < nvars; i++ )
    488 {
    489#ifdef SCIP_MORE_DEBUG
    490 oldlb = newlbs[i];
    491 oldub = newubs[i];
    492#endif
    493 idx = varinds[i];
    494 if( SCIPisPositive(scip, row2coefs[idx]) )
    495 {
    496 if( ninfs == 0 )
    497 newlbs[i] = MAX(newlbs[i], (l2 + row2coefs[idx] * ubs[idx]) / row2coefs[idx]);
    498 else if( SCIPisInfinity(scip, ubs[idx]) )
    499 newlbs[i] = MAX(newlbs[i], l2 / row2coefs[idx]);
    500 }
    501 else if ( SCIPisNegative(scip, row2coefs[idx]) )
    502 {
    503 if( ninfs == 0 )
    504 newubs[i] = MIN(newubs[i], (l2 + row2coefs[idx] * lbs[idx]) / row2coefs[idx]);
    505 else if( SCIPisInfinity(scip, -lbs[idx]) )
    506 newubs[i] = MIN(newubs[i], l2 / row2coefs[idx]);
    507 }
    508#ifdef SCIP_MORE_DEBUG
    509 if( !SCIPisEQ(scip, oldlb, newlbs[i]) || !SCIPisEQ(scip, oldub, newubs[i]) )
    510 SCIPdebugMsg(scip, "%g <= %g <= var_%d <= %g <= %g\n", oldlb, newlbs[i], i, newubs[i], oldub);
    511#endif
    512 }
    513 }
    514
    515 ninfs += l1infs;
    516
    517 i = 0;
    518 while( i < nbreakpoints )
    519 {
    520 int nnewinfs;
    521 SCIP_Real l1update;
    522 SCIP_Real l2update;
    523 SCIP_Bool updated;
    524
    525 /* determine number of infinities and compute update for l1 and l2 */
    526 shift = 0;
    527 nnewinfs = 0;
    528 l1update = 0.0;
    529 l2update = 0.0;
    530 updated = FALSE;
    531 j = i;
    532 while( !updated )
    533 {
    534 idx = varinds[j];
    535 assert(signs[idx] == UP || signs[idx] == DN);
    536 if( signs[idx] == UP )
    537 sign = 1;
    538 else
    539 sign = -1;
    540
    541 if( !SCIPisInfinity(scip, -lbs[idx]) )
    542 {
    543 l1update += sign * row1coefs[idx] * lbs[idx];
    544 l2update += sign * row2coefs[idx] * lbs[idx];
    545 }
    546 else
    547 {
    548 if( signs[idx] == UP )
    549 ninfs--;
    550 else
    551 nnewinfs++;
    552 }
    553
    554 if( !SCIPisInfinity(scip, ubs[idx]) )
    555 {
    556 l1update -= sign * row1coefs[idx] * ubs[idx];
    557 l2update -= sign * row2coefs[idx] * ubs[idx];
    558 }
    559 else
    560 {
    561 if( signs[idx] == UP )
    562 nnewinfs++;
    563 else
    564 ninfs--;
    565 }
    566
    567 if( signs[idx] == UP )
    568 signs[idx] = POS;
    569 else
    570 signs[idx] = NEG;
    571
    572 if( j + 1 >= nbreakpoints || !SCIPisEQ(scip, breakpoints[j], breakpoints[j + 1]) )
    573 updated = TRUE;
    574
    575 shift++;
    576 j++;
    577 }
    578
    579#ifdef SCIP_MORE_DEBUG
    580 SCIPdebugMsg(scip, "lambda_%d = %g, l1 = %g, l2 = %g, ninfs = %d\n", i, breakpoints[i], l1, l2, ninfs);
    581#endif
    582
    583 assert(ninfs >= 0);
    584
    585 /* if more than one infinity destroys our bounds we cannot tighten anything */
    586 if( ninfs <= 1 )
    587 {
    588 /* check for bounds to be tightened */
    589 for( j = 0; j < nvars; j++ )
    590 {
    591#ifdef SCIP_MORE_DEBUG
    592 SCIP_Real oldlb = newlbs[j];
    593 SCIP_Real oldub = newubs[j];
    594#endif
    595
    596 idx = varinds[j];
    597 coef = breakpoints[i] * row1coefs[idx] + (1 - breakpoints[i]) * row2coefs[idx];
    598 assert(!SCIPisEQ(scip, breakpoints[i], 2.0));
    599
    600 /* skip if the coefficient is too close to zero as it becomes numerically unstable */
    601 if( SCIPisZero(scip, coef) )
    602 continue;
    603
    604 if( signs[idx] == POS || signs[idx] == DN )
    605 {
    606 if( ninfs == 0 )
    607 newlbs[j] = MAX(newlbs[j], (breakpoints[i] * l1 + (1 - breakpoints[i]) * l2 + coef * ubs[idx]) / coef);
    608 else if( SCIPisInfinity(scip, ubs[idx]) )
    609 newlbs[j] = MAX(newlbs[j], (breakpoints[i] * l1 + (1 - breakpoints[i]) * l2) / coef);
    610 }
    611 else if ( signs[idx] == NEG || signs[idx] == UP )
    612 {
    613 if( ninfs == 0 )
    614 newubs[j] = MIN(newubs[j], (breakpoints[i] * l1 + (1 - breakpoints[i]) * l2 + coef * lbs[idx]) / coef);
    615 else if( SCIPisInfinity(scip, -lbs[idx]) )
    616 newubs[j] = MIN(newubs[j], (breakpoints[i] * l1 + (1 - breakpoints[i]) * l2) / coef);
    617 }
    618#ifdef SCIP_MORE_DEBUG
    619 if( !SCIPisEQ(scip, oldlb, newlbs[j]) || !SCIPisEQ(scip, oldub, newubs[j]) )
    620 SCIPdebugMsg(scip, "%g <= %g <= var_%d <= %g <= %g\n", oldlb, newlbs[j], j, newubs[j], oldub);
    621#endif
    622 }
    623 }
    624
    625 i += shift;
    626 ninfs += nnewinfs;
    627 l1 += l1update;
    628 l2 += l2update;
    629 }
    630
    631 /* check infinities in first row */
    632 ninfs = 0;
    633 for( i = 0; i < nvars; i++ )
    634 {
    635 idx = varinds[i];
    636 if( (SCIPisPositive(scip, row1coefs[idx]) && SCIPisInfinity(scip, ubs[idx]))
    637 || (SCIPisNegative(scip, row1coefs[idx]) && SCIPisInfinity(scip, -lbs[idx])) )
    638 ninfs++;
    639 }
    640
    641 /* calculate bounds for lambda = 1 */
    642#ifdef SCIP_MORE_DEBUG
    643 SCIPdebugMsg(scip, "lambda = 1, l1 = %g, l2 = %g, ninfs = %d\n", i, breakpoints[i], l1, l2, ninfs);
    644#endif
    645 if( ninfs <= 1 )
    646 {
    647#ifdef SCIP_MORE_DEBUG
    648 SCIP_Real oldlb;
    649 SCIP_Real oldub;
    650#endif
    651 for( i = 0; i < nvars; i++ )
    652 {
    653#ifdef SCIP_MORE_DEBUG
    654 oldlb = newlbs[i];
    655 oldub = newubs[i];
    656#endif
    657 idx = varinds[i];
    658 if( SCIPisPositive(scip, row1coefs[idx]) )
    659 {
    660 if( ninfs == 0 )
    661 newlbs[i] = MAX(newlbs[i], (l1 + row1coefs[idx] * ubs[idx]) / row1coefs[idx]);
    662 else if( SCIPisInfinity(scip, ubs[idx]) )
    663 newlbs[i] = MAX(newlbs[i], l1 / row1coefs[idx]);
    664 }
    665 else if ( SCIPisNegative(scip, row1coefs[idx]) )
    666 {
    667 if( ninfs == 0 )
    668 newubs[i] = MIN(newubs[i], (l1 + row1coefs[idx] * lbs[idx]) / row1coefs[idx]);
    669 else if( SCIPisInfinity(scip, -lbs[idx]) )
    670 newubs[i] = MIN(newubs[i], l1 / row1coefs[idx]);
    671 }
    672#ifdef SCIP_MORE_DEBUG
    673 if( !SCIPisEQ(scip, oldlb, newlbs[i]) || !SCIPisEQ(scip, oldub, newubs[i]) )
    674 SCIPdebugMsg(scip, "%g <= %g <= var_%i <= %g <= %g\n", oldlb, newlbs[i], i, newubs[i], oldub);
    675#endif
    676 }
    677 }
    678
    679 /* update bound arrays and determine success */
    680 for( i = 0; i < nvars; i++ )
    681 {
    682 idx = varinds[i];
    683
    684 assert(SCIPisLE(scip, lbs[idx], newlbs[i]));
    685 assert(SCIPisGE(scip, ubs[idx], newubs[i]));
    686
    687 if( SCIPisGT(scip, newlbs[i], lbs[idx]) || SCIPisLT(scip, newubs[i], ubs[idx]) )
    688 {
    689 (*success) = TRUE;
    690
    691 lbs[idx] = newlbs[i];
    692 ubs[idx] = newubs[i];
    693 }
    694 }
    695 SCIPfreeBufferArray(scip, &newubs);
    696 SCIPfreeBufferArray(scip, &newlbs);
    697 }
    698
    699 SCIPfreeBufferArray(scip, &breakpoints);
    700 SCIPfreeBufferArray(scip, &signs);
    701 SCIPfreeBufferArray(scip, &varinds);
    702 SCIPfreeBufferArray(scip, &row2coefs);
    703 SCIPfreeBufferArray(scip, &row1coefs);
    704
    705 return SCIP_OKAY;
    706}
    707
    708/** get minimal and maximal residual activities without one specific column */
    709static
    711 SCIP* scip, /**< SCIP main data structure */
    712 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
    713 int withoutcol, /**< exclude this column index */
    714 int row, /**< row index */
    715 SCIP_Real* lbs, /**< lower bounds */
    716 SCIP_Real* ubs, /**< upper bounds */
    717 SCIP_Real* minresactivity, /**< minimum residual activity of this row */
    718 SCIP_Real* maxresactivity, /**< maximum residual activity of this row */
    719 SCIP_Bool* isminsettoinfinity, /**< flag indicating if minresactiviy is set to infinity */
    720 SCIP_Bool* ismaxsettoinfinity /**< flag indicating if maxresactiviy is set to infinity */
    721 )
    722{
    723 SCIP_Real coef;
    724 int* rowpnt;
    725 int* rowend;
    726 SCIP_Real* valpnt;
    727 int nmaxactneginf;
    728 int nmaxactposinf;
    729 int nminactneginf;
    730 int nminactposinf;
    731 SCIP_Real maxresact;
    732 SCIP_Real minresact;
    733 int col;
    734
    735 assert(scip != NULL);
    736 assert(matrix != NULL);
    737 assert(minresactivity != NULL);
    738 assert(maxresactivity != NULL);
    739 assert(isminsettoinfinity != NULL);
    740 assert(ismaxsettoinfinity != NULL);
    741
    742 *isminsettoinfinity = FALSE;
    743 *ismaxsettoinfinity = FALSE;
    744
    745 nmaxactneginf = 0;
    746 nmaxactposinf = 0;
    747 nminactneginf = 0;
    748 nminactposinf = 0;
    749 maxresact = 0;
    750 minresact = 0;
    751
    752 rowpnt = SCIPmatrixGetRowIdxPtr(matrix, row);
    753 rowend = rowpnt + SCIPmatrixGetRowNNonzs(matrix, row);
    754 valpnt = SCIPmatrixGetRowValPtr(matrix, row);
    755
    756 for( ; rowpnt < rowend; rowpnt++, valpnt++ )
    757 {
    758 col = *rowpnt;
    759
    760 if( col == withoutcol )
    761 continue;
    762
    763 coef = *valpnt;
    764
    765 /* positive coefficient */
    766 if( coef > 0.0 )
    767 {
    768 if( SCIPisInfinity(scip, ubs[col]) )
    769 nmaxactposinf++;
    770 else
    771 maxresact += coef * ubs[col];
    772
    773 if( SCIPisInfinity(scip, -lbs[col]) )
    774 nminactneginf++;
    775 else
    776 minresact += coef * lbs[col];
    777 }
    778 else /* negative coefficient */
    779 {
    780 if( SCIPisInfinity(scip, -lbs[col]) )
    781 nmaxactneginf++;
    782 else
    783 maxresact += coef * lbs[col];
    784
    785 if( SCIPisInfinity(scip, ubs[col]) )
    786 nminactposinf++;
    787 else
    788 minresact += coef * ubs[col];
    789 }
    790 }
    791
    792 if( (nmaxactneginf + nmaxactposinf) > 0 )
    793 *ismaxsettoinfinity = TRUE;
    794 else
    795 *maxresactivity = maxresact;
    796
    797 if( (nminactneginf + nminactposinf) > 0 )
    798 *isminsettoinfinity = TRUE;
    799 else
    800 *minresactivity = minresact;
    801}
    802
    803/** calculate the upper and lower bound of one variable from one row */
    804static
    806 SCIP* scip, /**< SCIP main data structure */
    807 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
    808 int col, /**< column index of variable */
    809 int row, /**< row index */
    810 SCIP_Real val, /**< coefficient of this column in this row */
    811 SCIP_Real* lbs, /**< lower bounds */
    812 SCIP_Real* ubs, /**< upper bounds */
    813 SCIP_Real* rowub, /**< upper bound of row */
    814 SCIP_Bool* ubfound, /**< flag indicating that an upper bound was calculated */
    815 SCIP_Real* rowlb, /**< lower bound of row */
    816 SCIP_Bool* lbfound /**< flag indicating that a lower bound was caluclated */
    817 )
    818{
    819 SCIP_Bool isminsettoinfinity;
    820 SCIP_Bool ismaxsettoinfinity;
    821 SCIP_Real minresactivity;
    822 SCIP_Real maxresactivity;
    823 SCIP_Real lhs;
    824 SCIP_Real rhs;
    825
    826 assert(rowub != NULL);
    827 assert(ubfound != NULL);
    828 assert(rowlb != NULL);
    829 assert(lbfound != NULL);
    830
    831 *rowub = SCIPinfinity(scip);
    832 *ubfound = FALSE;
    833 *rowlb = -SCIPinfinity(scip);
    834 *lbfound = FALSE;
    835
    836 getMinMaxActivityResiduals(scip, matrix, col, row, lbs, ubs,
    837 &minresactivity, &maxresactivity,
    838 &isminsettoinfinity, &ismaxsettoinfinity);
    839
    840 lhs = SCIPmatrixGetRowLhs(matrix, row);
    841 rhs = SCIPmatrixGetRowRhs(matrix, row);
    842
    843 if( val > 0.0 )
    844 {
    845 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) )
    846 {
    847 *rowub = (rhs - minresactivity) / val; // maybe one wants some kind of numerical guard of check that values is not too small for all these
    848 *ubfound = TRUE;
    849 }
    850
    851 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) )
    852 {
    853 *rowlb = (lhs - maxresactivity) / val;
    854 *lbfound = TRUE;
    855 }
    856 }
    857 else
    858 {
    859 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) )
    860 {
    861 *rowub = (lhs - maxresactivity) / val;
    862 *ubfound = TRUE;
    863 }
    864
    865 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) )
    866 {
    867 *rowlb = (rhs - minresactivity) / val;
    868 *lbfound = TRUE;
    869 }
    870 }
    871}
    872
    873
    874/** detect implied variable bounds */
    875static
    877 SCIP* scip, /**< SCIP main data structure */
    878 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
    879 int col, /**< column index for implied free test */
    880 SCIP_Real* lbs, /**< lower bounds */
    881 SCIP_Real* ubs, /**< upper bounds */
    882 SCIP_Bool* ubimplied, /**< flag indicating an implied upper bound */
    883 SCIP_Bool* lbimplied /**< flag indicating an implied lower bound */
    884 )
    885{
    886 SCIP_Real impliedub;
    887 SCIP_Real impliedlb;
    888 int* colpnt;
    889 int* colend;
    890 SCIP_Real* valpnt;
    891
    892 assert(scip != NULL);
    893 assert(matrix != NULL);
    894 assert(lbs != NULL);
    895 assert(ubs != NULL);
    896 assert(ubimplied != NULL);
    897 assert(lbimplied != NULL);
    898
    899 *ubimplied = FALSE;
    900 impliedub = SCIPinfinity(scip);
    901
    902 *lbimplied = FALSE;
    903 impliedlb = -SCIPinfinity(scip);
    904
    905 colpnt = SCIPmatrixGetColIdxPtr(matrix, col);
    906 colend = colpnt + SCIPmatrixGetColNNonzs(matrix, col);
    907 valpnt = SCIPmatrixGetColValPtr(matrix, col);
    908 for( ; (colpnt < colend); colpnt++, valpnt++ )
    909 {
    910 SCIP_Real rowub;
    911 SCIP_Bool ubfound;
    912 SCIP_Real rowlb;
    913 SCIP_Bool lbfound;
    914
    915 getVarBoundsOfRow(scip, matrix, col, *colpnt, *valpnt, lbs, ubs,
    916 &rowub, &ubfound, &rowlb, &lbfound);
    917
    918 if( ubfound && (rowub < impliedub) )
    919 impliedub = rowub;
    920
    921 if( lbfound && (rowlb > impliedlb) )
    922 impliedlb = rowlb;
    923 }
    924
    925 /* we consider +/-inf bounds as implied bounds */
    926 if( SCIPisInfinity(scip, ubs[col]) ||
    927 (!SCIPisInfinity(scip, ubs[col]) && SCIPisLE(scip, impliedub, ubs[col])) )
    928 *ubimplied = TRUE;
    929
    930 if( SCIPisInfinity(scip, -lbs[col]) ||
    931 (!SCIPisInfinity(scip, -lbs[col]) && SCIPisGE(scip, impliedlb, lbs[col])) )
    932 *lbimplied = TRUE;
    933}
    934
    935
    936/** calculate minimal column activity from one variable without one row */
    937static
    939 SCIP* scip, /**< SCIP main data structure */
    940 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
    941 int col, /**< column index */
    942 int withoutrow, /**< exclude this row index */
    943 SCIP_Real* lbdual, /**< lower bounds of dual variables */
    944 SCIP_Real* ubdual /**< upper bounds of dual variables */
    945 )
    946{
    947 SCIP_Real* valpnt;
    948 int* colpnt;
    949 int* colend;
    950 SCIP_Real val;
    951 SCIP_Real mincolactivity;
    952 int row;
    953
    954 assert(scip != NULL);
    955 assert(matrix != NULL);
    956 assert(lbdual != NULL);
    957 assert(ubdual != NULL);
    958
    959 mincolactivity = 0;
    960
    961 colpnt = SCIPmatrixGetColIdxPtr(matrix, col);
    962 colend = colpnt + SCIPmatrixGetColNNonzs(matrix, col);
    963 valpnt = SCIPmatrixGetColValPtr(matrix, col);
    964
    965 for( ; colpnt < colend; colpnt++, valpnt++ )
    966 {
    967 row = *colpnt;
    968 val = *valpnt;
    969
    970 if( row == withoutrow )
    971 continue;
    972
    973 if( val > 0.0 )
    974 {
    975 assert(!SCIPisInfinity(scip, -lbdual[row]));
    976 mincolactivity += val * lbdual[row];
    977 }
    978 else if( val < 0.0 )
    979 {
    980 assert(!SCIPisInfinity(scip, ubdual[row]));
    981 mincolactivity += val * ubdual[row];
    982 }
    983 }
    984
    985 return mincolactivity;
    986}
    987
    988
    989/** In the primal the residual activity of a constraint w.r.t. a variable is the activity of the constraint without the variable.
    990 * This function does the same but in the dual.
    991 * It computes the residual activity of column 'col' w.r.t. variable 'row'
    992 */
    993static
    995 SCIP* scip, /**< SCIP main data structure */
    996 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
    997 int col, /**< column index */
    998 int row, /**< row index */
    999 SCIP_Real val, /**< matrix coefficient */
    1000 SCIP_Real* lbdual, /**< lower bounds of the dual variables */
    1001 SCIP_Real* ubdual, /**< upper bounds of the dual variables */
    1002 const SCIP_Real* mincolact, /**< minimal column activities */
    1003 const int* mincolactinf, /**< number of infinite contributions to minimal column activity */
    1004 SCIP_Real* mincolresact /**< minimal residual column activity */
    1005 )
    1006{
    1007 assert(scip != NULL);
    1008 assert(matrix != NULL);
    1009 assert(lbdual != NULL);
    1010 assert(ubdual != NULL);
    1011 assert(mincolact != NULL);
    1012 assert(mincolactinf != NULL);
    1013 assert(mincolresact != NULL);
    1014
    1015 *mincolresact = -SCIPinfinity(scip);
    1016
    1017 if( val > 0.0 )
    1018 {
    1019 if( SCIPisInfinity(scip, -lbdual[row]) )
    1020 {
    1021 assert(mincolactinf[col] >= 1);
    1022 if( mincolactinf[col] == 1 )
    1023 *mincolresact = getMinColActWithoutRow(scip, matrix, col, row, lbdual, ubdual);
    1024 else
    1025 *mincolresact = -SCIPinfinity(scip);
    1026 }
    1027 else
    1028 {
    1029 if( mincolactinf[col] > 0 )
    1030 *mincolresact = -SCIPinfinity(scip);
    1031 else
    1032 *mincolresact = mincolact[col] - val * lbdual[row];
    1033 }
    1034 }
    1035 else if( val < 0.0 )
    1036 {
    1037 if( SCIPisInfinity(scip, ubdual[row]) )
    1038 {
    1039 assert(mincolactinf[col] >= 1);
    1040 if( mincolactinf[col] == 1 )
    1041 *mincolresact = getMinColActWithoutRow(scip, matrix, col, row, lbdual, ubdual);
    1042 else
    1043 *mincolresact = -SCIPinfinity(scip);
    1044 }
    1045 else
    1046 {
    1047 if( mincolactinf[col] > 0 )
    1048 *mincolresact = -SCIPinfinity(scip);
    1049 else
    1050 *mincolresact = mincolact[col] - val * ubdual[row];
    1051 }
    1052 }
    1053}
    1054
    1055/** calculate minimal column activity of one column */
    1056static
    1058 SCIP* scip, /**< SCIP main data structure */
    1059 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
    1060 int col, /**< column for activity calculations */
    1061 SCIP_Real* lbdual, /**< lower bounds of dual variables */
    1062 SCIP_Real* ubdual, /**< upper bounds of dual variables */
    1063 SCIP_Real* mincolact, /**< minimal column activities */
    1064 int* mincolactinf /**< number of -inf contributions to minimal column activity */
    1065 )
    1066{
    1067 SCIP_Real* valpnt;
    1068 int* colpnt;
    1069 int* colend;
    1070 SCIP_Real val;
    1071 int row;
    1072
    1073 assert(scip != NULL);
    1074 assert(matrix != NULL);
    1075 assert(lbdual != NULL);
    1076 assert(ubdual != NULL);
    1077 assert(mincolact != NULL);
    1078 assert(mincolactinf != NULL);
    1079
    1080 /* init activities */
    1081 mincolact[col] = 0.0;
    1082 mincolactinf[col] = 0;
    1083
    1084 colpnt = SCIPmatrixGetColIdxPtr(matrix, col);
    1085 colend = colpnt + SCIPmatrixGetColNNonzs(matrix, col);
    1086 valpnt = SCIPmatrixGetColValPtr(matrix, col);
    1087
    1088 /* calculate column activities */
    1089 for( ; colpnt < colend; colpnt++, valpnt++ )
    1090 {
    1091 row = *colpnt;
    1092 val = *valpnt;
    1093
    1094 if( val > 0.0 )
    1095 {
    1096 if(SCIPisInfinity(scip, -lbdual[row]))
    1097 mincolactinf[col]++;
    1098 else
    1099 mincolact[col] += val * lbdual[row];
    1100 }
    1101 else if( val < 0.0 )
    1102 {
    1103 if(SCIPisInfinity(scip, ubdual[row]))
    1104 mincolactinf[col]++;
    1105 else
    1106 mincolact[col] += val * ubdual[row];
    1107 }
    1108 }
    1109
    1110 /* update column activities if infinity counters are greater 0 */
    1111 if( mincolactinf[col] > 0 )
    1112 mincolact[col] = -SCIPinfinity(scip);
    1113}
    1114
    1115/** calculate maximal column activity of one column */
    1116static
    1118 SCIP* scip, /**< SCIP main data structure */
    1119 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
    1120 int col, /**< column for activity calculations */
    1121 SCIP_Real* lbdual, /**< lower bounds of dual variables */
    1122 SCIP_Real* ubdual, /**< upper bounds of dual variables */
    1123 SCIP_Real* maxcolact, /**< minimal column activities */
    1124 int* maxcolactinf /**< number of -inf contributions to minimal column activity */
    1125 )
    1126{
    1127 SCIP_Real* valpnt;
    1128 int* colpnt;
    1129 int* colend;
    1130 SCIP_Real val;
    1131 int row;
    1132
    1133 assert(scip != NULL);
    1134 assert(matrix != NULL);
    1135 assert(lbdual != NULL);
    1136 assert(ubdual != NULL);
    1137 assert(maxcolact != NULL);
    1138 assert(maxcolactinf != NULL);
    1139
    1140 /* init activities */
    1141 maxcolact[col] = 0.0;
    1142 maxcolactinf[col] = 0;
    1143
    1144 colpnt = SCIPmatrixGetColIdxPtr(matrix, col);
    1145 colend = colpnt + SCIPmatrixGetColNNonzs(matrix, col);
    1146 valpnt = SCIPmatrixGetColValPtr(matrix, col);
    1147
    1148 /* calculate column activities */
    1149 for( ; colpnt < colend; colpnt++, valpnt++ )
    1150 {
    1151 row = *colpnt;
    1152 val = *valpnt;
    1153
    1154 if( val > 0.0 )
    1155 {
    1156 if(SCIPisInfinity(scip, ubdual[row]))
    1157 maxcolactinf[col]++;
    1158 else
    1159 maxcolact[col] += val * ubdual[row];
    1160 }
    1161 else if( val < 0.0 )
    1162 {
    1163 if(SCIPisInfinity(scip, -lbdual[row]))
    1164 maxcolactinf[col]++;
    1165 else
    1166 maxcolact[col] += val * lbdual[row];
    1167 }
    1168 }
    1169
    1170 /* update column activities if infinity counters are greater 0 */
    1171 if( maxcolactinf[col] > 0 )
    1172 maxcolact[col] = SCIPinfinity(scip);
    1173}
    1174
    1175
    1176/** update minimal/maximal column activity infinity counters */
    1177static
    1179 SCIP* scip, /**< SCIP main data structure */
    1180 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
    1181 int row, /**< row index */
    1182 SCIP_Real* lbdual, /**< lower bounds of dual variables */
    1183 SCIP_Real* ubdual, /**< upper bounds of dual variables */
    1184 const SCIP_Bool* isubimplied, /**< flags indicating of the upper bound is implied */
    1185 SCIP_Real* mincolact, /**< minimal column activities */
    1186 int* mincolactinf, /**< number of infinity contributions to minimal column activity */
    1187 SCIP_Bool ubinfchange, /**< flag indicating if the upper bound has changed from infinity to a finite value */
    1188 SCIP_Bool lbinfchange /**< flag indicating if the lower bound has changed from -infinity to a finite value */
    1189 )
    1190{
    1191 SCIP_Real* valpnt;
    1192 int* rowpnt;
    1193 int* rowend;
    1194 SCIP_Real val;
    1195 int col;
    1196
    1197 rowpnt = SCIPmatrixGetRowIdxPtr(matrix, row);
    1198 rowend = rowpnt + SCIPmatrixGetRowNNonzs(matrix, row);
    1199 valpnt = SCIPmatrixGetRowValPtr(matrix, row);
    1200
    1201 /* look at all column entries present within row and update the
    1202 * corresponding infinity counters. if one counter gets to zero,
    1203 * then calculate this column activity new.
    1204 */
    1205
    1206 for(; (rowpnt < rowend); rowpnt++, valpnt++ )
    1207 {
    1208 col = *rowpnt;
    1209 val = *valpnt;
    1210
    1211 if( isubimplied[col] )
    1212 {
    1213 if( val < 0 )
    1214 {
    1215 if( ubinfchange )
    1216 {
    1217 assert(mincolactinf[col] > 0);
    1218 mincolactinf[col]--;
    1219 }
    1220 }
    1221 else if( val > 0 )
    1222 {
    1223 if( lbinfchange )
    1224 {
    1225 assert(mincolactinf[col] > 0);
    1226 mincolactinf[col]--;
    1227 }
    1228 }
    1229
    1230 if( mincolactinf[col] == 0 )
    1231 calcMinColActivity(scip, matrix, col, lbdual, ubdual, mincolact, mincolactinf);
    1232 }
    1233 }
    1234}
    1235
    1236#ifdef SCIP_DEBUG
    1237/** use LP calculations for determining the best dual variable bounds from a specific row index */
    1238static
    1240 SCIP* scip, /**< SCIP main data structure */
    1241 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
    1242 int row, /**< row index for dual bound calculations */
    1243 SCIP_Bool solveLP, /**< flag indicating to solve subscip LP */
    1244 SCIP_Real* lowerbnddual, /**< lower bound of dual variable */
    1245 SCIP_Real* upperbnddual /**< upper bound of dual variable */
    1246 )
    1247{
    1248 int i;
    1249 int nrows;
    1250 int ncols;
    1251 int numberconvars;
    1252 SCIP_VAR* var;
    1253 SCIP_VAR** variables;
    1254 SCIP_VAR** tmpvars;
    1255 SCIP_Real* tmpcoef;
    1256 SCIP_CONS** constraints;
    1257 int numDualVars;
    1258 SCIP* subscip;
    1259 SCIP_RETCODE retcode;
    1260 char name[SCIP_MAXSTRLEN+3];
    1261 int fillcnt;
    1262 int* colpnt;
    1263 int* colend;
    1264 SCIP_Real* valpnt;
    1265 int* colmap;
    1266
    1267 *lowerbnddual = -SCIPinfinity(scip);
    1268 *upperbnddual = SCIPinfinity(scip);
    1269
    1270 nrows = SCIPmatrixGetNRows(matrix);
    1271 assert(0 <= row && row < nrows);
    1272 ncols = SCIPmatrixGetNColumns(matrix);
    1273
    1274 SCIP_CALL( SCIPcreate(&subscip) );
    1275 SCIP_CALL( SCIPcreateProbBasic(subscip, "subscip") );
    1277
    1278 /* avoid recursive calls */
    1279 SCIP_CALL( SCIPsetIntParam(subscip, "presolving/dualinfer/maxrounds", 0) );
    1280 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
    1281 SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", TRUE) );
    1282
    1283 SCIP_CALL( SCIPallocBufferArray(scip, &colmap, ncols) );
    1284 numberconvars = 0;
    1285 for(i = 0; i < ncols; i++)
    1286 {
    1287 var = SCIPmatrixGetVar(matrix, i);
    1288 if( !SCIPvarIsNonimpliedIntegral(var) )
    1289 {
    1290 colmap[i] = numberconvars; /* start numbering with 0 */
    1291 numberconvars++;
    1292 }
    1293 else
    1294 colmap[i] = -1;
    1295 }
    1296 numDualVars = nrows + 2 * numberconvars;
    1297
    1298 /* create dual variables */
    1299 SCIP_CALL( SCIPallocBufferArray(scip, &variables, numDualVars) );
    1300 for( i = 0; i < nrows; i++ )
    1301 {
    1302 variables[i] = NULL;
    1303 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "y%d", i);
    1304 if( !SCIPmatrixIsRowRhsInfinity(matrix, i ) )
    1305 {
    1306 /* dual variable for equation or ranged row */
    1307 SCIP_CALL( SCIPcreateVarBasic(subscip, &variables[i], name,
    1309 }
    1310 else
    1311 {
    1312 /* dual variable for >= inequality */
    1313 SCIP_CALL( SCIPcreateVarBasic(subscip, &variables[i], name,
    1315 }
    1316 SCIP_CALL( SCIPaddVar(subscip, variables[i]) );
    1317 assert( variables[i] != NULL );
    1318 }
    1319
    1320 /* in addition, we introduce dual variables for the bounds,
    1321 because we treat each continuous variable as a free variable */
    1322 fillcnt = nrows;
    1323 for( i = 0; i < numberconvars; i++ )
    1324 {
    1325 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "ylb%d", fillcnt);
    1326 SCIP_CALL( SCIPcreateVarBasic(subscip, &variables[fillcnt], name,
    1328 SCIP_CALL( SCIPaddVar(subscip, variables[fillcnt]) );
    1329 assert( variables[fillcnt] != NULL );
    1330 fillcnt++;
    1331
    1332 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "yub%d", fillcnt);
    1333 SCIP_CALL( SCIPcreateVarBasic(subscip, &variables[fillcnt], name,
    1335 SCIP_CALL( SCIPaddVar(subscip, variables[fillcnt]) );
    1336 assert( variables[fillcnt] != NULL );
    1337 fillcnt++;
    1338 }
    1339 assert(numDualVars == fillcnt);
    1340
    1341 SCIP_CALL( SCIPallocBufferArray(scip, &tmpvars, numDualVars) );
    1342 SCIP_CALL( SCIPallocBufferArray(scip, &tmpcoef, numDualVars) );
    1343
    1344 SCIP_CALL( SCIPallocBufferArray(scip, &constraints, numberconvars) );
    1345 for( i = 0; i <numberconvars; i++)
    1346 constraints[i] = NULL;
    1347
    1348 for(i = 0; i < ncols; i++)
    1349 {
    1350 var = SCIPmatrixGetVar(matrix, i);
    1351 if( !SCIPvarIsNonimpliedIntegral(var) )
    1352 {
    1353 SCIP_Real objval = SCIPvarGetObj(var);
    1354 int cidx = colmap[i];
    1355 assert(0 <= cidx && cidx < numberconvars);
    1356
    1357 colpnt = SCIPmatrixGetColIdxPtr(matrix, i);
    1358 colend = colpnt + SCIPmatrixGetColNNonzs(matrix, i);
    1359 valpnt = SCIPmatrixGetColValPtr(matrix, i);
    1360 fillcnt = 0;
    1361 for( ; colpnt < colend; colpnt++, valpnt++ )
    1362 {
    1363 assert(0 <= *colpnt && *colpnt < nrows);
    1364 assert(variables[*colpnt] != NULL);
    1365 tmpvars[fillcnt] = variables[*colpnt];
    1366 tmpcoef[fillcnt] = *valpnt;
    1367 fillcnt++;
    1368 }
    1369
    1370 /* consider dual variable for a lower bound */
    1372 {
    1373 assert(variables[nrows + 2 * cidx] != NULL);
    1374 tmpvars[fillcnt] = variables[nrows + 2 * cidx];
    1375 tmpcoef[fillcnt] = 1.0;
    1376 fillcnt++;
    1377 }
    1378
    1379 /* consider dual variable for an upper bound */
    1381 {
    1382 assert(variables[nrows + 2 * cidx + 1] != NULL);
    1383 tmpvars[fillcnt] = variables[nrows + 2 * cidx + 1];
    1384 tmpcoef[fillcnt] = -1.0;
    1385 fillcnt++;
    1386 }
    1387
    1388 /* because we treat the continuous columns as free variable,
    1389 we need here an equality */
    1390 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "c%d", cidx);
    1391 SCIP_CALL( SCIPcreateConsBasicLinear(subscip, &constraints[cidx], name,
    1392 fillcnt, tmpvars, tmpcoef, objval, objval) );
    1393 SCIP_CALL( SCIPaddCons(subscip, constraints[cidx]) );
    1394 }
    1395 }
    1396
    1397 /* determine lower dual bound via a minimization problem */
    1399 SCIP_CALL( SCIPchgVarObj(subscip, variables[row], 1.0) );
    1400 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "dbg_min_%s.lp", SCIPvarGetName(variables[row]));
    1401 SCIP_CALL( SCIPwriteOrigProblem(subscip, name, "lp", FALSE) );
    1402 if( solveLP )
    1403 {
    1404 retcode = SCIPsolve(subscip);
    1405 if( retcode != SCIP_OKAY )
    1406 SCIPwarningMessage(scip, "Error subscip: <%d>\n", retcode);
    1407 else
    1408 {
    1409 if( SCIPgetStatus(subscip) == SCIP_STATUS_OPTIMAL )
    1410 {
    1411 SCIP_SOL* sol;
    1412 SCIP_Bool feasible;
    1413 sol = SCIPgetBestSol(subscip);
    1414 SCIP_CALL( SCIPcheckSolOrig(subscip, sol, &feasible, TRUE, TRUE) );
    1415
    1416 if(feasible)
    1417 *lowerbnddual = SCIPgetSolOrigObj(subscip, sol);
    1418 }
    1419 }
    1420 SCIP_CALL( SCIPfreeTransform(subscip) );
    1421 }
    1422
    1423 /* determine upper dual bound via a maximization problem */
    1425 SCIP_CALL( SCIPchgVarObj(subscip, variables[row], 1.0) );
    1426 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "dbg_max_%s.lp", SCIPvarGetName(variables[row]));
    1427 SCIP_CALL( SCIPwriteOrigProblem(subscip, name, "lp", FALSE) );
    1428 if( solveLP )
    1429 {
    1430 retcode = SCIPsolve(subscip);
    1431 if( retcode != SCIP_OKAY )
    1432 SCIPwarningMessage(scip, "Error subscip: <%d>\n", retcode);
    1433 else
    1434 {
    1435 if( SCIPgetStatus(subscip) == SCIP_STATUS_OPTIMAL )
    1436 {
    1437 SCIP_SOL* sol;
    1438 SCIP_Bool feasible;
    1439 sol = SCIPgetBestSol(subscip);
    1440 SCIP_CALL( SCIPcheckSolOrig(subscip, sol, &feasible, TRUE, TRUE) );
    1441
    1442 if(feasible)
    1443 *upperbnddual = SCIPgetSolOrigObj(subscip, sol);
    1444 }
    1445 }
    1446 SCIP_CALL( SCIPfreeTransform(subscip) );
    1447 }
    1448
    1449 /* release variables and constraints */
    1450 for( i = 0; i < numDualVars; i++ )
    1451 {
    1452 if(variables[i] != NULL)
    1453 SCIP_CALL( SCIPreleaseVar(subscip, &variables[i]) );
    1454 }
    1455 for( i = 0; i < numberconvars; i++ )
    1456 {
    1457 if(constraints[i] != NULL)
    1458 SCIP_CALL( SCIPreleaseCons(subscip, &constraints[i]) );
    1459 }
    1460
    1461 SCIPfreeBufferArray(scip, &constraints);
    1462 SCIPfreeBufferArray(scip, &tmpcoef);
    1463 SCIPfreeBufferArray(scip, &tmpvars);
    1464 SCIPfreeBufferArray(scip, &variables);
    1465 SCIP_CALL( SCIPfree(&subscip) );
    1466 SCIPfreeBufferArray(scip, &colmap);
    1467
    1468 return SCIP_OKAY;
    1469}
    1470#endif
    1471
    1472/** update bounds of the dual variables */
    1473static
    1475 SCIP* scip, /**< SCIP main data structure */
    1476 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
    1477 SCIP_Real objval, /**< objective function value */
    1478 SCIP_Real val, /**< matrix coefficient */
    1479 int row, /**< row index */
    1480 SCIP_Real mincolresact, /**< minimal column residual activity */
    1481 SCIP_Real* lbdual, /**< dual lower bounds */
    1482 SCIP_Real* ubdual, /**< dual upper bounds */
    1483 int* boundchanges, /**< counter for the number of bound changes */
    1484 SCIP_Bool* ubinfchange, /**< flag indicating an upper bound change from infinite to finite */
    1485 SCIP_Bool* lbinfchange /**< flag indicating a lower bound change from infinite to finite */
    1486 )
    1487{
    1488 SCIP_Real newlbdual;
    1489 SCIP_Real newubdual;
    1490
    1491 assert(scip != NULL);
    1492 assert(matrix != NULL);
    1493 assert(lbdual != NULL);
    1494 assert(ubdual != NULL);
    1495 assert(boundchanges != NULL);
    1496 assert(ubinfchange != NULL);
    1497 assert(lbinfchange != NULL);
    1498
    1499 *ubinfchange = FALSE;
    1500 *lbinfchange = FALSE;
    1501
    1502 if( !SCIPisInfinity(scip, -mincolresact) )
    1503 {
    1504 if( val > 0 )
    1505 {
    1506 newubdual = (objval - mincolresact) / val;
    1507
    1508 if( newubdual < ubdual[row] )
    1509 {
    1510 /* accept the new upper bound only if the numerics are reliable */
    1511 if( SCIPisLE(scip,lbdual[row],newubdual) )
    1512 {
    1513 if( SCIPisInfinity(scip, ubdual[row]) )
    1514 *ubinfchange = TRUE;
    1515
    1516 ubdual[row] = newubdual;
    1517 (*boundchanges)++;
    1518 }
    1519 }
    1520 }
    1521 else if( val < 0 )
    1522 {
    1523 newlbdual = (objval - mincolresact) / val;
    1524
    1525 if( newlbdual > lbdual[row] )
    1526 {
    1527 /* accept the new lower bound only if the numerics are reliable */
    1528 if( SCIPisLE(scip,newlbdual,ubdual[row]) )
    1529 {
    1530 if( SCIPisInfinity(scip, -lbdual[row]) )
    1531 *lbinfchange = TRUE;
    1532
    1533 lbdual[row] = newlbdual;
    1534 (*boundchanges)++;
    1535 }
    1536 }
    1537 }
    1538 }
    1539}
    1540
    1541/** dual bound strengthening */
    1542static
    1544 SCIP* scip, /**< SCIP main data structure */
    1545 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
    1546 SCIP_PRESOLDATA* presoldata, /**< presolver data structure */
    1547 FIXINGDIRECTION* varstofix, /**< array holding information for later upper/lower bound fixing */
    1548 int* npossiblefixings, /**< number of possible fixings */
    1549 SIDECHANGE* sidestochange, /**< array holding if this is an implied equality */
    1550 int* npossiblesidechanges/**< number of possible equality changes */
    1551 )
    1552{
    1553 SCIP_Real* lbdual;
    1554 SCIP_Real* ubdual;
    1555 SCIP_Real* mincolact;
    1556 int* mincolactinf;
    1557 SCIP_Real* maxcolact;
    1558 int* maxcolactinf;
    1559 int* colpnt;
    1560 int* colend;
    1561 SCIP_Real* valpnt;
    1562 int boundchanges;
    1563 int loops;
    1564 int i;
    1565 int j;
    1566 int k;
    1567 int nrows;
    1568 int ncols;
    1569 SCIP_Bool* isubimplied;
    1570 SCIP_Bool* islbimplied;
    1571 SCIP_Real* tmplbs;
    1572 SCIP_Real* tmpubs;
    1573 SCIP_VAR* var;
    1574 int* implubvars;
    1575 int nimplubvars;
    1576
    1577 SCIP_Longint maxhashes;
    1578 int maxlen;
    1579 int pospp;
    1580 int listsizepp;
    1581 int posmm;
    1582 int listsizemm;
    1583 int pospm;
    1584 int listsizepm;
    1585 int posmp;
    1586 int listsizemp;
    1587
    1588 int* hashlistpp;
    1589 int* hashlistmm;
    1590 int* hashlistpm;
    1591 int* hashlistmp;
    1592
    1593 int* colidxlistpp;
    1594 int* colidxlistmm;
    1595 int* colidxlistpm;
    1596 int* colidxlistmp;
    1597
    1598 int block1start;
    1599 int block1end;
    1600 int block2start;
    1601 int block2end;
    1602
    1603 SCIP_HASHSET* pairhashset;
    1604 SCIP_Real* colvalptr;
    1605 int* colidxptr;
    1606
    1607 assert(scip != NULL);
    1608 assert(matrix != NULL);
    1609 assert(varstofix != NULL);
    1610 assert(npossiblefixings != NULL);
    1611 assert(sidestochange != NULL);
    1612 assert(npossiblesidechanges != NULL);
    1613
    1614 nrows = SCIPmatrixGetNRows(matrix);
    1615 ncols = SCIPmatrixGetNColumns(matrix);
    1616
    1617 SCIP_CALL( SCIPallocBufferArray(scip, &tmplbs, ncols) );
    1618 SCIP_CALL( SCIPallocBufferArray(scip, &tmpubs, ncols) );
    1619 for( i = 0; i < ncols; i++ )
    1620 {
    1621 var = SCIPmatrixGetVar(matrix, i);
    1622 tmplbs[i] = SCIPvarGetLbLocal(var);
    1623 tmpubs[i] = SCIPvarGetUbLocal(var);
    1624 }
    1625
    1626 /* verify which bounds of continuous variables are implied */
    1627 SCIP_CALL( SCIPallocBufferArray(scip, &isubimplied, ncols) );
    1628 SCIP_CALL( SCIPallocBufferArray(scip, &islbimplied, ncols) );
    1629 SCIP_CALL( SCIPallocBufferArray(scip, &implubvars, ncols) );
    1630 nimplubvars = 0;
    1631 for( i = 0; i < ncols; i++ )
    1632 {
    1633 var = SCIPmatrixGetVar(matrix, i);
    1634
    1635 if( SCIPmatrixUplockConflict(matrix, i) || SCIPmatrixDownlockConflict(matrix, i)
    1637 {
    1638 /* we don't care about integral variables or variables that have conflicting locks */
    1639 isubimplied[i] = FALSE;
    1640 islbimplied[i] = FALSE;
    1641 }
    1642 else
    1643 {
    1644 getImpliedBounds(scip, matrix, i, tmplbs, tmpubs, &(isubimplied[i]), &(islbimplied[i]));
    1645
    1646 /* if a continuous variable has a not implied upper bound we can
    1647 * not use this variable (column) for propagating dual bounds.
    1648 * not implied lowers bound can usually be treated.
    1649 */
    1650
    1651 /* collect continuous variables with implied upper bound */
    1652 if( isubimplied[i] )
    1653 {
    1654 implubvars[nimplubvars] = i;
    1655 nimplubvars++;
    1656
    1657 /* reset implied bounds for further detections of other implied bounds */
    1658 tmpubs[i] = SCIPinfinity(scip);
    1659 }
    1660
    1661 if( islbimplied[i] )
    1662 tmplbs[i] = -SCIPinfinity(scip);
    1663 }
    1664 }
    1665
    1666 /* initialize bounds of the dual variables */
    1667 SCIP_CALL( SCIPallocBufferArray(scip, &lbdual, nrows) );
    1668 SCIP_CALL( SCIPallocBufferArray(scip, &ubdual, nrows) );
    1669 for( i = 0; i < nrows; i++ )
    1670 {
    1671 if( !SCIPmatrixIsRowRhsInfinity(matrix, i) )
    1672 {
    1673 /* dual free variable for equation or ranged row */
    1674 lbdual[i] = -SCIPinfinity(scip);
    1675 ubdual[i] = SCIPinfinity(scip);
    1676 }
    1677 else
    1678 {
    1679 /* dual variable for >= inequality */
    1680 lbdual[i] = 0.0;
    1681 ubdual[i] = SCIPinfinity(scip);
    1682 }
    1683 }
    1684
    1685 /* run convex combination on pairs of continuous variables (columns) using Belotti's algorithm */
    1686 if( nimplubvars >= 2 && presoldata->usetwocolcombine )
    1687 {
    1688 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &hashlistpp, ncols) );
    1689 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &hashlistmm, ncols) );
    1690 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &hashlistpm, ncols) );
    1691 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &hashlistmp, ncols) );
    1692
    1693 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &colidxlistpp, ncols) );
    1694 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &colidxlistmm, ncols) );
    1695 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &colidxlistpm, ncols) );
    1696 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &colidxlistmp, ncols) );
    1697
    1698 pospp = 0;
    1699 posmm = 0;
    1700 pospm = 0;
    1701 posmp = 0;
    1702 listsizepp = ncols;
    1703 listsizemm = ncols;
    1704 listsizepm = ncols;
    1705 listsizemp = ncols;
    1706 maxhashes = presoldata->maxhashfac == -1 ? SCIP_LONGINT_MAX : (((SCIP_Longint)ncols) * presoldata->maxhashfac);
    1707
    1708 for( i = 0; i < nimplubvars; i++)
    1709 {
    1710 if( ((SCIP_Longint)pospp) + posmm + pospm + posmp > maxhashes )
    1711 break;
    1712
    1713 colvalptr = SCIPmatrixGetColValPtr(matrix, implubvars[i]);
    1714 colidxptr = SCIPmatrixGetColIdxPtr(matrix, implubvars[i]);
    1715 maxlen = MIN(presoldata->maxconsiderednonzeros, SCIPmatrixGetColNNonzs(matrix, implubvars[i])); /*lint !e666*/
    1716 for( j = 0; j < maxlen; j++)
    1717 {
    1718 for( k = j + 1; k < maxlen; k++)
    1719 {
    1720 if( SCIPisPositive(scip, colvalptr[j]) )
    1721 {
    1722 if(SCIPisPositive(scip, colvalptr[k]) )
    1723 {
    1724 SCIP_CALL( addEntry(scip, &pospp, &listsizepp, &hashlistpp, &colidxlistpp,
    1725 hashIndexPair(colidxptr[j], colidxptr[k]), implubvars[i]) );
    1726 }
    1727 else
    1728 {
    1729 SCIP_CALL( addEntry(scip, &pospm, &listsizepm, &hashlistpm, &colidxlistpm,
    1730 hashIndexPair(colidxptr[j], colidxptr[k]), implubvars[i]) );
    1731 }
    1732 }
    1733 else
    1734 {
    1735 if(SCIPisPositive(scip, colvalptr[k]) )
    1736 {
    1737 SCIP_CALL( addEntry(scip, &posmp, &listsizemp, &hashlistmp, &colidxlistmp,
    1738 hashIndexPair(colidxptr[j], colidxptr[k]), implubvars[i]) );
    1739 }
    1740 else
    1741 {
    1742 SCIP_CALL( addEntry(scip, &posmm, &listsizemm, &hashlistmm, &colidxlistmm,
    1743 hashIndexPair(colidxptr[j], colidxptr[k]), implubvars[i]) );
    1744 }
    1745 }
    1746 }
    1747 }
    1748 }
    1749#ifdef SCIP_MORE_DEBUG
    1750 SCIPdebugMsg(scip, "hashlist sizes: pp %d, mm %d, pm %d, mp %d \n", pospp, posmm, pospm, posmp);
    1751#endif
    1752 SCIPsortIntInt(hashlistpp, colidxlistpp, pospp);
    1753 SCIPsortIntInt(hashlistmm, colidxlistmm, posmm);
    1754 SCIPsortIntInt(hashlistpm, colidxlistpm, pospm);
    1755 SCIPsortIntInt(hashlistmp, colidxlistmp, posmp);
    1756
    1757 SCIP_CALL( SCIPhashsetCreate(&pairhashset, SCIPblkmem(scip), 1) );
    1758
    1759 /* Process pp and mm lists */
    1760 if( pospp > 0 && posmm > 0 )
    1761 {
    1762 SCIP_Longint ncombines;
    1763 SCIP_Longint maxcombines;
    1764 SCIP_Bool finished;
    1765 SCIP_Bool success;
    1766 int combinefails;
    1767 int retrievefails;
    1768 COLPAIR colpair;
    1769
    1770 finished = FALSE;
    1771 block1start = 0;
    1772 block1end = 0;
    1773 block2start = 0;
    1774 block2end = 0;
    1775
    1776 maxcombines = presoldata->maxpairfac == -1 ? SCIP_LONGINT_MAX : (((SCIP_Longint)ncols) * presoldata->maxpairfac);
    1777
    1778 ncombines = 0;
    1779 combinefails = 0;
    1780 retrievefails = 0;
    1781 findNextBlock(hashlistpp, pospp, &block1start, &block1end);
    1782 findNextBlock(hashlistmm, posmm, &block2start, &block2end);
    1783#ifdef SCIP_MORE_DEBUG
    1784 SCIPdebugMsg(scip, "processing pp and mm\n");
    1785#endif
    1786
    1787 // same as in the rworowbnd presolver - both while loops to basically the same with one using pp and mm and the other pm and mp
    1788 // I would write an additional function and remove the code duplication
    1789 while( !finished )
    1790 {
    1791 if( hashlistpp[block1start] == hashlistmm[block2start] )
    1792 {
    1793 for( i = block1start; i < block1end; i++ )
    1794 {
    1795 for( j = block2start; j < block2end; j++ )
    1796 {
    1797 if( colidxlistpp[i] != colidxlistmm[j] )
    1798 {
    1799 colpair.col1idx = MIN(colidxlistpp[i], colidxlistmm[j]);
    1800 colpair.col2idx = MAX(colidxlistpp[i], colidxlistmm[j]);
    1801
    1802 if( !SCIPhashsetExists(pairhashset, encodeColPair(&colpair)) )
    1803 {
    1804 int* colpnt1 = SCIPmatrixGetColIdxPtr(matrix, colpair.col1idx);
    1805 SCIP_Real* valpnt1 = SCIPmatrixGetColValPtr(matrix, colpair.col1idx);
    1806 int* colpnt2 = SCIPmatrixGetColIdxPtr(matrix, colpair.col2idx);
    1807 SCIP_Real* valpnt2 = SCIPmatrixGetColValPtr(matrix, colpair.col2idx);
    1808 SCIP_Real obj1 = SCIPvarGetObj(SCIPmatrixGetVar(matrix, colpair.col1idx));
    1809 SCIP_Real obj2 = SCIPvarGetObj(SCIPmatrixGetVar(matrix, colpair.col2idx));
    1810 int collen1 = SCIPmatrixGetColNNonzs(matrix, colpair.col1idx);
    1811 int collen2 = SCIPmatrixGetColNNonzs(matrix, colpair.col2idx);
    1812
    1813 success = FALSE;
    1814
    1815 SCIP_CALL( combineCols(scip, colpnt1, colpnt2, valpnt1, valpnt2, obj1, obj2, collen1,
    1816 collen2, nrows, TRUE, TRUE, lbdual, ubdual, &success) );
    1817
    1818 if( success )
    1819 combinefails = 0;
    1820 else
    1821 combinefails++;
    1822
    1823 SCIP_CALL( SCIPhashsetInsert(pairhashset, SCIPblkmem(scip), encodeColPair(&colpair)) );
    1824 ncombines++;
    1825 if( ncombines >= maxcombines || combinefails >= presoldata->maxcombinefails )
    1826 finished = TRUE;
    1827#ifdef SCIP_MORE_DEBUG
    1828 SCIPdebugMsg(scip, "pm/mp: %d retrievefails before reset, %d combines\n", retrievefails, ncombines);
    1829#endif
    1830 retrievefails = 0;
    1831 }
    1832 else if( retrievefails < presoldata->maxretrievefails )
    1833 retrievefails++;
    1834 else
    1835 finished = TRUE;
    1836 }
    1837 if( finished )
    1838 break;
    1839 }
    1840 if( finished )
    1841 break;
    1842 }
    1843
    1844 if( block1end < pospp && block2end < posmm )
    1845 {
    1846 findNextBlock(hashlistpp, pospp, &block1start, &block1end);
    1847 findNextBlock(hashlistmm, posmm, &block2start, &block2end);
    1848 }
    1849 else
    1850 finished = TRUE;
    1851 }
    1852 else if( hashlistpp[block1start] < hashlistmm[block2start] && block1end < pospp )
    1853 findNextBlock(hashlistpp, pospp, &block1start, &block1end);
    1854 else if( hashlistpp[block1start] > hashlistmm[block2start] && block2end < posmm )
    1855 findNextBlock(hashlistmm, posmm, &block2start, &block2end);
    1856 else
    1857 finished = TRUE;
    1858 }
    1859 }
    1860
    1861 /* Process pm and mp lists */
    1862 if( pospm > 0 && posmp > 0 )
    1863 {
    1864 SCIP_Longint maxcombines;
    1865 SCIP_Longint ncombines;
    1866 SCIP_Bool finished;
    1867 SCIP_Bool success;
    1868 int combinefails;
    1869 int retrievefails;
    1870 COLPAIR colpair;
    1871
    1872 finished = FALSE;
    1873 block1start = 0;
    1874 block1end = 0;
    1875 block2start = 0;
    1876 block2end = 0;
    1877
    1878 maxcombines = presoldata->maxpairfac == -1 ? SCIP_LONGINT_MAX : (((SCIP_Longint)ncols) * presoldata->maxpairfac);
    1879
    1880 ncombines = 0;
    1881 combinefails = 0;
    1882 retrievefails = 0;
    1883 findNextBlock(hashlistpm, pospm, &block1start, &block1end);
    1884 findNextBlock(hashlistmp, posmp, &block2start, &block2end);
    1885#ifdef SCIP_MORE_DEBUG
    1886 SCIPdebugMsg(scip, "processing pm and mp\n");
    1887#endif
    1888
    1889 while( !finished )
    1890 {
    1891 if( hashlistpm[block1start] == hashlistmp[block2start] )
    1892 {
    1893 for( i = block1start; i < block1end; i++ )
    1894 {
    1895 for( j = block2start; j < block2end; j++ )
    1896 {
    1897 if( colidxlistpm[i] != colidxlistmp[j] )
    1898 {
    1899 colpair.col1idx = MIN(colidxlistpm[i], colidxlistmp[j]);
    1900 colpair.col2idx = MAX(colidxlistpm[i], colidxlistmp[j]);
    1901
    1902 if( !SCIPhashsetExists(pairhashset, encodeColPair(&colpair)) )
    1903 {
    1904 int* colpnt1 = SCIPmatrixGetColIdxPtr(matrix, colpair.col1idx);
    1905 SCIP_Real* valpnt1 = SCIPmatrixGetColValPtr(matrix, colpair.col1idx);
    1906 int* colpnt2 = SCIPmatrixGetColIdxPtr(matrix, colpair.col2idx);
    1907 SCIP_Real* valpnt2 = SCIPmatrixGetColValPtr(matrix, colpair.col2idx);
    1908 SCIP_Real obj1 = SCIPvarGetObj(SCIPmatrixGetVar(matrix, colpair.col1idx));
    1909 SCIP_Real obj2 = SCIPvarGetObj(SCIPmatrixGetVar(matrix, colpair.col2idx));
    1910 int collen1 = SCIPmatrixGetColNNonzs(matrix, colpair.col1idx);
    1911 int collen2 = SCIPmatrixGetColNNonzs(matrix, colpair.col2idx);
    1912
    1913 success = FALSE;
    1914
    1915 SCIP_CALL( combineCols(scip, colpnt1, colpnt2, valpnt1, valpnt2, obj1, obj2, collen1,
    1916 collen2, nrows, TRUE, TRUE, lbdual, ubdual, &success) );
    1917
    1918 if( success )
    1919 combinefails = 0;
    1920 else
    1921 combinefails++;
    1922
    1923 SCIP_CALL( SCIPhashsetInsert(pairhashset, SCIPblkmem(scip), encodeColPair(&colpair)) );
    1924 ncombines++;
    1925 if( ncombines >= maxcombines || combinefails >= presoldata->maxcombinefails )
    1926 finished = TRUE;
    1927
    1928 retrievefails = 0;
    1929 }
    1930 else if( retrievefails < presoldata->maxretrievefails )
    1931 retrievefails++;
    1932 else
    1933 finished = TRUE;
    1934 }
    1935 if( finished )
    1936 break;
    1937 }
    1938 if( finished )
    1939 break;
    1940 }
    1941
    1942 if( block1end < pospm && block2end < posmp )
    1943 {
    1944 findNextBlock(hashlistpm, pospm, &block1start, &block1end);
    1945 findNextBlock(hashlistmp, posmp, &block2start, &block2end);
    1946 }
    1947 else
    1948 finished = TRUE;
    1949 }
    1950 else if( hashlistpm[block1start] < hashlistmp[block2start] && block1end < pospm )
    1951 findNextBlock(hashlistpm, pospm, &block1start, &block1end);
    1952 else if( hashlistpm[block1start] > hashlistmp[block2start] && block2end < posmp )
    1953 findNextBlock(hashlistmp, posmp, &block2start, &block2end);
    1954 else
    1955 finished = TRUE;
    1956 }
    1957 }
    1958
    1959 SCIPhashsetFree(&pairhashset, SCIPblkmem(scip));
    1960 SCIPfreeBlockMemoryArray(scip, &colidxlistmp, listsizemp);
    1961 SCIPfreeBlockMemoryArray(scip, &colidxlistpm, listsizepm);
    1962 SCIPfreeBlockMemoryArray(scip, &colidxlistmm, listsizemm);
    1963 SCIPfreeBlockMemoryArray(scip, &colidxlistpp, listsizepp);
    1964 SCIPfreeBlockMemoryArray(scip, &hashlistmp, listsizemp);
    1965 SCIPfreeBlockMemoryArray(scip, &hashlistpm, listsizepm);
    1966 SCIPfreeBlockMemoryArray(scip, &hashlistmm, listsizemm);
    1967 SCIPfreeBlockMemoryArray(scip, &hashlistpp, listsizepp);
    1968
    1969#ifdef SCIP_MORE_DEBUG
    1970 SCIPdebugMsg(scip, "CombCols:\n");
    1971 for( i = 0; i < nrows; i++ )
    1972 {
    1973 assert(SCIPisLE(scip,lbdual[i],ubdual[i]));
    1974 SCIPdebugMsg(scip, "y%d=[%g,%g]\n",i,lbdual[i],ubdual[i]);
    1975 }
    1976 SCIPdebugMsg(scip,"\n");
    1977#endif
    1978 }
    1979
    1980 SCIP_CALL( SCIPallocBufferArray(scip, &mincolact, ncols) );
    1981 SCIP_CALL( SCIPallocBufferArray(scip, &mincolactinf, ncols) );
    1982
    1983 /* apply dual bound strengthening */
    1984 loops = 0;
    1985 boundchanges = 1;
    1986 while( 0 < boundchanges && loops < presoldata->maxdualbndloops )
    1987 {
    1988 loops++;
    1989 boundchanges = 0;
    1990
    1991 for( i = 0; i < nimplubvars; i++ )
    1992 {
    1993 assert(!SCIPvarIsIntegral(SCIPmatrixGetVar(matrix, implubvars[i]))
    1994 || SCIPvarIsImpliedIntegral(SCIPmatrixGetVar(matrix, implubvars[i])));
    1995 calcMinColActivity(scip, matrix, implubvars[i], lbdual, ubdual, mincolact, mincolactinf);
    1996 }
    1997
    1998 for( i = 0; i < nimplubvars; i++ )
    1999 {
    2000 SCIP_Real objval;
    2001 SCIP_Bool ubinfchange;
    2002 SCIP_Bool lbinfchange;
    2003 int col;
    2004
    2005 col = implubvars[i];
    2006 var = SCIPmatrixGetVar(matrix, col);
    2007
    2008 objval = SCIPvarGetObj(var);
    2009 colpnt = SCIPmatrixGetColIdxPtr(matrix, col);
    2010 colend = colpnt + SCIPmatrixGetColNNonzs(matrix, col);
    2011 valpnt = SCIPmatrixGetColValPtr(matrix, col);
    2012
    2013 for( ; colpnt < colend; colpnt++, valpnt++ )
    2014 {
    2015 int row;
    2016 SCIP_Real val;
    2017 SCIP_Real mincolresact;
    2018
    2019 row = *colpnt;
    2020 val = *valpnt;
    2021
    2022 calcMinColActResidual(scip, matrix, col, row, val, lbdual, ubdual,
    2023 mincolact, mincolactinf, &mincolresact);
    2024
    2025 updateDualBounds(scip, matrix, objval, val, row, mincolresact,
    2026 lbdual, ubdual, &boundchanges, &ubinfchange, &lbinfchange);
    2027
    2028 if( ubinfchange || lbinfchange )
    2029 infinityCountUpdate(scip, matrix, row, lbdual, ubdual, isubimplied,
    2030 mincolact, mincolactinf, ubinfchange, lbinfchange);
    2031 }
    2032 }
    2033 }
    2034
    2035#ifdef SCIP_MORE_DEBUG
    2036 SCIPdebugMsg(scip, "BndStr:\n");
    2037 for( i = 0; i < nrows; i++ )
    2038 {
    2039 assert(SCIPisLE(scip,lbdual[i],ubdual[i]));
    2040 SCIPdebugMsg(scip, "y%d=[%g,%g]\n",i,lbdual[i],ubdual[i]);
    2041 }
    2042 SCIPdebugMsg(scip,"\n");
    2043#endif
    2044
    2045 SCIP_CALL( SCIPallocBufferArray(scip, &maxcolact, ncols) );
    2046 SCIP_CALL( SCIPallocBufferArray(scip, &maxcolactinf, ncols) );
    2047
    2048 /* calculate final minimal and maximal column activities */
    2049 for( i = 0; i < ncols; i++ )
    2050 {
    2051 calcMinColActivity(scip, matrix, i, lbdual, ubdual, mincolact, mincolactinf);
    2052 calcMaxColActivity(scip, matrix, i, lbdual, ubdual, maxcolact, maxcolactinf);
    2053 }
    2054
    2055 for( i = 0; i < ncols; i++ )
    2056 {
    2057 SCIP_Real objval;
    2058
    2059 var = SCIPmatrixGetVar(matrix, i);
    2060
    2061 /* do not fix variables if the locks do not match */
    2062 if( SCIPmatrixUplockConflict(matrix, i) || SCIPmatrixDownlockConflict(matrix, i) )
    2063 continue;
    2064
    2065 objval = SCIPvarGetObj(var);
    2066
    2067 /* c_j - sup(y^T A_{.j}) > 0 => fix x_j to its lower bound */
    2068 if( SCIPisGT(scip, objval, maxcolact[i]) && varstofix[i] == NOFIX )
    2069 {
    2071 {
    2072 varstofix[i] = FIXATLB;
    2073 (*npossiblefixings)++;
    2074 }
    2075 }
    2076
    2077 /* c_j - inf(y^T A_{.j}) < 0 => fix x_j to its upper bound */
    2078 if( SCIPisLT(scip, objval, mincolact[i]) && varstofix[i] == NOFIX )
    2079 {
    2081 {
    2082 varstofix[i] = FIXATUB;
    2083 (*npossiblefixings)++;
    2084 }
    2085 }
    2086 }
    2087
    2088 for( i = 0; i < nrows; i++ )
    2089 {
    2090 /* implied equality: y_i > 0 => A_{i.}x - b_i = 0 */
    2091 if( SCIPmatrixIsRowRhsInfinity(matrix, i) )
    2092 {
    2093 if( SCIPisGT(scip, lbdual[i], 0.0) && (sidestochange[i] == NOCHANGE) )
    2094 {
    2095 /* change >= inequality to equality */
    2096 sidestochange[i] = RHSTOLHS;
    2097 (*npossiblesidechanges)++;
    2098 }
    2099 }
    2100 else
    2101 {
    2102 if( !SCIPmatrixIsRowRhsInfinity(matrix, i) &&
    2103 !SCIPisEQ(scip,SCIPmatrixGetRowLhs(matrix, i),SCIPmatrixGetRowRhs(matrix, i)) )
    2104 {
    2105 /* for ranged rows we have to decide which side (lhs or rhs) determines the equality */
    2106 if( SCIPisGT(scip, lbdual[i], 0.0) && sidestochange[i]==NOCHANGE )
    2107 {
    2108 sidestochange[i] = RHSTOLHS;
    2109 (*npossiblesidechanges)++;
    2110 }
    2111
    2112 if( SCIPisLT(scip, ubdual[i], 0.0) && sidestochange[i]==NOCHANGE)
    2113 {
    2114 sidestochange[i] = LHSTORHS;
    2115 (*npossiblesidechanges)++;
    2116 }
    2117 }
    2118 }
    2119 }
    2120
    2121 SCIPfreeBufferArray(scip, &maxcolactinf);
    2122 SCIPfreeBufferArray(scip, &maxcolact);
    2123 SCIPfreeBufferArray(scip, &mincolactinf);
    2124 SCIPfreeBufferArray(scip, &mincolact);
    2125
    2126 SCIPfreeBufferArray(scip, &ubdual);
    2127 SCIPfreeBufferArray(scip, &lbdual);
    2128 SCIPfreeBufferArray(scip, &implubvars);
    2129 SCIPfreeBufferArray(scip, &islbimplied);
    2130 SCIPfreeBufferArray(scip, &isubimplied);
    2131 SCIPfreeBufferArray(scip, &tmpubs);
    2132 SCIPfreeBufferArray(scip, &tmplbs);
    2133
    2134 return SCIP_OKAY;
    2135}
    2136
    2137/*
    2138 * Callback methods of presolver
    2139 */
    2140
    2141/** copy method for constraint handler plugins (called when SCIP copies plugins) */
    2142static
    2143SCIP_DECL_PRESOLCOPY(presolCopyDualinfer)
    2144{ /*lint --e{715}*/
    2145 assert(scip != NULL);
    2146 assert(presol != NULL);
    2147 assert(strcmp(SCIPpresolGetName(presol), PRESOL_NAME) == 0);
    2148
    2149 /* call inclusion method of presolver */
    2151
    2152 return SCIP_OKAY;
    2153}
    2154
    2155/** destructor of presolver to free user data (called when SCIP is exiting) */
    2156static
    2157SCIP_DECL_PRESOLFREE(presolFreeDualinfer)
    2158{ /*lint --e{715}*/
    2159 SCIP_PRESOLDATA* presoldata;
    2160
    2161 /* free presolver data */
    2162 presoldata = SCIPpresolGetData(presol);
    2163 assert(presoldata != NULL);
    2164
    2165 SCIPfreeBlockMemory(scip, &presoldata);
    2166 SCIPpresolSetData(presol, NULL);
    2167
    2168 return SCIP_OKAY;
    2169}
    2170
    2171/** execution method of presolver */
    2172static
    2173SCIP_DECL_PRESOLEXEC(presolExecDualinfer)
    2174{ /*lint --e{715}*/
    2175 SCIP_MATRIX* matrix;
    2176 SCIP_Bool initialized;
    2177 SCIP_Bool complete;
    2178 SCIP_Bool infeasible;
    2179 SCIP_PRESOLDATA* presoldata;
    2180 FIXINGDIRECTION* varstofix;
    2181 int npossiblefixings;
    2182 int nconvarsfixed;
    2183 int nintvarsfixed;
    2184 int nbinvarsfixed;
    2185 SIDECHANGE* sidestochange;
    2186 int npossiblesidechanges;
    2187 int nsideschanged;
    2188 int i;
    2189 int nrows;
    2190 int ncols;
    2191 SCIP_VAR* var;
    2192
    2193 assert(result != NULL);
    2194 *result = SCIP_DIDNOTRUN;
    2195
    2197 return SCIP_OKAY;
    2198
    2199 /* the reductions made in this presolver apply to all optimal solutions because of complementary slackness */
    2201 return SCIP_OKAY;
    2202
    2203 *result = SCIP_DIDNOTFIND;
    2204
    2206 {
    2207 SCIPdebugMsg(scip, "DualInfer not executed because condition of existing dual solution is not fulfilled.\n");
    2208 return SCIP_OKAY;
    2209 }
    2210
    2211 presoldata = SCIPpresolGetData(presol);
    2212 assert(presoldata != NULL);
    2213
    2214 matrix = NULL;
    2215 SCIP_CALL( SCIPmatrixCreate(scip, &matrix, TRUE, &initialized, &complete, &infeasible,
    2216 naddconss, ndelconss, nchgcoefs, nchgbds, nfixedvars) );
    2217
    2218 /* if infeasibility was detected during matrix creation, return here */
    2219 if( infeasible )
    2220 {
    2221 if( initialized )
    2222 SCIPmatrixFree(scip, &matrix);
    2223
    2224 *result = SCIP_CUTOFF;
    2225 return SCIP_OKAY;
    2226 }
    2227
    2228 if( !initialized )
    2229 return SCIP_OKAY;
    2230
    2231 npossiblefixings = 0;
    2232 nconvarsfixed = 0;
    2233 nintvarsfixed = 0;
    2234 nbinvarsfixed = 0;
    2235 npossiblesidechanges = 0;
    2236 nsideschanged = 0;
    2237
    2238 nrows = SCIPmatrixGetNRows(matrix);
    2239 ncols = SCIPmatrixGetNColumns(matrix);
    2240
    2241 SCIP_CALL( SCIPallocBufferArray(scip, &varstofix, ncols) );
    2242 SCIP_CALL( SCIPallocBufferArray(scip, &sidestochange, nrows) );
    2243
    2244 BMSclearMemoryArray(varstofix, ncols);
    2245 BMSclearMemoryArray(sidestochange, nrows);
    2246
    2247 SCIP_CALL( dualBoundStrengthening(scip, matrix, presoldata,
    2248 varstofix, &npossiblefixings, sidestochange, &npossiblesidechanges) );
    2249
    2250 if( npossiblefixings > 0 )
    2251 {
    2252 for( i = ncols - 1; i >= 0; --i )
    2253 {
    2254 SCIP_Bool fixed;
    2255
    2256 var = SCIPmatrixGetVar(matrix, i);
    2257
    2258 /* there should be no fixings for variables with inconsistent locks */
    2259 assert(varstofix[i] == NOFIX || (!SCIPmatrixUplockConflict(matrix, i) && !SCIPmatrixDownlockConflict(matrix, i)));
    2260
    2261 fixed = FALSE;
    2262
    2263 if( varstofix[i] == FIXATLB )
    2264 {
    2265 SCIP_Real lb;
    2266 lb = SCIPvarGetLbLocal(var);
    2267
    2268 /* fix at lower bound */
    2269 SCIP_CALL( SCIPfixVar(scip, var, lb, &infeasible, &fixed) );
    2270 if( infeasible )
    2271 {
    2272 SCIPdebugMsg(scip, " -> infeasible fixing\n");
    2273 *result = SCIP_CUTOFF;
    2274 break;
    2275 }
    2276 assert(fixed);
    2277 (*nfixedvars)++;
    2278 *result = SCIP_SUCCESS;
    2279 }
    2280 else if( varstofix[i] == FIXATUB )
    2281 {
    2282 SCIP_Real ub;
    2283 ub = SCIPvarGetUbLocal(var);
    2284
    2285 /* fix at upper bound */
    2286 SCIP_CALL( SCIPfixVar(scip, var, ub, &infeasible, &fixed) );
    2287 if( infeasible )
    2288 {
    2289 SCIPdebugMsg(scip, " -> infeasible fixing\n");
    2290 *result = SCIP_CUTOFF;
    2291 break;
    2292 }
    2293 assert(fixed);
    2294 (*nfixedvars)++;
    2295 *result = SCIP_SUCCESS;
    2296 }
    2297
    2298 /* keep a small statistic which types of variables are fixed */
    2299 if( fixed )
    2300 {
    2301 if( !SCIPvarIsNonimpliedIntegral(var) )
    2302 nconvarsfixed++;
    2303 else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
    2304 nbinvarsfixed++;
    2305 else
    2306 nintvarsfixed++;
    2307 }
    2308 }
    2309 }
    2310
    2311 if( npossiblesidechanges > 0 )
    2312 {
    2313 for( i = 0; i < nrows; i++ )
    2314 {
    2315 SCIP_CONS* cons;
    2316 SCIP_CONSHDLR* conshdlr;
    2317 const char* conshdlrname;
    2318
    2319 if( sidestochange[i] == NOCHANGE )
    2320 continue;
    2321
    2322 if( presoldata->maxrowsupport < SCIPmatrixGetRowNNonzs(matrix, i) )
    2323 continue;
    2324
    2325 cons = SCIPmatrixGetCons(matrix,i);
    2326 conshdlr = SCIPconsGetHdlr(cons);
    2327 conshdlrname = SCIPconshdlrGetName(conshdlr);
    2328
    2329 if( strcmp(conshdlrname, "linear") == 0 )
    2330 {
    2331 SCIP_Real lhs;
    2332 SCIP_Real rhs;
    2333 SCIP_Real matrixlhs;
    2334 SCIP_Real matrixrhs;
    2335
    2336 lhs = SCIPgetLhsLinear(scip, cons);
    2337 rhs = SCIPgetRhsLinear(scip, cons);
    2338 matrixlhs = SCIPmatrixGetRowLhs(matrix, i);
    2339 matrixrhs = SCIPmatrixGetRowRhs(matrix, i);
    2340
    2341 assert(!SCIPisEQ(scip, matrixlhs, matrixrhs));
    2342
    2343 /* when creating the matrix, constraints are multiplied if necessary by (-1)
    2344 * to ensure that the following representation is obtained:
    2345 * infty >= a x >= b
    2346 * or
    2347 * c >= ax >= b (ranged rows)
    2348 */
    2349
    2350 /* for ranged constraints we have to distinguish between both sides */
    2351 if( sidestochange[i] == RHSTOLHS )
    2352 {
    2353 if( SCIPisEQ(scip, matrixlhs, lhs) )
    2354 {
    2355 /* change rhs to lhs */
    2356 SCIP_CALL( SCIPchgRhsLinear(scip, cons, matrixlhs) );
    2357 }
    2358 else
    2359 {
    2360 /* consider multiplication by (-1) in the matrix */
    2361 SCIP_CALL( SCIPchgLhsLinear(scip, cons, -matrixlhs) );
    2362 }
    2363
    2364 nsideschanged++;
    2365 (*nchgsides)++;
    2366 }
    2367 else if( sidestochange[i] == LHSTORHS )
    2368 {
    2369 if( SCIPisEQ(scip, matrixrhs, rhs) )
    2370 {
    2371 /* change lhs to rhs */
    2372 SCIP_CALL( SCIPchgLhsLinear(scip, cons, matrixrhs) );
    2373 }
    2374 else
    2375 {
    2376 /* consider multiplication by (-1) in the matrix */
    2377 SCIP_CALL( SCIPchgRhsLinear(scip, cons, -matrixrhs) );
    2378 }
    2379
    2380 nsideschanged++;
    2381 (*nchgsides)++;
    2382 }
    2383 }
    2384 }
    2385 }
    2386
    2387 SCIPfreeBufferArray(scip, &sidestochange);
    2388 SCIPfreeBufferArray(scip, &varstofix);
    2389
    2390 if( (nconvarsfixed + nintvarsfixed + nbinvarsfixed) > 0 || npossiblesidechanges > 0 )
    2391 {
    2392 SCIPdebugMsg(scip, "### fixed vars [cont: %d, int: %d, bin: %d], changed sides [%d]\n",
    2393 nconvarsfixed, nintvarsfixed, nbinvarsfixed, nsideschanged);
    2394 }
    2395
    2396 SCIPmatrixFree(scip, &matrix);
    2397
    2398 return SCIP_OKAY;
    2399}
    2400
    2401
    2402/*
    2403 * presolver specific interface methods
    2404 */
    2405
    2406/** creates the dual inference presolver and includes it in SCIP */
    2408 SCIP* scip /**< SCIP data structure */
    2409 )
    2410{
    2411 SCIP_PRESOL* presol;
    2412 SCIP_PRESOLDATA* presoldata;
    2413
    2414 /* create presolver data */
    2415 SCIP_CALL( SCIPallocBlockMemory(scip, &presoldata) );
    2416
    2417 /* include presolver */
    2419 PRESOL_TIMING, presolExecDualinfer, presoldata) );
    2420 SCIP_CALL( SCIPsetPresolCopy(scip, presol, presolCopyDualinfer) );
    2421 SCIP_CALL( SCIPsetPresolFree(scip, presol, presolFreeDualinfer) );
    2422
    2424 "presolving/dualinfer/twocolcombine",
    2425 "use convex combination of columns for determining dual bounds",
    2426 &presoldata->usetwocolcombine, FALSE, DEFAULT_TWOCOLUMN_COMBINE, NULL, NULL) );
    2427
    2429 "presolving/dualinfer/maxdualbndloops",
    2430 "maximal number of dual bound strengthening loops",
    2431 &presoldata->maxdualbndloops, FALSE, DEFAULT_MAXLOOPS_DUALBNDSTR, -1, INT_MAX, NULL, NULL) );
    2432
    2434 "presolving/dualinfer/maxconsiderednonzeros",
    2435 "maximal number of considered non-zeros within one column (-1: no limit)",
    2436 &presoldata->maxconsiderednonzeros, TRUE, DEFAULT_MAXCONSIDEREDNONZEROS, -1, INT_MAX, NULL, NULL) );
    2437
    2439 "presolving/dualinfer/maxretrievefails",
    2440 "maximal number of consecutive useless hashtable retrieves",
    2441 &presoldata->maxretrievefails, TRUE, DEFAULT_MAXRETRIEVEFAILS, -1, INT_MAX, NULL, NULL) );
    2442
    2444 "presolving/dualinfer/maxcombinefails",
    2445 "maximal number of consecutive useless column combines",
    2446 &presoldata->maxcombinefails, TRUE, DEFAULT_MAXCOMBINEFAILS, -1, INT_MAX, NULL, NULL) );
    2447
    2449 "presolving/dualinfer/maxhashfac",
    2450 "Maximum number of hashlist entries as multiple of number of columns in the problem (-1: no limit)",
    2451 &presoldata->maxhashfac, TRUE, DEFAULT_MAXHASHFAC, -1, INT_MAX, NULL, NULL) );
    2452
    2454 "presolving/dualinfer/maxpairfac",
    2455 "Maximum number of processed column pairs as multiple of the number of columns in the problem (-1: no limit)",
    2456 &presoldata->maxpairfac, TRUE, DEFAULT_MAXPAIRFAC, -1, INT_MAX, NULL, NULL) );
    2457
    2459 "presolving/dualinfer/maxrowsupport",
    2460 "Maximum number of row's non-zeros for changing inequality to equality",
    2461 &presoldata->maxrowsupport, FALSE, DEFAULT_MAXROWSUPPORT, 2, INT_MAX, NULL, NULL) );
    2462
    2463 return SCIP_OKAY;
    2464}
    SCIP_VAR * a
    Definition: circlepacking.c:66
    SCIP_VAR ** b
    Definition: circlepacking.c:65
    Constraint handler for linear constraints in their most general form, .
    static SCIP_RETCODE determineBestBounds(SCIP *scip, SCIP_VAR *var, SCIP_SOL *sol, MIR_DATA *data, SCIP_Real boundswitch, int usevbds, SCIP_Bool allowlocal, SCIP_Bool fixintegralrhs, SCIP_Bool ignoresol, int *boundsfortrans, SCIP_BOUNDTYPE *boundtypesfortrans, SCIP_Real *bestlb, SCIP_Real *bestub, int *bestlbtype, int *bestubtype, SCIP_BOUNDTYPE *selectedbound, SCIP_Bool *freevariable)
    Definition: cuts.c:4803
    #define NULL
    Definition: def.h:248
    #define SCIP_MAXSTRLEN
    Definition: def.h:269
    #define SCIP_Longint
    Definition: def.h:141
    #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_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
    SCIP_RETCODE SCIPchgRhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
    SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
    SCIP_RETCODE SCIPcreateConsBasicLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
    SCIP_RETCODE SCIPchgLhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
    SCIP_RETCODE SCIPfree(SCIP **scip)
    Definition: scip_general.c:402
    SCIP_RETCODE SCIPcreate(SCIP **scip)
    Definition: scip_general.c:370
    SCIP_STATUS SCIPgetStatus(SCIP *scip)
    Definition: scip_general.c:562
    SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_prob.c:1907
    int SCIPgetNImplVars(SCIP *scip)
    Definition: scip_prob.c:2387
    int SCIPgetNContVars(SCIP *scip)
    Definition: scip_prob.c:2569
    SCIP_RETCODE SCIPwriteOrigProblem(SCIP *scip, const char *filename, const char *extension, SCIP_Bool genericnames)
    Definition: scip_prob.c:742
    SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:3274
    SCIP_RETCODE SCIPsetObjsense(SCIP *scip, SCIP_OBJSENSE objsense)
    Definition: scip_prob.c:1417
    SCIP_RETCODE SCIPcreateProbBasic(SCIP *scip, const char *name)
    Definition: scip_prob.c:182
    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
    void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
    Definition: scip_message.c:120
    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 SCIPsetIntParam(SCIP *scip, const char *name, int value)
    Definition: scip_param.c:487
    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 SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
    Definition: scip_param.c:429
    SCIP_RETCODE SCIPincludePresolDualinfer(SCIP *scip)
    const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4316
    SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
    Definition: cons.c:8409
    SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    SCIP_Real SCIPgetPseudoObjval(SCIP *scip)
    Definition: scip_lp.c:339
    #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 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_RETCODE SCIPcheckSolOrig(SCIP *scip, SCIP_SOL *sol, SCIP_Bool *feasible, SCIP_Bool printreason, SCIP_Bool completely)
    Definition: scip_sol.c:4380
    SCIP_SOL * SCIPgetBestSol(SCIP *scip)
    Definition: scip_sol.c:2981
    SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1892
    SCIP_RETCODE SCIPfreeTransform(SCIP *scip)
    Definition: scip_solve.c:3462
    SCIP_RETCODE SCIPsolve(SCIP *scip)
    Definition: scip_solve.c:2635
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    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_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_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
    Definition: var.c:23498
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24268
    SCIP_Bool SCIPvarIsNonimpliedIntegral(SCIP_VAR *var)
    Definition: var.c:23506
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23900
    SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
    Definition: var.c:23453
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24142
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
    Definition: scip_var.c:1887
    SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
    Definition: var.c:23490
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24234
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24120
    SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
    Definition: scip_var.c:10318
    SCIP_RETCODE SCIPcreateVarBasic(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype)
    Definition: scip_var.c:184
    SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
    Definition: scip_var.c:5372
    SCIP_Bool SCIPallowWeakDualReds(SCIP *scip)
    Definition: scip_var.c:10998
    void SCIPsortIntInt(int *intarray1, int *intarray2, int len)
    void SCIPsortIntReal(int *intarray, SCIP_Real *realarray, int len)
    void SCIPsortRealInt(SCIP_Real *realarray, int *intarray, int len)
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    static SCIP_RETCODE solveLP(SCIP *scip, SCIP_DIVESET *diveset, SCIP_Longint maxnlpiterations, SCIP_DIVECONTEXT divecontext, SCIP_Bool *lperror, SCIP_Bool *cutoff)
    Definition: heuristics.c:49
    SCIP_Bool SCIPmatrixUplockConflict(SCIP_MATRIX *matrix, int col)
    Definition: matrix.c:2201
    int * SCIPmatrixGetColIdxPtr(SCIP_MATRIX *matrix, int col)
    Definition: matrix.c:1873
    int SCIPmatrixGetRowNNonzs(SCIP_MATRIX *matrix, int row)
    Definition: matrix.c:2013
    int SCIPmatrixGetColNNonzs(SCIP_MATRIX *matrix, int col)
    Definition: matrix.c:1885
    SCIP_Bool SCIPmatrixIsRowRhsInfinity(SCIP_MATRIX *matrix, int row)
    Definition: matrix.c:2095
    SCIP_Real SCIPmatrixGetRowLhs(SCIP_MATRIX *matrix, int row)
    Definition: matrix.c:2047
    SCIP_Real * SCIPmatrixGetRowValPtr(SCIP_MATRIX *matrix, int row)
    Definition: matrix.c:1977
    SCIP_Bool SCIPmatrixDownlockConflict(SCIP_MATRIX *matrix, int col)
    Definition: matrix.c:2213
    SCIP_Real SCIPmatrixGetRowRhs(SCIP_MATRIX *matrix, int row)
    Definition: matrix.c:2059
    SCIP_Real * SCIPmatrixGetColValPtr(SCIP_MATRIX *matrix, int col)
    Definition: matrix.c:1861
    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
    SCIP_CONS * SCIPmatrixGetCons(SCIP_MATRIX *matrix, int row)
    Definition: matrix.c:2189
    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
    memory allocation routines
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    Fixingdirection
    enum Fixingdirection FIXINGDIRECTION
    #define DEFAULT_TWOCOLUMN_COMBINE
    static void calcMaxColActivity(SCIP *scip, SCIP_MATRIX *matrix, int col, SCIP_Real *lbdual, SCIP_Real *ubdual, SCIP_Real *maxcolact, int *maxcolactinf)
    SideChange
    @ RHSTOLHS
    @ LHSTORHS
    @ NOCHANGE
    static void * encodeColPair(COLPAIR *colpair)
    static void calcMinColActResidual(SCIP *scip, SCIP_MATRIX *matrix, int col, int row, SCIP_Real val, SCIP_Real *lbdual, SCIP_Real *ubdual, const SCIP_Real *mincolact, const int *mincolactinf, SCIP_Real *mincolresact)
    #define DEFAULT_MAXCONSIDEREDNONZEROS
    static void getImpliedBounds(SCIP *scip, SCIP_MATRIX *matrix, int col, SCIP_Real *lbs, SCIP_Real *ubs, SCIP_Bool *ubimplied, SCIP_Bool *lbimplied)
    static void calcMinColActivity(SCIP *scip, SCIP_MATRIX *matrix, int col, SCIP_Real *lbdual, SCIP_Real *ubdual, SCIP_Real *mincolact, int *mincolactinf)
    #define PRESOL_NAME
    @ FIXATUB
    @ FIXATLB
    @ NOFIX
    static int hashIndexPair(int idx1, int idx2)
    static SCIP_DECL_PRESOLFREE(presolFreeDualinfer)
    enum Fixingdirection FIXINGDIRECTION
    @ DN
    @ POS
    @ UP
    @ NEG
    static void getVarBoundsOfRow(SCIP *scip, SCIP_MATRIX *matrix, int col, int row, SCIP_Real val, SCIP_Real *lbs, SCIP_Real *ubs, SCIP_Real *rowub, SCIP_Bool *ubfound, SCIP_Real *rowlb, SCIP_Bool *lbfound)
    static SCIP_RETCODE combineCols(SCIP *scip, int *row1idxptr, int *row2idxptr, SCIP_Real *row1valptr, SCIP_Real *row2valptr, SCIP_Real b1, SCIP_Real b2, int row1len, int row2len, int ncols, SCIP_Bool swaprow1, SCIP_Bool swaprow2, SCIP_Real *lbs, SCIP_Real *ubs, SCIP_Bool *success)
    static SCIP_Real getMinColActWithoutRow(SCIP *scip, SCIP_MATRIX *matrix, int col, int withoutrow, SCIP_Real *lbdual, SCIP_Real *ubdual)
    #define PRESOL_PRIORITY
    static void updateDualBounds(SCIP *scip, SCIP_MATRIX *matrix, SCIP_Real objval, SCIP_Real val, int row, SCIP_Real mincolresact, SCIP_Real *lbdual, SCIP_Real *ubdual, int *boundchanges, SCIP_Bool *ubinfchange, SCIP_Bool *lbinfchange)
    static void findNextBlock(const int *list, int len, int *start, int *end)
    static SCIP_RETCODE dualBoundStrengthening(SCIP *scip, SCIP_MATRIX *matrix, SCIP_PRESOLDATA *presoldata, FIXINGDIRECTION *varstofix, int *npossiblefixings, SIDECHANGE *sidestochange, int *npossiblesidechanges)
    static SCIP_DECL_PRESOLEXEC(presolExecDualinfer)
    static SCIP_DECL_PRESOLCOPY(presolCopyDualinfer)
    #define DEFAULT_MAXHASHFAC
    enum SideChange SIDECHANGE
    static void getMinMaxActivityResiduals(SCIP *scip, SCIP_MATRIX *matrix, int withoutcol, int row, SCIP_Real *lbs, SCIP_Real *ubs, SCIP_Real *minresactivity, SCIP_Real *maxresactivity, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
    #define DEFAULT_MAXCOMBINEFAILS
    #define DEFAULT_MAXRETRIEVEFAILS
    #define DEFAULT_MAXLOOPS_DUALBNDSTR
    #define DEFAULT_MAXPAIRFAC
    #define PRESOL_MAXROUNDS
    #define PRESOL_TIMING
    static void infinityCountUpdate(SCIP *scip, SCIP_MATRIX *matrix, int row, SCIP_Real *lbdual, SCIP_Real *ubdual, const SCIP_Bool *isubimplied, SCIP_Real *mincolact, int *mincolactinf, SCIP_Bool ubinfchange, SCIP_Bool lbinfchange)
    #define DEFAULT_MAXROWSUPPORT
    #define PRESOL_DESC
    static SCIP_RETCODE addEntry(SCIP *scip, int *pos, int *listsize, int **hashlist, int **colidxlist, int hash, int colidx)
    dual inference presolver
    public methods for managing constraints
    public methods for matrix
    public methods for message output
    public methods for presolvers
    public methods for problem variables
    general public methods
    public methods for memory management
    public methods for message handling
    public methods for numerical tolerances
    public methods for presolving plugins
    public methods for global and local (sub)problems
    public methods for the probing mode
    public methods for SCIP variables
    SCIP_RETCODE SCIPincludeDefaultPlugins(SCIP *scip)
    default SCIP plugins
    struct SCIP_PresolData SCIP_PRESOLDATA
    Definition: type_presol.h:51
    @ SCIP_OBJSENSE_MAXIMIZE
    Definition: type_prob.h:47
    @ SCIP_OBJSENSE_MINIMIZE
    Definition: type_prob.h:48
    @ 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
    @ SCIP_STATUS_OPTIMAL
    Definition: type_stat.h:43
    @ SCIP_VARTYPE_CONTINUOUS
    Definition: type_var.h:71
    @ SCIP_VARTYPE_BINARY
    Definition: type_var.h:64