Scippy

    SCIP

    Solving Constraint Integer Programs

    presol_dualsparsify.c
    Go to the documentation of this file.
    1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    2/* */
    3/* This file is part of the program and library */
    4/* SCIP --- Solving Constraint Integer Programs */
    5/* */
    6/* Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file presol_dualsparsify.c
    26 * @brief cancel nonzeros of the constraint matrix based on the columns
    27 * @author Dieter Weninger
    28 * @author Leona Gottwald
    29 * @author Ambros Gleixner
    30 * @author Weikun Chen
    31 *
    32 * This presolver attempts to cancel non-zero entries of the constraint
    33 * matrix by adding scaled columns to other columns.
    34 *
    35 * In more detail, for two columns A_{j.} and A_{k.}, suppose for a given value s, we have
    36 *
    37 * | A_{j.} | - | A_{j.} - s*A_{k.} | > eta,
    38 *
    39 * where eta is an nonnegative integer. Then we introduce a new variable y := s*x_j + x_k
    40 * and aggregate the variable x_k = y - s*x_j. After aggregation, the column of the variable
    41 * x_j is A_{j.} + s*A_{j.} which is sparser than A_{j.}. In the case that x_k is nonimplied
    42 * free variable, we need to add a new constraint l_k <= y - weight*x_j <= u_k into the problem
    43 * to keep the bounds constraints of variable x_k.
    44 *
    45 * Further information can be found in
    46 * Chen et al. "Two-row and two-column mixed-integer presolve using hasing-based pairing methods".
    47 *
    48 * @todo add infrastructure to SCIP for handling aggregated binary variables
    49 */
    50
    51/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    52
    54#include "scip/cons_linear.h"
    55#include "scip/debug.h"
    57#include "scip/pub_cons.h"
    58#include "scip/pub_matrix.h"
    59#include "scip/pub_message.h"
    60#include "scip/pub_misc.h"
    61#include "scip/pub_misc_sort.h"
    62#include "scip/pub_presol.h"
    63#include "scip/pub_var.h"
    64#include "scip/scip_cons.h"
    65#include "scip/scip_general.h"
    66#include "scip/scip_mem.h"
    67#include "scip/scip_message.h"
    68#include "scip/scip_nlp.h"
    69#include "scip/scip_numerics.h"
    70#include "scip/scip_param.h"
    71#include "scip/scip_presol.h"
    72#include "scip/scip_pricer.h"
    73#include "scip/scip_prob.h"
    74#include "scip/scip_probing.h"
    76#include "scip/scip_timing.h"
    77#include "scip/scip_var.h"
    78#include <string.h>
    79
    80#define PRESOL_NAME "dualsparsify"
    81#define PRESOL_DESC "eliminate non-zero coefficients"
    82
    83#define PRESOL_PRIORITY -240000 /**< priority of the presolver (>= 0: before, < 0: after constraint handlers) */
    84#define PRESOL_MAXROUNDS -1 /**< maximal number of presolving rounds the presolver participates in (-1: no limit) */
    85#define PRESOL_TIMING SCIP_PRESOLTIMING_EXHAUSTIVE /* timing of the presolver (fast, medium, or exhaustive) */
    86
    87#define DEFAULT_ENABLECOPY TRUE /**< should dualsparsify presolver be copied to sub-SCIPs? */
    88#define DEFAULT_PRESERVEINTCOEFS FALSE /**< should we forbid cancellations that destroy integer coefficients? */
    89#define DEFAULT_PRESERVEGOODLOCKS FALSE /**< should we preserve good locked properties of variables (at most one lock in one direction)? */
    90#define DEFAULT_MAX_CONT_FILLIN 1 /**< default value for the maximal fillin for continuous variables */
    91#define DEFAULT_MAX_BIN_FILLIN 1 /**< default value for the maximal fillin for binary variables */
    92#define DEFAULT_MAX_INT_FILLIN 1 /**< default value for the maximal fillin for integer variables (including binary) */
    93#define DEFAULT_MAXCONSIDEREDNONZEROS 70 /**< maximal number of considered nonzeros within one column (-1: no limit) */
    94#define DEFAULT_MINELIMINATEDNONZEROS 100 /**< minimal eleminated nonzeros within one column if we need to add a constraint to the problem */
    95#define DEFAULT_MAXRETRIEVEFAC 100.0 /**< limit on the number of useless vs. useful hashtable retrieves as a multiple of the number of constraints */
    96#define DEFAULT_WAITINGFAC 2.0 /**< number of calls to wait until next execution as a multiple of the number of useless calls */
    97
    98#define MAXSCALE 1000.0 /**< maximal allowed scale for cancelling nonzeros */
    99
    100
    101/*
    102 * Data structures
    103 */
    104
    105/** presolver data */
    106struct SCIP_PresolData
    107{
    108 int nfailures; /**< number of calls to presolver without success */
    109 int nwaitingcalls; /**< number of presolver calls until next real execution */
    110 int naggregated; /**< number of aggregated variables */
    111 int maxcontfillin; /**< maximal fillin for continuous variables */
    112 int maxintfillin; /**< maximal fillin for integer variables*/
    113 int maxbinfillin; /**< maximal fillin for binary variables */
    114 int maxconsiderednonzeros;/**< maximal number of considered nonzeros within one column (-1: no limit) */
    115 int mineliminatednonzeros;/**< minimal eliminated nonzeros within one column if we need to add a constraint to the problem */
    116 SCIP_Real maxretrievefac; /**< limit on the number of useless vs. useful hashtable retrieves as a multiple of the number of constraints */
    117 SCIP_Real waitingfac; /**< number of calls to wait until next execution as a multiple of the number of useless calls */
    118 SCIP_Bool enablecopy; /**< should dualsparsify presolver be copied to sub-SCIPs? */
    119 SCIP_Bool preserveintcoefs; /**< should we forbid cancellations that destroy integer coefficients? */
    120 SCIP_Bool preservegoodlocks; /**< should we preserve good locked properties of variables (at most one lock in one direction)? */
    121};
    122
    123/** structure representing a pair of constraints in a column; used for lookup in a hashtable */
    125{
    126 int colindex; /**< index of the column */
    127 int consindex1; /**< index of the first constraint */
    128 int consindex2; /**< index of the second constraint */
    129 SCIP_Real conscoef1; /**< coefficient of the first constraint */
    130 SCIP_Real conscoef2; /**< coefficient of the second constriant */
    131};
    132
    134
    135/*
    136 * Local methods
    137 */
    138
    139/** returns TRUE iff both keys are equal */
    140static
    141SCIP_DECL_HASHKEYEQ(consPairsEqual)
    142{ /*lint --e{715}*/
    143 SCIP* scip;
    144 COLCONSPAIR* conspair1;
    145 COLCONSPAIR* conspair2;
    146 SCIP_Real ratio1;
    147 SCIP_Real ratio2;
    148
    149 scip = (SCIP*) userptr;
    150 conspair1 = (COLCONSPAIR*) key1;
    151 conspair2 = (COLCONSPAIR*) key2;
    152
    153 if( conspair1->consindex1 != conspair2->consindex1 )
    154 return FALSE;
    155
    156 if( conspair1->consindex2 != conspair2->consindex2 )
    157 return FALSE;
    158
    159 ratio1 = conspair1->conscoef2 / conspair1->conscoef1;
    160 ratio2 = conspair2->conscoef2 / conspair2->conscoef1;
    161
    162 return SCIPisEQ(scip, ratio1, ratio2);
    163}
    164
    165/** returns the hash value of the key */
    166static
    167SCIP_DECL_HASHKEYVAL(consPairHashval)
    168{ /*lint --e{715}*/
    169 COLCONSPAIR* conspair;
    170
    171 conspair = (COLCONSPAIR*) key;
    172
    173 return SCIPhashThree(conspair->consindex1, conspair->consindex2, SCIPrealHashCode(conspair->conscoef2 / conspair->conscoef1));
    174}
    175
    176/** calculate maximal activity of one row without one specific column */
    177static
    179 SCIP* scip, /**< SCIP main data structure */
    180 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
    181 int row, /**< row index */
    182 int col /**< column index */
    183 )
    184{
    185 SCIP_Real* valpnt;
    186 int* rowpnt;
    187 int* rowend;
    188 SCIP_Real maxactivity;
    189 SCIP_Real val;
    190 SCIP_Real lb;
    191 SCIP_Real ub;
    192 int c;
    193
    194 assert(scip != NULL);
    195 assert(matrix != NULL);
    196
    197 maxactivity = 0;
    198
    199 rowpnt = SCIPmatrixGetRowIdxPtr(matrix, row);
    200 rowend = rowpnt + SCIPmatrixGetRowNNonzs(matrix, row);
    201 valpnt = SCIPmatrixGetRowValPtr(matrix, row);
    202
    203 for( ; (rowpnt < rowend); rowpnt++, valpnt++ )
    204 {
    205 c = *rowpnt;
    206 val = *valpnt;
    207
    208 if( c == col )
    209 continue;
    210
    211 if( val > 0.0 )
    212 {
    213 ub = SCIPmatrixGetColUb(matrix, c);
    214 assert(!SCIPisInfinity(scip, ub));
    215
    216 maxactivity += val * ub;
    217 }
    218 else if( val < 0.0 )
    219 {
    220 lb = SCIPmatrixGetColLb(matrix, c);
    221 assert(!SCIPisInfinity(scip, -lb));
    222
    223 maxactivity += val * lb;
    224 }
    225 }
    226
    227 return maxactivity;
    228}
    229
    230/** calculate minimal activity of one row without one specific column */
    231static
    233 SCIP* scip, /**< SCIP main data structure */
    234 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
    235 int row, /**< row index */
    236 int col /**< column index */
    237 )
    238{
    239 SCIP_Real* valpnt;
    240 int* rowpnt;
    241 int* rowend;
    242 SCIP_Real minactivity;
    243 SCIP_Real val;
    244 SCIP_Real lb;
    245 SCIP_Real ub;
    246 int c;
    247
    248 assert(scip != NULL);
    249 assert(matrix != NULL);
    250
    251 minactivity = 0;
    252
    253 rowpnt = SCIPmatrixGetRowIdxPtr(matrix, row);
    254 rowend = rowpnt + SCIPmatrixGetRowNNonzs(matrix, row);
    255 valpnt = SCIPmatrixGetRowValPtr(matrix, row);
    256
    257 for( ; (rowpnt < rowend); rowpnt++, valpnt++ )
    258 {
    259 c = *rowpnt;
    260 val = *valpnt;
    261
    262 if( c == col )
    263 continue;
    264
    265 if( val > 0.0 )
    266 {
    267 lb = SCIPmatrixGetColLb(matrix, c);
    268 assert(!SCIPisInfinity(scip, -lb));
    269
    270 minactivity += val * lb;
    271 }
    272 else if( val < 0.0 )
    273 {
    274 ub = SCIPmatrixGetColUb(matrix, c);
    275 assert(!SCIPisInfinity(scip, ub));
    276
    277 minactivity += val * ub;
    278 }
    279 }
    280
    281 return minactivity;
    282}
    283
    284/** get minimal and maximal residual activity without one specified column */
    285static
    287 SCIP* scip, /**< SCIP main data structure */
    288 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
    289 int col, /**< column index */
    290 int row, /**< row index */
    291 SCIP_Real val, /**< coefficient of this variable in this row */
    292 SCIP_Real* minresactivity, /**< minimum residual activity of this row */
    293 SCIP_Real* maxresactivity, /**< maximum residual activity of this row */
    294 SCIP_Bool* isminsettoinfinity, /**< flag indicating if minresactiviy is set to infinity */
    295 SCIP_Bool* ismaxsettoinfinity /**< flag indicating if maxresactiviy is set to infinity */
    296 )
    297{
    298 SCIP_Real lb;
    299 SCIP_Real ub;
    300 int nmaxactneginf;
    301 int nmaxactposinf;
    302 int nminactneginf;
    303 int nminactposinf;
    304 SCIP_Real maxactivity;
    305 SCIP_Real minactivity;
    306
    307 assert(scip != NULL);
    308 assert(matrix != NULL);
    309 assert(minresactivity != NULL);
    310 assert(maxresactivity != NULL);
    311 assert(isminsettoinfinity != NULL);
    312 assert(ismaxsettoinfinity != NULL);
    313
    314 lb = SCIPmatrixGetColLb(matrix, col);
    315 ub = SCIPmatrixGetColUb(matrix, col);
    316
    317 *isminsettoinfinity = FALSE;
    318 *ismaxsettoinfinity = FALSE;
    319
    320 nmaxactneginf = SCIPmatrixGetRowNMaxActNegInf(matrix, row);
    321 nmaxactposinf = SCIPmatrixGetRowNMaxActPosInf(matrix, row);
    322 nminactneginf = SCIPmatrixGetRowNMinActNegInf(matrix, row);
    323 nminactposinf = SCIPmatrixGetRowNMinActPosInf(matrix, row);
    324
    325 maxactivity = SCIPmatrixGetRowMaxActivity(matrix, row);
    326 minactivity = SCIPmatrixGetRowMinActivity(matrix, row);
    327
    328 if( val >= 0.0 )
    329 {
    330 if( SCIPisInfinity(scip, ub) )
    331 {
    332 assert(nmaxactposinf >= 1);
    333 if( nmaxactposinf == 1 && nmaxactneginf == 0 )
    334 *maxresactivity = getMaxActivitySingleRowWithoutCol(scip, matrix, row, col);
    335 else
    336 {
    337 *maxresactivity = SCIPinfinity(scip);
    338 *ismaxsettoinfinity = TRUE;
    339 }
    340 }
    341 else
    342 {
    343 if( (nmaxactneginf + nmaxactposinf) > 0 )
    344 {
    345 *maxresactivity = SCIPinfinity(scip);
    346 *ismaxsettoinfinity = TRUE;
    347 }
    348 else
    349 *maxresactivity = maxactivity - val * ub;
    350 }
    351
    352 if( SCIPisInfinity(scip, -lb) )
    353 {
    354 assert(nminactneginf >= 1);
    355 if( nminactneginf == 1 && nminactposinf == 0 )
    356 *minresactivity = getMinActivitySingleRowWithoutCol(scip, matrix, row, col);
    357 else
    358 {
    359 *minresactivity = -SCIPinfinity(scip);
    360 *isminsettoinfinity = TRUE;
    361 }
    362 }
    363 else
    364 {
    365 if( (nminactneginf + nminactposinf) > 0 )
    366 {
    367 *minresactivity = -SCIPinfinity(scip);
    368 *isminsettoinfinity = TRUE;
    369 }
    370 else
    371 *minresactivity = minactivity - val * lb;
    372 }
    373 }
    374 else
    375 {
    376 if( SCIPisInfinity(scip, -lb) )
    377 {
    378 assert(nmaxactneginf >= 1);
    379 if( nmaxactneginf == 1 && nmaxactposinf == 0 )
    380 *maxresactivity = getMaxActivitySingleRowWithoutCol(scip, matrix, row, col);
    381 else
    382 {
    383 *maxresactivity = SCIPinfinity(scip);
    384 *ismaxsettoinfinity = TRUE;
    385 }
    386 }
    387 else
    388 {
    389 if( (nmaxactneginf + nmaxactposinf) > 0 )
    390 {
    391 *maxresactivity = SCIPinfinity(scip);
    392 *ismaxsettoinfinity = TRUE;
    393 }
    394 else
    395 *maxresactivity = maxactivity - val * lb;
    396 }
    397
    398 if( SCIPisInfinity(scip, ub) )
    399 {
    400 assert(nminactposinf >= 1);
    401 if( nminactposinf == 1 && nminactneginf == 0 )
    402 *minresactivity = getMinActivitySingleRowWithoutCol(scip, matrix, row, col);
    403 else
    404 {
    405 *minresactivity = -SCIPinfinity(scip);
    406 *isminsettoinfinity = TRUE;
    407 }
    408 }
    409 else
    410 {
    411 if( (nminactneginf + nminactposinf) > 0 )
    412 {
    413 *minresactivity = -SCIPinfinity(scip);
    414 *isminsettoinfinity = TRUE;
    415 }
    416 else
    417 *minresactivity = minactivity - val * ub;
    418 }
    419 }
    420}
    421
    422/** calculate the upper and lower bound of one variable from one row */
    423static
    425 SCIP* scip, /**< SCIP main data structure */
    426 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
    427 int col, /**< column index of variable */
    428 int row, /**< row index */
    429 SCIP_Real val, /**< coefficient of this column in this row */
    430 SCIP_Real* rowub, /**< upper bound of row */
    431 SCIP_Bool* ubfound, /**< flag indicating that an upper bound was calculated */
    432 SCIP_Real* rowlb, /**< lower bound of row */
    433 SCIP_Bool* lbfound /**< flag indicating that a lower bound was caluclated */
    434 )
    435{
    436 SCIP_Bool isminsettoinfinity;
    437 SCIP_Bool ismaxsettoinfinity;
    438 SCIP_Real minresactivity;
    439 SCIP_Real maxresactivity;
    440 SCIP_Real lhs;
    441 SCIP_Real rhs;
    442
    443 assert(rowub != NULL);
    444 assert(ubfound != NULL);
    445 assert(rowlb != NULL);
    446 assert(lbfound != NULL);
    447
    448 *rowub = SCIPinfinity(scip);
    449 *ubfound = FALSE;
    450 *rowlb = -SCIPinfinity(scip);
    451 *lbfound = FALSE;
    452
    453 getMinMaxActivityResiduals(scip, matrix, col, row, val,
    454 &minresactivity, &maxresactivity,
    455 &isminsettoinfinity, &ismaxsettoinfinity);
    456
    457 lhs = SCIPmatrixGetRowLhs(matrix, row);
    458 rhs = SCIPmatrixGetRowRhs(matrix, row);
    459
    460 if( val > 0.0 )
    461 {
    462 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) )
    463 {
    464 *rowub = (rhs - minresactivity) / val;
    465 *ubfound = TRUE;
    466 }
    467
    468 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) )
    469 {
    470 *rowlb = (lhs - maxresactivity) / val;
    471 *lbfound = TRUE;
    472 }
    473 }
    474 else
    475 {
    476 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) )
    477 {
    478 *rowub = (lhs - maxresactivity) / val;
    479 *ubfound = TRUE;
    480 }
    481
    482 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) )
    483 {
    484 *rowlb = (rhs - minresactivity) / val;
    485 *lbfound = TRUE;
    486 }
    487 }
    488}
    489
    490/** detect implied variable bounds */
    491static
    493 SCIP* scip, /**< SCIP main data structure */
    494 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
    495 int col, /**< column index for implied free test */
    496 SCIP_Bool* ubimplied, /**< flag indicating an implied upper bound */
    497 SCIP_Bool* lbimplied /**< flag indicating an implied lower bound */
    498 )
    499{
    500 SCIP_Real* valpnt;
    501 int* colpnt;
    502 int* colend;
    503 SCIP_Real impliedub;
    504 SCIP_Real impliedlb;
    505 SCIP_Real ub;
    506 SCIP_Real lb;
    507
    508 assert(scip != NULL);
    509 assert(matrix != NULL);
    510 assert(ubimplied != NULL);
    511 assert(lbimplied != NULL);
    512
    513 *ubimplied = FALSE;
    514 impliedub = SCIPinfinity(scip);
    515
    516 *lbimplied = FALSE;
    517 impliedlb = -SCIPinfinity(scip);
    518
    519 ub = SCIPmatrixGetColUb(matrix, col);
    520 lb = SCIPmatrixGetColLb(matrix, col);
    521
    522 colpnt = SCIPmatrixGetColIdxPtr(matrix, col);
    523 colend = colpnt + SCIPmatrixGetColNNonzs(matrix, col);
    524 valpnt = SCIPmatrixGetColValPtr(matrix, col);
    525 for( ; (colpnt < colend); colpnt++, valpnt++ )
    526 {
    527 SCIP_Real rowub;
    528 SCIP_Bool ubfound;
    529 SCIP_Real rowlb;
    530 SCIP_Bool lbfound;
    531
    532 getVarBoundsOfRow(scip, matrix, col, *colpnt, *valpnt, &rowub, &ubfound, &rowlb, &lbfound);
    533
    534 if( ubfound && (rowub < impliedub) )
    535 impliedub = rowub;
    536
    537 if( lbfound && (rowlb > impliedlb) )
    538 impliedlb = rowlb;
    539 }
    540
    541 /* we consider +/-inf bounds as implied bounds */
    542 if( SCIPisInfinity(scip, ub) ||
    543 (!SCIPisInfinity(scip, ub) && SCIPisLE(scip, impliedub, ub)) )
    544 *ubimplied = TRUE;
    545
    546 if( SCIPisInfinity(scip, -lb) ||
    547 (!SCIPisInfinity(scip, -lb) && SCIPisGE(scip, impliedlb, lb)) )
    548 *lbimplied = TRUE;
    549}
    550
    551/** y = weight1 * var[colidx1] + var[colidx2] */
    552static
    554 SCIP* scip, /**< SCIP datastructure */
    555 SCIP_MATRIX* matrix, /**< matrix datastructure */
    556 SCIP_PRESOLDATA* presoldata, /**< presolver data */
    557 SCIP_VAR** vars, /**< the current variables */
    558 int colidx1, /**< one of the indexes of column to try nonzero cancellation for */
    559 int colidx2, /**< one of the indexes of column to try nonzero cancellation for */
    560 SCIP_Bool isimpliedfree, /**< is the aggregated variable implied free? */
    561 SCIP_Real weight1 /**< weight variable one in the aggregated expression */
    562 )
    563{
    564 SCIP_VAR* tmpvars[2];
    565 SCIP_Real coefs[2];
    566 char newvarname[SCIP_MAXSTRLEN];
    567 char newconsname[SCIP_MAXSTRLEN];
    568 SCIP_CONS* newcons;
    569 SCIP_VAR* aggregatedvar;
    570 SCIP_VAR* newvar;
    571 SCIP_VARTYPE newvartype;
    572 SCIP_IMPLINTTYPE newvarimpltype;
    573 SCIP_Real constant;
    574 SCIP_Real newlb;
    575 SCIP_Real newub;
    576 SCIP_Real lhs;
    577 SCIP_Real rhs;
    578 SCIP_Bool infeasible;
    579 SCIP_Bool aggregated;
    580#ifndef NDEBUG
    581 if( isimpliedfree )
    582 {
    583 SCIP_Bool lbimplied;
    584 SCIP_Bool ubimplied;
    585
    586 getImpliedBounds(scip, matrix, colidx2, &ubimplied, &lbimplied);
    587 assert(lbimplied && ubimplied);
    588 }
    589#endif
    590
    591 assert( !SCIPisSumZero(scip, weight1) );
    592 assert( !SCIPisSumZero(scip, 1.0 / weight1) );
    593
    594 presoldata->naggregated += 1;
    595 aggregatedvar = vars[colidx2];
    596
    597 /* if the variable is implied free, we make sure that the columns bounds are removed,
    598 * so that subsequent checks for implied bounds do not interfere with the exploitation
    599 * of this variables implied bounds
    600 */
    601 if( isimpliedfree )
    602 {
    603 SCIPdebugMsg(scip, "remove column bounds of column %d\n", colidx2);
    604 SCIPmatrixRemoveColumnBounds(scip, matrix, colidx2);
    605 }
    606
    607 assert(!SCIPdoNotMultaggrVar(scip, aggregatedvar));
    608
    609 (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "dualsparsifyvar_%d", presoldata->naggregated);
    610
    611 constant = 0.0;
    612
    613 if( weight1 > 0.0 )
    614 {
    615 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(vars[colidx1])) ||
    616 SCIPisInfinity(scip, -SCIPvarGetLbGlobal(vars[colidx2])) )
    617 newlb = -SCIPinfinity(scip);
    618 else
    619 newlb = weight1 * SCIPvarGetLbGlobal(vars[colidx1]) + SCIPvarGetLbGlobal(vars[colidx2]);
    620
    621 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(vars[colidx1])) ||
    622 SCIPisInfinity(scip, SCIPvarGetUbGlobal(vars[colidx2])) )
    623 newub = SCIPinfinity(scip);
    624 else
    625 newub = weight1 * SCIPvarGetUbGlobal(vars[colidx1]) + SCIPvarGetUbGlobal(vars[colidx2]);
    626 }
    627 else
    628 {
    629 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(vars[colidx1])) ||
    630 SCIPisInfinity(scip, -SCIPvarGetLbGlobal(vars[colidx2])) )
    631 newlb = -SCIPinfinity(scip);
    632 else
    633 newlb = weight1 * SCIPvarGetUbGlobal(vars[colidx1]) + SCIPvarGetLbGlobal(vars[colidx2]);
    634
    635 if( SCIPisInfinity(scip, SCIPvarGetLbGlobal(vars[colidx1])) ||
    636 SCIPisInfinity(scip, SCIPvarGetUbGlobal(vars[colidx2])) )
    637 newub = SCIPinfinity(scip);
    638 else
    639 newub = weight1 * SCIPvarGetLbGlobal(vars[colidx1]) + SCIPvarGetUbGlobal(vars[colidx2]);
    640 }
    641
    642 newvartype = SCIPvarIsIntegral(aggregatedvar) ? SCIP_VARTYPE_INTEGER : SCIP_VARTYPE_CONTINUOUS;
    643 newvarimpltype = SCIPvarIsImpliedIntegral(aggregatedvar) ? SCIP_IMPLINTTYPE_WEAK : SCIP_IMPLINTTYPE_NONE;
    644
    645 lhs = SCIPvarGetLbGlobal(vars[colidx2]);
    646 rhs = SCIPvarGetUbGlobal(vars[colidx2]);
    647
    648 SCIP_CALL( SCIPcreateVarImpl(scip, &newvar, newvarname, newlb, newub, 0.0, newvartype, newvarimpltype,
    649 SCIPvarIsInitial(aggregatedvar), SCIPvarIsRemovable(aggregatedvar), NULL, NULL, NULL, NULL, NULL) );
    650 SCIP_CALL( SCIPaddVar(scip, newvar) );
    651
    652 /* set the debug solution value for the new variable */
    653#ifdef WITH_DEBUG_SOLUTION
    654 if( SCIPdebugIsMainscip(scip) )
    655 {
    656 SCIP_Real val1;
    657 SCIP_Real val2;
    658
    659 SCIP_CALL( SCIPdebugGetSolVal(scip, vars[colidx1], &val1) );
    660 SCIP_CALL( SCIPdebugGetSolVal(scip, vars[colidx2], &val2) );
    661 SCIP_CALL( SCIPdebugAddSolVal(scip, newvar, weight1 * val1 + val2) );
    662
    663 SCIPdebugMsg(scip, "set debug solution value of %s to %g\n", SCIPvarGetName(newvar), weight1 * val1 + val2);
    664 }
    665#endif
    666
    667 tmpvars[0] = vars[colidx1];
    668 tmpvars[1] = newvar;
    669 coefs[0] = -weight1;
    670 coefs[1] = 1.0;
    671
    672 SCIP_CALL( SCIPmultiaggregateVar(scip, aggregatedvar, 2, tmpvars, coefs, constant, &infeasible, &aggregated) );
    673
    674 assert(!infeasible);
    675 assert(aggregated);
    676
    677 vars[colidx2] = newvar;
    678
    679 /* create a linear constraint that ensures that var[colidx2].lb <= y - weight1 * var[colidx1] <= var[colidx2].ub;
    680 * note that it might happen that vars[colidx2] is not implied free even though it has infinite bounds because
    681 * getImpliedBounds() considers infinite bounds to be implied
    682 */
    683 if( !isimpliedfree && (!SCIPisInfinity(scip, rhs) || !SCIPisInfinity(scip, -lhs)) )
    684 {
    685 SCIPdebugMsg(scip, "create a linear constraint to ensure %g <= %g %s + %g %s <= %g\n", lhs, coefs[0], SCIPvarGetName(tmpvars[0]),
    686 coefs[1], SCIPvarGetName(tmpvars[1]), rhs);
    687 (void) SCIPsnprintf(newconsname, SCIP_MAXSTRLEN, "dualsparsifycons_%d", presoldata->naggregated);
    688
    689 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, newconsname, 2, tmpvars, coefs,
    690 lhs, rhs, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
    691 SCIP_CALL( SCIPaddCons(scip, newcons) );
    692
    693 SCIPdebugPrintCons(scip, newcons, NULL);
    694
    695 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    696 }
    697
    698 SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
    699
    700 return SCIP_OKAY;
    701}
    702
    703/** try nonzero cancellation for given column */
    704static
    706 SCIP* scip, /**< SCIP datastructure */
    707 SCIP_MATRIX* matrix, /**< the constraint matrix */
    708 SCIP_PRESOLDATA* presoldata, /**< presolver data */
    709 SCIP_HASHTABLE* pairtable, /**< the hashtable containing COLCONSPAIR's of equations */
    710 SCIP_Bool* ishashingcols, /**< array to indicates whether it is impliedfree or not */
    711 SCIP_VAR** vars, /**< array to store the current variables */
    712 SCIP_Bool* isblockedvar, /**< array to indicates whether it is blocked or not */
    713 int colidx, /**< index of column to try nonzero cancellation for */
    714 int maxcontfillin, /**< maximal fill-in allowed for continuous variables */
    715 int maxintfillin, /**< maximal fill-in allowed for integral variables */
    716 int maxbinfillin, /**< maximal fill-in allowed for binary variables */
    717 int maxconsiderednonzeros, /**< maximal number of nonzeros to consider for cancellation */
    718 SCIP_Bool preserveintcoefs, /**< only perform nonzero cancellation if integrality of coefficients is preserved? */
    719 SCIP_Longint* nuseless, /**< pointer to update number of useless hashtable retrieves */
    720 int* nchgcoefs, /**< pointer to update number of changed coefficients */
    721 int* ncanceled, /**< pointer to update number of canceled nonzeros */
    722 int* nfillin, /**< pointer to update the produced fill-in */
    723 SCIP_Bool isaddedcons /**< whether a linear constraint required to added to keep the validity */
    724 )
    725{
    726 SCIP_VAR* cancelvar;
    727 SCIP_Real* cancelcolvals;
    728 SCIP_Real* colvalptr;
    729 SCIP_Real* tmpvals;
    730 SCIP_Real* scores;
    731 int* cancelcolinds;
    732 int* colidxptr;
    733 int* tmpinds;
    734 SCIP_Real bestcancelrate;
    735 SCIP_Real bestscale;
    736 SCIP_Real ncols;
    737 SCIP_Bool colishashing;
    738 SCIP_Bool swapped = FALSE;
    739 int cancelcollen;
    740 int bestnfillin;
    741 int nretrieves;
    742 int maxfillin;
    743 int bestcand;
    744 int nchgcoef;
    745
    746 ncols = SCIPmatrixGetNColumns(matrix);
    747 colishashing = ishashingcols[colidx];
    748 cancelcollen = SCIPmatrixGetColNNonzs(matrix, colidx);
    749 colidxptr = SCIPmatrixGetColIdxPtr(matrix, colidx);
    750 colvalptr = SCIPmatrixGetColValPtr(matrix, colidx);
    751 cancelvar = vars[colidx];
    752
    753 if( SCIPvarIsIntegral(cancelvar) )
    754 {
    755 if( SCIPvarIsBinary(cancelvar) )
    756 maxfillin = maxbinfillin;
    757 else
    758 maxfillin = maxintfillin;
    759 }
    760 else
    761 maxfillin = maxcontfillin;
    762
    763 SCIP_CALL( SCIPduplicateBufferArray(scip, &cancelcolinds, colidxptr, cancelcollen) );
    764 SCIP_CALL( SCIPduplicateBufferArray(scip, &cancelcolvals, colvalptr, cancelcollen) );
    765 SCIP_CALL( SCIPallocBufferArray(scip, &tmpinds, cancelcollen) );
    766 SCIP_CALL( SCIPallocBufferArray(scip, &tmpvals, cancelcollen) );
    767 SCIP_CALL( SCIPallocBufferArray(scip, &scores, cancelcollen) );
    768
    769 nchgcoef = 0;
    770 nretrieves = 0;
    771 while( TRUE ) /*lint !e716 */
    772 {
    773 COLCONSPAIR colconspair;
    774 int maxlen;
    775 int i;
    776 int j;
    777
    778 bestcand = -1;
    779 bestnfillin = 0;
    780 bestscale = 1.0;
    781 bestcancelrate = 0.0;
    782
    783 /* sort the rows non-decreasingly by number of nonzeros
    784 * if the number of nonzeros, we use the colindex as tie-breaker
    785 */
    786 for( i = 0; i < cancelcollen; ++i )
    787 {
    788 tmpinds[i] = i;
    789 scores[i] = -SCIPmatrixGetRowNNonzs(matrix, cancelcolinds[i]) - 1.0 * cancelcolinds[i] / (ncols);
    790 }
    791 SCIPsortRealInt(scores, tmpinds, cancelcollen);
    792
    793 maxlen = cancelcollen;
    794 if( maxconsiderednonzeros >= 0 )
    795 maxlen = MIN(cancelcollen, maxconsiderednonzeros);
    796
    797 for( i = 0; i < maxlen; ++i )
    798 {
    799 for( j = i + 1; j < maxlen; ++j )
    800 {
    801 COLCONSPAIR* hashingcolconspair;
    802 SCIP_VAR* hashingcolvar;
    803 SCIP_Real* hashingcolvals;
    804 int* hashingcolinds;
    805 SCIP_Real cancelrate;
    806 SCIP_Real rowlhs;
    807 SCIP_Real rowrhs;
    808 SCIP_Real scale;
    809 SCIP_Bool hashingcolisbin;
    810 SCIP_Bool abortpair;
    811 int hashingcollen;
    812 int ntotfillin;
    813 int ncancel;
    814 int a,b;
    815 int i1,i2;
    816
    817 i1 = tmpinds[i];
    818 i2 = tmpinds[j];
    819
    820 assert(cancelcolinds[i] < cancelcolinds[j]);
    821
    822 if( cancelcolinds[i1] < cancelcolinds[i2] )
    823 {
    824 colconspair.consindex1 = cancelcolinds[i1];
    825 colconspair.consindex2 = cancelcolinds[i2];
    826 colconspair.conscoef1 = cancelcolvals[i1];
    827 colconspair.conscoef2 = cancelcolvals[i2];
    828 }
    829 else
    830 {
    831 colconspair.consindex1 = cancelcolinds[i2];
    832 colconspair.consindex2 = cancelcolinds[i1];
    833 colconspair.conscoef1 = cancelcolvals[i2];
    834 colconspair.conscoef2 = cancelcolvals[i1];
    835 }
    836
    837 hashingcolconspair = (COLCONSPAIR*)SCIPhashtableRetrieve(pairtable, (void*) &colconspair);
    838 nretrieves++;
    839
    840 if( hashingcolconspair == NULL ||
    841 hashingcolconspair->colindex == colidx || isblockedvar[hashingcolconspair->colindex] )
    842 continue;
    843
    844 /* if the column we want to cancel is a hashing column (which we stored for canceling other columns),
    845 * we will only use the hashing columns for canceling with less nonzeros and if the number of nonzeros
    846 * is equal we use the colindex as tie-breaker to avoid cyclic nonzero cancellation
    847 */
    848 hashingcollen = SCIPmatrixGetColNNonzs(matrix, hashingcolconspair->colindex);
    849 if( colishashing && (cancelcollen < hashingcollen ||
    850 (cancelcollen == hashingcollen && colidx < hashingcolconspair->colindex)) )
    851 continue;
    852
    853 hashingcolvals = SCIPmatrixGetColValPtr(matrix, hashingcolconspair->colindex);
    854 hashingcolinds = SCIPmatrixGetColIdxPtr(matrix, hashingcolconspair->colindex);
    855 hashingcolvar = vars[hashingcolconspair->colindex];
    856 hashingcolisbin = SCIPvarIsBinary(hashingcolvar);
    857
    858 /* @todo do more reduction if knapsack constraint handler supports downgrading constraint,
    859 * i.e., converting into a linear constraint
    860 */
    861 if( hashingcolisbin )
    862 continue;
    863
    864 scale = -colconspair.conscoef1 / hashingcolconspair->conscoef1;
    865 assert(scale != 0.0); /*lint !e777*/
    866
    867 if( REALABS(scale) > MAXSCALE )
    868 continue;
    869
    870 if( !SCIPisVarAggrCoefAcceptable(scip, hashingcolvar, scale) )
    871 continue;
    872
    873 if( SCIPvarIsIntegral(hashingcolvar) )
    874 {
    875 if( SCIPvarIsIntegral(cancelvar) )
    876 {
    877 /* skip if the hashing variable is an integer variable and
    878 * the canceled variable is an implicit integer variable
    879 */
    880 if( !SCIPvarIsImpliedIntegral(hashingcolvar) && SCIPvarIsImpliedIntegral(cancelvar) )
    881 continue;
    882
    883 /* skip if the scale is non-integral */
    884 if( !SCIPisIntegral(scip, scale) )
    885 continue;
    886
    887 /* round scale to be exactly integral */
    888 scale = floor(scale + 0.5);
    889 }
    890 /* skip if the canceled variable is a continuous variable */
    891 else
    892 continue;
    893 }
    894
    895 a = 0;
    896 b = 0;
    897 ncancel = 0;
    898 ntotfillin = 0;
    899 abortpair = FALSE;
    900
    901 while( a < cancelcollen && b < hashingcollen )
    902 {
    903 if( cancelcolinds[a] == hashingcolinds[b] )
    904 {
    905 SCIP_Real newcoef;
    906
    907 newcoef = cancelcolvals[a] + scale * hashingcolvals[b];
    908
    909 /* check if coefficient is canceled */
    910 if( SCIPisZero(scip, newcoef) )
    911 {
    912 ++ncancel;
    913 }
    914 /* otherwise, check if integral coefficients are preserved if the column is integral */
    915 else if( (preserveintcoefs && SCIPvarIsIntegral(cancelvar) &&
    916 SCIPisIntegral(scip, cancelcolvals[a]) && !SCIPisIntegral(scip, newcoef)) )
    917 {
    918 abortpair = TRUE;
    919 break;
    920 }
    921 /* finally, check if locks could be modified in a bad way due to flipped signs */
    922 else if( COPYSIGN(1.0, newcoef) != COPYSIGN(1.0, cancelcolvals[a]) ) /*lint !e777*/
    923 {
    924 /* do not flip signs for non-canceled coefficients if this adds a lock to a variable that
    925 * had at most one lock in that direction before, except if the other direction gets unlocked
    926 */
    927 rowrhs = SCIPmatrixGetRowRhs(matrix, cancelcolinds[a]);
    928 rowlhs = SCIPmatrixGetRowLhs(matrix, cancelcolinds[a]);
    929 if( (cancelcolvals[a] > 0.0 && ! SCIPisInfinity(scip, rowrhs)) ||
    930 (cancelcolvals[a] < 0.0 && ! SCIPisInfinity(scip, -rowlhs)) )
    931 {
    932 /* if we get into this case the variable had a positive coefficient in a <= constraint or
    933 * a negative coefficient in a >= constraint, e.g. an uplock. If this was the only uplock
    934 * we do not abort their cancelling, otherwise we abort if we had a single or no downlock
    935 * and add one
    936 */
    937 if( presoldata->preservegoodlocks && (SCIPmatrixGetColNUplocks(matrix, colidx) > 1 &&
    938 SCIPmatrixGetColNDownlocks(matrix, colidx) <= 1) )
    939 {
    940 abortpair = TRUE;
    941 break;
    942 }
    943 }
    944
    945 if( (cancelcolvals[a] < 0.0 && ! SCIPisInfinity(scip, rowrhs)) ||
    946 (cancelcolvals[a] > 0.0 && ! SCIPisInfinity(scip, -rowlhs)) )
    947 {
    948 /* symmetric case where the variable had a downlock */
    949 if( presoldata->preservegoodlocks && (SCIPmatrixGetColNDownlocks(matrix, colidx) > 1 &&
    950 SCIPmatrixGetColNUplocks(matrix, colidx) <= 1) )
    951 {
    952 abortpair = TRUE;
    953 break;
    954 }
    955 }
    956 }
    957
    958 ++a;
    959 ++b;
    960 }
    961 else if( cancelcolinds[a] < hashingcolinds[b] )
    962 {
    963 ++a;
    964 }
    965 else
    966 {
    967 SCIP_Real newcoef;
    968
    969 newcoef = scale * hashingcolvals[b];
    970 rowrhs = SCIPmatrixGetRowRhs(matrix, hashingcolinds[b]);
    971 rowlhs = SCIPmatrixGetRowLhs(matrix, hashingcolinds[b]);
    972
    973 if( (newcoef > 0.0 && ! SCIPisInfinity(scip, rowrhs)) ||
    974 (newcoef < 0.0 && ! SCIPisInfinity(scip, -rowlhs)) )
    975 {
    976 if( presoldata->preservegoodlocks && SCIPmatrixGetColNUplocks(matrix, colidx) <= 1 )
    977 {
    978 abortpair = TRUE;
    979 ++b;
    980 break;
    981 }
    982 }
    983
    984 if( (newcoef < 0.0 && ! SCIPisInfinity(scip, rowrhs)) ||
    985 (newcoef > 0.0 && ! SCIPisInfinity(scip, -rowlhs)) )
    986 {
    987 if( presoldata->preservegoodlocks && SCIPmatrixGetColNDownlocks(matrix, colidx) <= 1 )
    988 {
    989 abortpair = TRUE;
    990 ++b;
    991 break;
    992 }
    993 }
    994
    995 ++b;
    996
    997 if( ++ntotfillin > maxfillin )
    998 {
    999 abortpair = TRUE;
    1000 break;
    1001 }
    1002 }
    1003 }
    1004
    1005 if( abortpair )
    1006 continue;
    1007
    1008 while( b < hashingcollen )
    1009 {
    1010 ++b;
    1011
    1012 if( ++ntotfillin > maxfillin )
    1013 break;
    1014 }
    1015CHECKFILLINAGAIN:
    1016 if( ntotfillin > maxfillin || ntotfillin >= ncancel )
    1017 continue;
    1018
    1019 cancelrate = (ncancel - ntotfillin) / (SCIP_Real) cancelcollen;
    1020
    1021 /* if a linear constraint is needed to keep the validity, we require a large nonzero cancellation */
    1022 if( isaddedcons && (ncancel - ntotfillin < presoldata->mineliminatednonzeros) )
    1023 continue;
    1024
    1025 if( cancelrate > bestcancelrate )
    1026 {
    1027 if( ishashingcols[hashingcolconspair->colindex] )
    1028 {
    1029 SCIP_Bool lbimplied;
    1030 SCIP_Bool ubimplied;
    1031
    1032 /* recompute whether a variable is still implied free; after some previous multi-aggregations of
    1033 * some variables, it might be that other variables that are contained in the same linear rows of the
    1034 * matrix are not implied free anymore (see #2971)
    1035 */
    1036 getImpliedBounds(scip, matrix, hashingcolconspair->colindex, &ubimplied, &lbimplied);
    1037
    1038 if( !lbimplied || !ubimplied )
    1039 {
    1040 ishashingcols[hashingcolconspair->colindex] = FALSE;
    1041 ntotfillin += 2;
    1042 goto CHECKFILLINAGAIN;
    1043 }
    1044 }
    1045
    1046 bestnfillin = ntotfillin;
    1047 bestcand = hashingcolconspair->colindex;
    1048 bestscale = scale;
    1049 bestcancelrate = cancelrate;
    1050
    1051 /* stop looking if the current candidate does not create any fill-in or alter coefficients */
    1052 if( cancelrate == 1.0 )
    1053 break;
    1054 }
    1055
    1056 /* we accept the best candidate immediately if it does not create any fill-in or alter coefficients */
    1057 if( bestcand != -1 && bestcancelrate == 1.0 )
    1058 break;
    1059 }
    1060 }
    1061
    1062 if( bestcand != -1 )
    1063 {
    1064 SCIP_Real* hashingcolvals;
    1065 int* hashingcolinds;
    1066 int hashingcollen;
    1067 int tmpcollen;
    1068 int a;
    1069 int b;
    1070
    1071 SCIPdebugMsg(scip, "cancelcol %d (%s) candidate column %d (%s) (bestcancelrate = %g, bestscale = %g)\n",
    1072 colidx, SCIPvarGetName(cancelvar), bestcand, SCIPvarGetName(vars[bestcand]), bestcancelrate, bestscale);
    1073
    1074 hashingcolvals = SCIPmatrixGetColValPtr(matrix, bestcand);
    1075 hashingcolinds = SCIPmatrixGetColIdxPtr(matrix, bestcand);
    1076 hashingcollen = SCIPmatrixGetColNNonzs(matrix, bestcand);
    1077
    1078 a = 0;
    1079 b = 0;
    1080 tmpcollen = 0;
    1081
    1082 while( a < cancelcollen && b < hashingcollen )
    1083 {
    1084 if( cancelcolinds[a] == hashingcolinds[b] )
    1085 {
    1086 SCIP_Real val = cancelcolvals[a] + bestscale * hashingcolvals[b];
    1087
    1088 if( !SCIPisZero(scip, val) )
    1089 {
    1090 tmpinds[tmpcollen] = cancelcolinds[a];
    1091 tmpvals[tmpcollen] = val;
    1092 ++tmpcollen;
    1093 }
    1094 ++nchgcoef;
    1095
    1096 ++a;
    1097 ++b;
    1098 }
    1099 else if( cancelcolinds[a] < hashingcolinds[b] )
    1100 {
    1101 tmpinds[tmpcollen] = cancelcolinds[a];
    1102 tmpvals[tmpcollen] = cancelcolvals[a];
    1103 ++tmpcollen;
    1104 ++a;
    1105 }
    1106 else
    1107 {
    1108 tmpinds[tmpcollen] = hashingcolinds[b];
    1109 tmpvals[tmpcollen] = hashingcolvals[b] * bestscale;
    1110 ++nchgcoef;
    1111 ++tmpcollen;
    1112 ++b;
    1113 }
    1114 }
    1115
    1116 while( a < cancelcollen )
    1117 {
    1118 tmpinds[tmpcollen] = cancelcolinds[a];
    1119 tmpvals[tmpcollen] = cancelcolvals[a];
    1120 ++tmpcollen;
    1121 ++a;
    1122 }
    1123
    1124 while( b < hashingcollen )
    1125 {
    1126 tmpinds[tmpcollen] = hashingcolinds[b];
    1127 tmpvals[tmpcollen] = hashingcolvals[b] * bestscale;
    1128 ++nchgcoef;
    1129 ++tmpcollen;
    1130 ++b;
    1131 }
    1132
    1133 /* update fill-in counter */
    1134 *nfillin += bestnfillin;
    1135
    1136 /* swap the temporary arrays so that the cancelcolinds and cancelcolvals arrays, contain the new
    1137 * changed column, and the tmpinds and tmpvals arrays can be overwritten in the next iteration
    1138 */
    1139 SCIPswapPointers((void**) &tmpinds, (void**) &cancelcolinds);
    1140 SCIPswapPointers((void**) &tmpvals, (void**) &cancelcolvals);
    1141 swapped = ! swapped;
    1142 cancelcollen = tmpcollen;
    1143 SCIP_CALL( aggregation(scip, matrix, presoldata, vars, colidx, bestcand, ishashingcols[bestcand], -bestscale) );
    1144
    1145 /* the newly created variable is now at the position bestcand and is assumed to have the same coefficients.
    1146 * this is not the case if the variable is not implied free since then a new constraint was added and the
    1147 * nonzero fillin would not be counted correctly if we do not block this variable
    1148 */
    1149 if( !ishashingcols[bestcand] )
    1150 isblockedvar[bestcand] = TRUE;
    1151 }
    1152 else
    1153 break;
    1154 }
    1155
    1156 if( nchgcoef != 0 )
    1157 {
    1158 /* update counters */
    1159 *nchgcoefs += nchgcoef;
    1160 *ncanceled += SCIPmatrixGetColNNonzs(matrix, colidx) - cancelcollen;
    1161
    1162 isblockedvar[colidx] = TRUE;
    1163
    1164 /* if successful, decrease the useless hashtable retrieves counter; the rationale here is that we want to keep
    1165 * going if, after many useless calls that almost exceeded the budget, we finally reach a useful section; but we
    1166 * don't allow a negative build-up for the case that the useful section is all at the beginning and we just want
    1167 * to quit quickly afterwards
    1168 */
    1169 *nuseless -= nretrieves;
    1170 *nuseless = MAX(*nuseless, 0);
    1171 }
    1172 else
    1173 {
    1174 /* if not successful, increase useless hashtable retrieves counter */
    1175 *nuseless += nretrieves;
    1176 }
    1177
    1178 SCIPfreeBufferArray(scip, &scores);
    1179 if( swapped )
    1180 {
    1181 SCIPfreeBufferArray(scip, &cancelcolvals);
    1182 SCIPfreeBufferArray(scip, &cancelcolinds);
    1183 SCIPfreeBufferArray(scip, &tmpvals);
    1184 SCIPfreeBufferArray(scip, &tmpinds);
    1185 }
    1186 else
    1187 {
    1188 SCIPfreeBufferArray(scip, &tmpvals);
    1189 SCIPfreeBufferArray(scip, &tmpinds);
    1190 SCIPfreeBufferArray(scip, &cancelcolvals);
    1191 SCIPfreeBufferArray(scip, &cancelcolinds);
    1192 }
    1193
    1194 return SCIP_OKAY;
    1195}
    1196
    1197/** updates failure counter after one execution */
    1198static
    1200 SCIP_PRESOLDATA* presoldata, /**< presolver data */
    1201 SCIP_Bool success /**< was this execution successful? */
    1202 )
    1203{
    1204 assert(presoldata != NULL);
    1205
    1206 if( success )
    1207 {
    1208 presoldata->nfailures = 0;
    1209 presoldata->nwaitingcalls = 0;
    1210 }
    1211 else
    1212 {
    1213 presoldata->nfailures++;
    1214 presoldata->nwaitingcalls = (int)(presoldata->waitingfac*(SCIP_Real)presoldata->nfailures);
    1215 }
    1216}
    1217
    1218/*
    1219 * Callback methods of presolver
    1220 */
    1221
    1222/** copy method for constraint handler plugins (called when SCIP copies plugins) */
    1223static
    1224SCIP_DECL_PRESOLCOPY(presolCopyDualsparsify)
    1225{
    1226 SCIP_PRESOLDATA* presoldata;
    1227
    1228 assert(scip != NULL);
    1229 assert(presol != NULL);
    1230 assert(strcmp(SCIPpresolGetName(presol), PRESOL_NAME) == 0);
    1231
    1232 /* call inclusion method of presolver if copying is enabled */
    1233 presoldata = SCIPpresolGetData(presol);
    1234 assert(presoldata != NULL);
    1235 if( presoldata->enablecopy )
    1236 {
    1238 }
    1239
    1240 return SCIP_OKAY;
    1241}
    1242
    1243
    1244/** execution method of presolver */
    1245static
    1246SCIP_DECL_PRESOLEXEC(presolExecDualsparsify)
    1247{ /*lint --e{715}*/
    1248 SCIP_MATRIX* matrix;
    1249 int* perm;
    1250 int* colidxsorted;
    1251 int* colsparsity;
    1252 SCIP_Real* scores;
    1253 COLCONSPAIR* conspairs;
    1254 SCIP_HASHTABLE* pairtable;
    1255 SCIP_PRESOLDATA* presoldata;
    1256 SCIP_Bool* ishashingcols;
    1257 SCIP_Bool* isblockedvar;
    1258 SCIP_VAR** vars;
    1259 SCIP_Longint maxuseless;
    1260 SCIP_Longint nuseless;
    1261 SCIP_Bool initialized;
    1262 SCIP_Bool complete;
    1263 SCIP_Bool infeasible;
    1264 int ncols;
    1265 int c;
    1266 int i;
    1267 int j;
    1268 int conspairssize;
    1269 int nconspairs;
    1270 int numcancel;
    1271 int nfillin;
    1272
    1273 assert(result != NULL);
    1274
    1275 *result = SCIP_DIDNOTRUN;
    1276
    1277 if( SCIPdoNotAggr(scip) )
    1278 return SCIP_OKAY;
    1279
    1280 /* If restart is performed, some cuts will be tranformed into linear constraints.
    1281 * However, SCIPmatrixCreate() only collects the original constraints (not the constraints transformed from cuts)
    1282 * For this reason, we only perform this method in the first run of branch-and-cut.
    1283 * */
    1284 if( SCIPgetNRuns(scip) > 1 )
    1285 return SCIP_OKAY;
    1286
    1287 presoldata = SCIPpresolGetData(presol);
    1288
    1289 if( presoldata->nwaitingcalls > 0 )
    1290 {
    1291 presoldata->nwaitingcalls--;
    1292 SCIPdebugMsg(scip, "skipping dualsparsify: nfailures=%d, nwaitingcalls=%d\n", presoldata->nfailures,
    1293 presoldata->nwaitingcalls);
    1294 return SCIP_OKAY;
    1295 }
    1296
    1297 SCIPdebugMsg(scip, "starting dualsparsify. . .\n");
    1298 *result = SCIP_DIDNOTFIND;
    1299
    1300 matrix = NULL;
    1301 SCIP_CALL( SCIPmatrixCreate(scip, &matrix, TRUE, &initialized, &complete, &infeasible,
    1302 naddconss, ndelconss, nchgcoefs, nchgbds, nfixedvars) );
    1303
    1304 /* if infeasibility was detected during matrix creation or
    1305 * matrix creation is incomplete, return here.
    1306 */
    1307 if( infeasible || !complete )
    1308 {
    1309 if( initialized )
    1310 SCIPmatrixFree(scip, &matrix);
    1311
    1312 if( infeasible )
    1313 *result = SCIP_CUTOFF;
    1314
    1315 return SCIP_OKAY;
    1316 }
    1317
    1318 if( !initialized )
    1319 return SCIP_OKAY;
    1320
    1321 ncols = SCIPmatrixGetNColumns(matrix);
    1322
    1323 /* sort columns by row indices */
    1324 for( i = 0; i < ncols; i++ )
    1325 {
    1326 int* colpnt = SCIPmatrixGetColIdxPtr(matrix, i);
    1327 SCIP_Real* valpnt = SCIPmatrixGetColValPtr(matrix, i);
    1328 SCIPsortIntReal(colpnt, valpnt, SCIPmatrixGetColNNonzs(matrix, i));
    1329 }
    1330
    1333 SCIP_CALL( SCIPallocBufferArray(scip, &ishashingcols, SCIPmatrixGetNColumns(matrix)) );
    1335 SCIP_CALL( SCIPallocBufferArray(scip, &isblockedvar, SCIPmatrixGetNColumns(matrix)) );
    1336
    1337 /* loop over all columns and create cons pairs */
    1338 conspairssize = 0;
    1339 nconspairs = 0;
    1340 conspairs = NULL;
    1342 SCIPhashGetKeyStandard, consPairsEqual, consPairHashval, (void*) scip) );
    1343
    1344 /* collect implied free variables and their number of nonzeros */
    1345 for( c = 0; c < ncols; c++ )
    1346 {
    1347 SCIP_Bool lbimplied;
    1348 SCIP_Bool ubimplied;
    1349 int nnonz;
    1350
    1351 vars[c] = SCIPmatrixGetVar(matrix, c);
    1352
    1353 /* if the locks do not match do not consider the column for sparsification */
    1354 if( SCIPmatrixDownlockConflict(matrix, c) || SCIPmatrixUplockConflict(matrix, c) )
    1355 {
    1356 isblockedvar[c] = TRUE;
    1357 ishashingcols[c] = FALSE;
    1358 continue;
    1359 }
    1360
    1361 /* skip if the variable is not allowed to be multi-aggregated */
    1362 if( SCIPdoNotMultaggrVar(scip, vars[c]) )
    1363 {
    1364 isblockedvar[c] = TRUE;
    1365 ishashingcols[c] = FALSE;
    1366 continue;
    1367 }
    1368
    1369 nnonz = SCIPmatrixGetColNNonzs(matrix, c);
    1370
    1371 getImpliedBounds(scip, matrix, c, &ubimplied, &lbimplied);
    1372
    1373 ishashingcols[c] = FALSE;
    1374
    1375 if( lbimplied && ubimplied )
    1376 ishashingcols[c] = TRUE;
    1377
    1378 isblockedvar[c] = FALSE;
    1379
    1380 /* only consider implied free variables
    1381 * skip singleton variables, because either the constraint is redundant
    1382 * or the variables can be canceled by variable substitution
    1383 */
    1384 if( nnonz >= 2 && (lbimplied && ubimplied) )
    1385 {
    1386 SCIP_Real* colvals;
    1387 int* colinds;
    1388 int failshift;
    1389 int npairs;
    1390
    1391 colinds = SCIPmatrixGetColIdxPtr(matrix, c);
    1392 colvals = SCIPmatrixGetColValPtr(matrix, c);
    1393
    1394 /* sort the rows non-decreasingly by number of nonzeros
    1395 * if the number of nonzeros is equal, we use the colindex as tie-breaker
    1396 */
    1397 for( i = 0; i < nnonz; ++i )
    1398 {
    1399 perm[i] = i;
    1400 scores[i] = -SCIPmatrixGetRowNNonzs(matrix, colinds[i]) - 1.0 *colinds[i] / ncols;
    1401 }
    1402 SCIPsortRealInt(scores, perm, nnonz);
    1403
    1404 if( presoldata->maxconsiderednonzeros >= 0 )
    1405 nnonz = MIN(nnonz, presoldata->maxconsiderednonzeros);
    1406
    1407 npairs = (nnonz * (nnonz - 1)) / 2;
    1408 if( nconspairs + npairs > conspairssize )
    1409 {
    1410 int newsize = SCIPcalcMemGrowSize(scip, nconspairs + npairs);
    1411 SCIP_CALL( SCIPreallocBufferArray(scip, &conspairs, newsize) );
    1412 conspairssize = newsize;
    1413 }
    1414
    1415 /* if we are called after one or more failures, i.e., executions without finding cancellations, then we
    1416 * shift the section of nonzeros considered; in the case that the maxconsiderednonzeros limit is hit, this
    1417 * results in different constraint pairs being tried and avoids trying the same useless cancellations
    1418 * repeatedly
    1419 */
    1420 failshift = presoldata->nfailures*presoldata->maxconsiderednonzeros;
    1421
    1422 for( i = 0; i < nnonz; ++i )
    1423 {
    1424 for( j = i + 1; j < nnonz; ++j )
    1425 {
    1426 int i1;
    1427 int i2;
    1428
    1429 assert(nconspairs < conspairssize);
    1430 assert(conspairs != NULL);
    1431
    1432 i1 = perm[(i + failshift) % nnonz];
    1433 i2 = perm[(j + failshift) % nnonz];
    1434 /* coverity[var_deref_op] */
    1435 conspairs[nconspairs].colindex = c;
    1436
    1437 if( colinds[i1] < colinds[i2])
    1438 {
    1439 conspairs[nconspairs].consindex1 = colinds[i1];
    1440 conspairs[nconspairs].consindex2 = colinds[i2];
    1441 conspairs[nconspairs].conscoef1 = colvals[i1];
    1442 conspairs[nconspairs].conscoef2 = colvals[i2];
    1443 }
    1444 else
    1445 {
    1446 conspairs[nconspairs].consindex1 = colinds[i2];
    1447 conspairs[nconspairs].consindex2 = colinds[i1];
    1448 conspairs[nconspairs].conscoef1 = colvals[i2];
    1449 conspairs[nconspairs].conscoef2 = colvals[i1];
    1450 }
    1451 ++nconspairs;
    1452 }
    1453 }
    1454 }
    1455 }
    1456
    1457 /* insert conspairs into hash table */
    1458 for( c = 0; c < nconspairs; ++c )
    1459 {
    1460 COLCONSPAIR* otherconspair;
    1461 SCIP_Bool insert;
    1462
    1463 assert(conspairs != NULL);
    1464
    1465 insert = TRUE;
    1466
    1467 /* check if this pair is already contained in the hash table;
    1468 * The loop is required due to the non-transitivity of the hash functions
    1469 */
    1470 while( (otherconspair = (COLCONSPAIR*)SCIPhashtableRetrieve(pairtable, (void*) &conspairs[c])) != NULL )
    1471 {
    1472 /* if the previous constraint pair has fewer or the same number of nonzeros in the attached column
    1473 * we keep that pair and skip this one
    1474 */
    1475 if( SCIPmatrixGetColNNonzs(matrix, otherconspair->colindex) <=
    1476 SCIPmatrixGetColNNonzs(matrix, conspairs[c].colindex) )
    1477 {
    1478 insert = FALSE;
    1479 break;
    1480 }
    1481
    1482 /* this pairs column has fewer nonzeros, so remove the other pair from the hash table and loop */
    1483 SCIP_CALL( SCIPhashtableRemove(pairtable, (void*) otherconspair) );
    1484 }
    1485
    1486 if( insert )
    1487 {
    1488 SCIP_CALL( SCIPhashtableInsert(pairtable, (void*) &conspairs[c]) );
    1489 }
    1490 }
    1491
    1492 /* sort cols according to decreasing sparsity */
    1493 SCIP_CALL( SCIPallocBufferArray(scip, &colidxsorted, ncols) );
    1494 SCIP_CALL( SCIPallocBufferArray(scip, &colsparsity, ncols) );
    1495 for( c = 0; c < ncols; ++c )
    1496 {
    1497 colidxsorted[c] = c;
    1498 colsparsity[c] = -SCIPmatrixGetColNNonzs(matrix, c);
    1499 }
    1500 SCIPsortIntInt(colsparsity, colidxsorted, ncols);
    1501
    1502 /* loop over the columns and cancel nonzeros until maximum number of retrieves is reached */
    1503 maxuseless = (SCIP_Longint)(presoldata->maxretrievefac * (SCIP_Real)ncols);
    1504 nuseless = 0;
    1505 numcancel = 0;
    1506 nfillin = 0;
    1507 for( c = 0; c < ncols && nuseless <= maxuseless && !SCIPisStopped(scip); c++ )
    1508 {
    1509 int colidx;
    1510
    1511 colidx = colidxsorted[c];
    1512
    1513 if( isblockedvar[colidx] )
    1514 continue;
    1515
    1516 /* since the function parameters for the max fillin are unsigned we do not need to handle the
    1517 * unlimited (-1) case due to implicit conversion rules */
    1518 SCIP_CALL( cancelCol(scip, matrix, presoldata, pairtable, ishashingcols, vars, isblockedvar, colidx, \
    1519 presoldata->maxcontfillin == -1 ? INT_MAX : presoldata->maxcontfillin, \
    1520 presoldata->maxintfillin == -1 ? INT_MAX : presoldata->maxintfillin, \
    1521 presoldata->maxbinfillin == -1 ? INT_MAX : presoldata->maxbinfillin, \
    1522 presoldata->maxconsiderednonzeros, presoldata->preserveintcoefs, \
    1523 &nuseless, nchgcoefs, &numcancel, &nfillin, FALSE) );
    1524 }
    1525
    1526 if( numcancel > 0 )
    1527 {
    1529 " (%.1fs) dualsparsify: %d nonzeros canceled\n", SCIPgetSolvingTime(scip), numcancel);
    1530 *result = SCIP_SUCCESS;
    1531 }
    1532 else /* do reductions on variables that contain larger nonzero entries */
    1533 {
    1534 SCIPhashtableRemoveAll(pairtable);
    1535 nconspairs = 0;
    1536
    1537 /* collect large nonzero entries variables and their number of nonzeros */
    1538 for( c = 0; c < ncols; c++ )
    1539 {
    1540 int nnonz;
    1541
    1542 nnonz = SCIPmatrixGetColNNonzs(matrix, c);
    1543 vars[c] = SCIPmatrixGetVar(matrix, c);
    1544
    1545 /* if the locks do not match do not consider the column for sparsification
    1546 * also skip if the variable is not allowed to be multi-aggregated
    1547 */
    1548 if( SCIPmatrixDownlockConflict(matrix, c) || SCIPmatrixUplockConflict(matrix, c) || SCIPdoNotMultaggrVar(scip, vars[c]) )
    1549 {
    1550 isblockedvar[c] = TRUE;
    1551 ishashingcols[c] = FALSE;
    1552 continue;
    1553 }
    1554
    1555 isblockedvar[c] = FALSE;
    1556
    1557 /* only consider nonimplied free variables, i.e., non-hashing columns in the previous step,
    1558 * with large nonzero entries
    1559 * skip singleton variables, because either the constraint is redundant
    1560 * or the variables can be canceled by variables substitution
    1561 */
    1562 if( nnonz >= presoldata->mineliminatednonzeros && !ishashingcols[c] )
    1563 {
    1564 int* colinds;
    1565 SCIP_Real* colvals;
    1566 int npairs;
    1567 int failshift;
    1568
    1569 ishashingcols[c] = TRUE;
    1570 colinds = SCIPmatrixGetColIdxPtr(matrix, c);
    1571 colvals = SCIPmatrixGetColValPtr(matrix, c);
    1572
    1573 /* sort the rows non-decreasingly by number of nonzeros
    1574 * if the number of nonzeros, we use the colindex as tie-breaker
    1575 */
    1576 for( i = 0; i < nnonz; ++i )
    1577 {
    1578 perm[i] = i;
    1579 scores[i] = -SCIPmatrixGetRowNNonzs(matrix, colinds[i]) - 1.0 * colinds[i] / ncols;
    1580 }
    1581 SCIPsortRealInt(scores, perm, nnonz);
    1582
    1583 if( presoldata->maxconsiderednonzeros >= 0 )
    1584 nnonz = MIN(nnonz, presoldata->maxconsiderednonzeros);
    1585
    1586 npairs = (nnonz * (nnonz - 1)) / 2;
    1587 if( nconspairs + npairs > conspairssize )
    1588 {
    1589 int newsize = SCIPcalcMemGrowSize(scip, nconspairs + npairs);
    1590 SCIP_CALL( SCIPreallocBufferArray(scip, &conspairs, newsize) );
    1591 conspairssize = newsize;
    1592 }
    1593
    1594 /* if we are called after one or more failures, i.e., executions without finding cancellations, then we
    1595 * shift the section of nonzeros considered; in the case that the maxconsiderednonzeros limit is hit,
    1596 * this results in different constraint pairs being tried and avoids trying the same useless
    1597 * cancellations repeatedly
    1598 */
    1599 failshift = presoldata->nfailures*presoldata->maxconsiderednonzeros;
    1600
    1601 for( i = 0; i < nnonz; ++i )
    1602 {
    1603 for( j = i + 1; j < nnonz; ++j )
    1604 {
    1605 int i1;
    1606 int i2;
    1607
    1608 assert(nconspairs < conspairssize);
    1609 assert(conspairs != NULL);
    1610
    1611 i1 = perm[(i + failshift) % nnonz];
    1612 i2 = perm[(j + failshift) % nnonz];
    1613 conspairs[nconspairs].colindex = c;
    1614
    1615 if( colinds[i1] < colinds[i2])
    1616 {
    1617 conspairs[nconspairs].consindex1 = colinds[i1];
    1618 conspairs[nconspairs].consindex2 = colinds[i2];
    1619 conspairs[nconspairs].conscoef1 = colvals[i1];
    1620 conspairs[nconspairs].conscoef2 = colvals[i2];
    1621 }
    1622 else
    1623 {
    1624 conspairs[nconspairs].consindex1 = colinds[i2];
    1625 conspairs[nconspairs].consindex2 = colinds[i1];
    1626 conspairs[nconspairs].conscoef1 = colvals[i2];
    1627 conspairs[nconspairs].conscoef2 = colvals[i1];
    1628 }
    1629 ++nconspairs;
    1630 }
    1631 }
    1632 }
    1633 else
    1634 {
    1635 ishashingcols[c] = FALSE;
    1636 }
    1637 }
    1638
    1639 /* insert conspairs into hash table */
    1640 for( c = 0; c < nconspairs; ++c )
    1641 {
    1642 SCIP_Bool insert;
    1643 COLCONSPAIR* otherconspair;
    1644
    1645 assert(conspairs != NULL);
    1646
    1647 insert = TRUE;
    1648
    1649 /* check if this pair is already contained in the hash table;
    1650 * The loop is required due to the non-transitivity of the hash functions
    1651 */
    1652 while( (otherconspair = (COLCONSPAIR*)SCIPhashtableRetrieve(pairtable, (void*) &conspairs[c])) != NULL )
    1653 {
    1654 /* if the previous constraint pair has fewer or the same number of nonzeros in the attached column
    1655 * we keep that pair and skip this one
    1656 */
    1657 if( SCIPmatrixGetColNNonzs(matrix, otherconspair->colindex) <=
    1658 SCIPmatrixGetColNNonzs(matrix, conspairs[c].colindex) )
    1659 {
    1660 insert = FALSE;
    1661 break;
    1662 }
    1663
    1664 /* this pairs column has fewer nonzeros, so remove the other pair from the hash table and loop */
    1665 SCIP_CALL( SCIPhashtableRemove(pairtable, (void*) otherconspair) );
    1666 }
    1667
    1668 if( insert )
    1669 {
    1670 SCIP_CALL( SCIPhashtableInsert(pairtable, (void*) &conspairs[c]) );
    1671 }
    1672 }
    1673
    1674 /* sort rows according to decreasingly sparsity */
    1675 assert(colidxsorted != NULL);
    1676 assert(colsparsity != NULL);
    1677 for( c = 0; c < ncols; ++c )
    1678 {
    1679 colidxsorted[c] = c;
    1680 colsparsity[c] = -SCIPmatrixGetColNNonzs(matrix, c);
    1681 }
    1682 SCIPsortIntInt(colsparsity, colidxsorted, ncols);
    1683
    1684 /* loop over the columns and cancel nonzeros until maximum number of retrieves is reached */
    1685 maxuseless = (SCIP_Longint)(presoldata->maxretrievefac * (SCIP_Real)ncols);
    1686 nuseless = 0;
    1687 for( c = 0; c < ncols && nuseless <= maxuseless; c++ )
    1688 {
    1689 int colidx;
    1690 int nnonz;
    1691
    1692 colidx = colidxsorted[c];
    1693 nnonz = SCIPmatrixGetColNNonzs(matrix, colidx);
    1694
    1695 if( isblockedvar[colidx] || nnonz < presoldata->mineliminatednonzeros )
    1696 continue;
    1697
    1698 /* since the function parameters for the max fillin are unsigned we do not need to handle the
    1699 * unlimited (-1) case due to implicit conversion rules */
    1700 SCIP_CALL( cancelCol(scip, matrix, presoldata, pairtable, ishashingcols, vars, isblockedvar, colidx, \
    1701 presoldata->maxcontfillin == -1 ? INT_MAX : presoldata->maxcontfillin, \
    1702 presoldata->maxintfillin == -1 ? INT_MAX : presoldata->maxintfillin, \
    1703 presoldata->maxbinfillin == -1 ? INT_MAX : presoldata->maxbinfillin, \
    1704 presoldata->maxconsiderednonzeros, presoldata->preserveintcoefs, \
    1705 &nuseless, nchgcoefs, &numcancel, &nfillin, TRUE) );
    1706 }
    1707
    1708 if( numcancel > 0 )
    1709 {
    1711 " (%.1fs) dualsparsify: %d nonzeros canceled\n", SCIPgetSolvingTime(scip), numcancel);
    1712 *result = SCIP_SUCCESS;
    1713 }
    1714 }
    1715
    1716 updateFailureStatistic(presoldata, numcancel > 0);
    1717
    1718 SCIPfreeBufferArrayNull(scip, &conspairs);
    1719 SCIPfreeBufferArray(scip, &colsparsity);
    1720 SCIPfreeBufferArray(scip, &colidxsorted);
    1721
    1722 SCIPhashtableFree(&pairtable);
    1723
    1724 SCIPfreeBufferArray(scip, &isblockedvar);
    1725 SCIPfreeBufferArray(scip, &vars);
    1726 SCIPfreeBufferArray(scip, &ishashingcols);
    1727 SCIPfreeBufferArray(scip, &perm);
    1728 SCIPfreeBufferArray(scip, &scores);
    1729
    1730 SCIPmatrixFree(scip, &matrix);
    1731
    1732 return SCIP_OKAY;
    1733}
    1734
    1735/*
    1736 * presolver specific interface methods
    1737 */
    1738
    1739/** destructor of presolver to free user data (called when SCIP is exiting) */
    1740static
    1741SCIP_DECL_PRESOLFREE(presolFreeDualsparsify)
    1742{ /*lint --e{715}*/
    1743 SCIP_PRESOLDATA* presoldata;
    1744
    1745 /* free presolver data */
    1746 presoldata = SCIPpresolGetData(presol);
    1747 assert(presoldata != NULL);
    1748
    1749 SCIPfreeBlockMemory(scip, &presoldata);
    1750 SCIPpresolSetData(presol, NULL);
    1751
    1752 return SCIP_OKAY;
    1753}
    1754
    1755/** initialization method of presolver (called after problem was transformed) */
    1756static
    1757SCIP_DECL_PRESOLINIT(presolInitDualsparsify)
    1758{
    1759 SCIP_PRESOLDATA* presoldata;
    1760
    1761 /* set the counters in the init (and not in the initpre) callback such that they persist across restarts */
    1762 presoldata = SCIPpresolGetData(presol);
    1763 presoldata->nfailures = 0;
    1764 presoldata->nwaitingcalls = 0;
    1765 presoldata->naggregated = 0;
    1766
    1767 return SCIP_OKAY;
    1768}
    1769
    1770/** creates the dualsparsify presolver and includes it in SCIP */
    1772 SCIP* scip /**< SCIP data structure */
    1773 )
    1774{
    1775 SCIP_PRESOLDATA* presoldata;
    1776 SCIP_PRESOL* presol;
    1777
    1778 /* create dualsparsify presolver data */
    1779 SCIP_CALL( SCIPallocBlockMemory(scip, &presoldata) );
    1780
    1781 /* include presolver */
    1783 PRESOL_TIMING, presolExecDualsparsify, presoldata) );
    1784
    1785 SCIP_CALL( SCIPsetPresolCopy(scip, presol, presolCopyDualsparsify) );
    1786 SCIP_CALL( SCIPsetPresolFree(scip, presol, presolFreeDualsparsify) );
    1787 SCIP_CALL( SCIPsetPresolInit(scip, presol, presolInitDualsparsify) );
    1788
    1790 "presolving/dualsparsify/enablecopy",
    1791 "should dualsparsify presolver be copied to sub-SCIPs?",
    1792 &presoldata->enablecopy, TRUE, DEFAULT_ENABLECOPY, NULL, NULL) );
    1793
    1795 "presolving/dualsparsify/preserveintcoefs",
    1796 "should we forbid cancellations that destroy integer coefficients?",
    1797 &presoldata->preserveintcoefs, TRUE, DEFAULT_PRESERVEINTCOEFS, NULL, NULL) );
    1798
    1800 "presolving/dualsparsify/preservegoodlocks",
    1801 "should we preserve good locked properties of variables (at most one lock in one direction)?",
    1802 &presoldata->preservegoodlocks, TRUE, DEFAULT_PRESERVEGOODLOCKS, NULL, NULL) );
    1803
    1805 "presolving/dualsparsify/maxcontfillin",
    1806 "maximal fillin for continuous variables (-1: unlimited)",
    1807 &presoldata->maxcontfillin, FALSE, DEFAULT_MAX_CONT_FILLIN, -1, INT_MAX, NULL, NULL) );
    1808
    1810 "presolving/dualsparsify/maxbinfillin",
    1811 "maximal fillin for binary variables (-1: unlimited)",
    1812 &presoldata->maxbinfillin, FALSE, DEFAULT_MAX_BIN_FILLIN, -1, INT_MAX, NULL, NULL) );
    1813
    1815 "presolving/dualsparsify/maxintfillin",
    1816 "maximal fillin for integer variables including binaries (-1: unlimited)",
    1817 &presoldata->maxintfillin, FALSE, DEFAULT_MAX_INT_FILLIN, -1, INT_MAX, NULL, NULL) );
    1818
    1820 "presolving/dualsparsify/maxconsiderednonzeros",
    1821 "maximal number of considered nonzeros within one column (-1: no limit)",
    1822 &presoldata->maxconsiderednonzeros, TRUE, DEFAULT_MAXCONSIDEREDNONZEROS, -1, INT_MAX, NULL, NULL) );
    1823
    1825 "presolving/dualsparsify/mineliminatednonzeros",
    1826 "minimal eliminated nonzeros within one column if we need to add a constraint to the problem",
    1827 &presoldata->mineliminatednonzeros, FALSE, DEFAULT_MINELIMINATEDNONZEROS, 0, INT_MAX, NULL, NULL) );
    1828
    1830 "presolving/dualsparsify/maxretrievefac",
    1831 "limit on the number of useless vs. useful hashtable retrieves as a multiple of the number of constraints",
    1832 &presoldata->maxretrievefac, TRUE, DEFAULT_MAXRETRIEVEFAC, 0.0, SCIP_REAL_MAX, NULL, NULL) );
    1833
    1835 "presolving/dualsparsify/waitingfac",
    1836 "number of calls to wait until next execution as a multiple of the number of useless calls",
    1837 &presoldata->waitingfac, TRUE, DEFAULT_WAITINGFAC, 0.0, SCIP_REAL_MAX, NULL, NULL) );
    1838
    1839 return SCIP_OKAY;
    1840}
    SCIP_VAR * a
    Definition: circlepacking.c:66
    SCIP_VAR ** b
    Definition: circlepacking.c:65
    Constraint handler for linear constraints in their most general form, .
    methods for debugging
    #define SCIPdebugGetSolVal(scip, var, val)
    Definition: debug.h:312
    #define SCIPdebugAddSolVal(scip, var, val)
    Definition: debug.h:311
    #define NULL
    Definition: def.h:248
    #define SCIP_MAXSTRLEN
    Definition: def.h:269
    #define COPYSIGN
    Definition: def.h:239
    #define SCIP_Longint
    Definition: def.h:141
    #define SCIP_REAL_MAX
    Definition: def.h:158
    #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 REALABS(x)
    Definition: def.h:182
    #define SCIP_CALL(x)
    Definition: def.h:355
    SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:759
    SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_prob.c:1907
    SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:3274
    void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
    Definition: misc.c:2348
    #define SCIPhashThree(a, b, c)
    Definition: pub_misc.h:570
    SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
    Definition: misc.c:2298
    void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
    Definition: misc.c:2596
    void SCIPhashtableRemoveAll(SCIP_HASHTABLE *hashtable)
    Definition: misc.c:2743
    static INLINE uint32_t SCIPrealHashCode(double x)
    Definition: pub_misc.h:593
    SCIP_RETCODE SCIPhashtableRemove(SCIP_HASHTABLE *hashtable, void *element)
    Definition: misc.c:2665
    SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
    Definition: misc.c:2535
    void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:225
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:83
    SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:139
    SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:57
    void SCIPswapPointers(void **pointer1, void **pointer2)
    Definition: misc.c:10511
    SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    BMS_BLKMEM * SCIPblkmem(SCIP *scip)
    Definition: scip_mem.c:57
    int SCIPcalcMemGrowSize(SCIP *scip, int num)
    Definition: scip_mem.c:139
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPreallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:128
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPduplicateBufferArray(scip, ptr, source, num)
    Definition: scip_mem.h:132
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPfreeBufferArrayNull(scip, ptr)
    Definition: scip_mem.h:137
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    void SCIPpresolSetData(SCIP_PRESOL *presol, SCIP_PRESOLDATA *presoldata)
    Definition: presol.c:538
    SCIP_PRESOLDATA * SCIPpresolGetData(SCIP_PRESOL *presol)
    Definition: presol.c:528
    SCIP_RETCODE SCIPsetPresolInit(SCIP *scip, SCIP_PRESOL *presol, SCIP_DECL_PRESOLINIT((*presolinit)))
    Definition: scip_presol.c:180
    SCIP_RETCODE SCIPsetPresolFree(SCIP *scip, SCIP_PRESOL *presol, SCIP_DECL_PRESOLFREE((*presolfree)))
    Definition: scip_presol.c:164
    SCIP_RETCODE SCIPsetPresolCopy(SCIP *scip, SCIP_PRESOL *presol, SCIP_DECL_PRESOLCOPY((*presolcopy)))
    Definition: scip_presol.c:148
    SCIP_RETCODE SCIPincludePresolBasic(SCIP *scip, SCIP_PRESOL **presolptr, const char *name, const char *desc, int priority, int maxrounds, SCIP_PRESOLTIMING timing, SCIP_DECL_PRESOLEXEC((*presolexec)), SCIP_PRESOLDATA *presoldata)
    Definition: scip_presol.c:113
    const char * SCIPpresolGetName(SCIP_PRESOL *presol)
    Definition: presol.c:625
    int SCIPgetNRuns(SCIP *scip)
    SCIP_Real SCIPgetSolvingTime(SCIP *scip)
    Definition: scip_timing.c:378
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisSumZero(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
    Definition: var.c:23514
    SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
    Definition: var.c:23478
    SCIP_Bool SCIPdoNotAggr(SCIP *scip)
    Definition: scip_var.c:10909
    SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
    Definition: var.c:23498
    SCIP_Bool SCIPdoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:10942
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24142
    SCIP_RETCODE SCIPcreateVarImpl(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_IMPLINTTYPE impltype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
    Definition: scip_var.c:225
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    SCIP_RETCODE SCIPmultiaggregateVar(SCIP *scip, SCIP_VAR *var, int naggvars, SCIP_VAR **aggvars, SCIP_Real *scalars, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
    Definition: scip_var.c:10834
    SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
    Definition: scip_var.c:1887
    SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
    Definition: var.c:23490
    SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
    Definition: var.c:23524
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24120
    SCIP_Bool SCIPisVarAggrCoefAcceptable(SCIP *scip, SCIP_VAR *var, SCIP_Real scalar)
    Definition: scip_var.c:10962
    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
    SCIP_Bool SCIPmatrixUplockConflict(SCIP_MATRIX *matrix, int col)
    Definition: matrix.c:2201
    int SCIPmatrixGetRowNMinActNegInf(SCIP_MATRIX *matrix, int row)
    Definition: matrix.c:2141
    int * SCIPmatrixGetColIdxPtr(SCIP_MATRIX *matrix, int col)
    Definition: matrix.c:1873
    int SCIPmatrixGetRowNNonzs(SCIP_MATRIX *matrix, int row)
    Definition: matrix.c:2013
    int SCIPmatrixGetColNDownlocks(SCIP_MATRIX *matrix, int col)
    Definition: matrix.c:1941
    int SCIPmatrixGetColNNonzs(SCIP_MATRIX *matrix, int col)
    Definition: matrix.c:1885
    int SCIPmatrixGetColNUplocks(SCIP_MATRIX *matrix, int col)
    Definition: matrix.c:1929
    SCIP_Real SCIPmatrixGetRowMaxActivity(SCIP_MATRIX *matrix, int row)
    Definition: matrix.c:2129
    SCIP_Real SCIPmatrixGetColLb(SCIP_MATRIX *matrix, int col)
    Definition: matrix.c:1918
    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
    int SCIPmatrixGetRowNMinActPosInf(SCIP_MATRIX *matrix, int row)
    Definition: matrix.c:2153
    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_Real SCIPmatrixGetRowMinActivity(SCIP_MATRIX *matrix, int row)
    Definition: matrix.c:2117
    void SCIPmatrixFree(SCIP *scip, SCIP_MATRIX **matrix)
    Definition: matrix.c:1348
    int SCIPmatrixGetRowNMaxActPosInf(SCIP_MATRIX *matrix, int row)
    Definition: matrix.c:2177
    int SCIPmatrixGetRowNMaxActNegInf(SCIP_MATRIX *matrix, int row)
    Definition: matrix.c:2165
    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
    void SCIPmatrixRemoveColumnBounds(SCIP *scip, SCIP_MATRIX *matrix, int col)
    Definition: matrix.c:1459
    SCIP_Real SCIPmatrixGetColUb(SCIP_MATRIX *matrix, int col)
    Definition: matrix.c:1907
    memory allocation routines
    static SCIP_RETCODE cancelCol(SCIP *scip, SCIP_MATRIX *matrix, SCIP_PRESOLDATA *presoldata, SCIP_HASHTABLE *pairtable, SCIP_Bool *ishashingcols, SCIP_VAR **vars, SCIP_Bool *isblockedvar, int colidx, int maxcontfillin, int maxintfillin, int maxbinfillin, int maxconsiderednonzeros, SCIP_Bool preserveintcoefs, SCIP_Longint *nuseless, int *nchgcoefs, int *ncanceled, int *nfillin, SCIP_Bool isaddedcons)
    #define DEFAULT_MAXCONSIDEREDNONZEROS
    SCIP_RETCODE SCIPincludePresolDualsparsify(SCIP *scip)
    static SCIP_DECL_PRESOLINIT(presolInitDualsparsify)
    static SCIP_DECL_PRESOLFREE(presolFreeDualsparsify)
    #define PRESOL_NAME
    #define MAXSCALE
    #define DEFAULT_MAX_INT_FILLIN
    static void getVarBoundsOfRow(SCIP *scip, SCIP_MATRIX *matrix, int col, int row, SCIP_Real val, SCIP_Real *rowub, SCIP_Bool *ubfound, SCIP_Real *rowlb, SCIP_Bool *lbfound)
    static SCIP_RETCODE aggregation(SCIP *scip, SCIP_MATRIX *matrix, SCIP_PRESOLDATA *presoldata, SCIP_VAR **vars, int colidx1, int colidx2, SCIP_Bool isimpliedfree, SCIP_Real weight1)
    static void updateFailureStatistic(SCIP_PRESOLDATA *presoldata, SCIP_Bool success)
    #define DEFAULT_PRESERVEGOODLOCKS
    #define DEFAULT_MINELIMINATEDNONZEROS
    #define PRESOL_PRIORITY
    static SCIP_Real getMinActivitySingleRowWithoutCol(SCIP *scip, SCIP_MATRIX *matrix, int row, int col)
    #define DEFAULT_ENABLECOPY
    static SCIP_DECL_PRESOLEXEC(presolExecDualsparsify)
    static SCIP_DECL_PRESOLCOPY(presolCopyDualsparsify)
    #define DEFAULT_MAX_CONT_FILLIN
    #define DEFAULT_WAITINGFAC
    static void getImpliedBounds(SCIP *scip, SCIP_MATRIX *matrix, int col, SCIP_Bool *ubimplied, SCIP_Bool *lbimplied)
    #define DEFAULT_MAXRETRIEVEFAC
    static SCIP_DECL_HASHKEYVAL(consPairHashval)
    static SCIP_DECL_HASHKEYEQ(consPairsEqual)
    #define PRESOL_MAXROUNDS
    #define PRESOL_TIMING
    #define DEFAULT_MAX_BIN_FILLIN
    static SCIP_Real getMaxActivitySingleRowWithoutCol(SCIP *scip, SCIP_MATRIX *matrix, int row, int col)
    static void getMinMaxActivityResiduals(SCIP *scip, SCIP_MATRIX *matrix, int col, int row, SCIP_Real val, SCIP_Real *minresactivity, SCIP_Real *maxresactivity, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
    #define DEFAULT_PRESERVEINTCOEFS
    #define PRESOL_DESC
    cancel nonzeros of the constraint matrix based on the columns
    public methods for managing constraints
    public methods for matrix
    public methods for message output
    #define SCIPdebugPrintCons(x, y, z)
    Definition: pub_message.h:102
    public data structures and miscellaneous methods
    methods for sorting joint arrays of various types
    public methods for presolvers
    public methods for problem variables
    public methods for constraint handler plugins and constraints
    general public methods
    public methods for memory management
    public methods for message handling
    public methods for nonlinear relaxation
    public methods for numerical tolerances
    public methods for SCIP parameter handling
    public methods for presolving plugins
    public methods for variable pricer plugins
    public methods for global and local (sub)problems
    public methods for the probing mode
    public methods for querying solving statistics
    public methods for timing
    public methods for SCIP variables
    @ SCIP_VERBLEVEL_HIGH
    Definition: type_message.h:61
    struct SCIP_PresolData SCIP_PRESOLDATA
    Definition: type_presol.h:51
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_CUTOFF
    Definition: type_result.h:48
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_SUCCESS
    Definition: type_result.h:58
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    enum SCIP_ImplintType SCIP_IMPLINTTYPE
    Definition: type_var.h:117
    @ SCIP_IMPLINTTYPE_NONE
    Definition: type_var.h:90
    @ SCIP_IMPLINTTYPE_WEAK
    Definition: type_var.h:91
    @ SCIP_VARTYPE_INTEGER
    Definition: type_var.h:65
    @ SCIP_VARTYPE_CONTINUOUS
    Definition: type_var.h:71
    enum SCIP_Vartype SCIP_VARTYPE
    Definition: type_var.h:73