Scippy

    SCIP

    Solving Constraint Integer Programs

    presol_redvub.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_redvub.c
    26 * @ingroup DEFPLUGINS_PRESOL
    27 * @brief remove redundant variable upper bound constraints
    28 * @author Dieter Weninger
    29 *
    30 * This presolver looks for dominating variable bound constraints
    31 * on the same continuous variable and discards them. For example let x be a
    32 * continuous variable and y, y' are binary variables. In addition, let two variable
    33 * upper bound constraints ax - by <= e and cx - dy' <= f are given. If
    34 * ax - by <= e implies cx - dy' <= f, then we can remove the second constraint
    35 * and substitute/aggregate y' := y. The same can be done with variable lower
    36 * bound constraints.
    37 *
    38 */
    39
    40/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    41
    43#include "scip/presol_redvub.h"
    44#include "scip/pub_matrix.h"
    45#include "scip/pub_message.h"
    46#include "scip/pub_presol.h"
    47#include "scip/pub_var.h"
    48#include "scip/scip_cons.h"
    49#include "scip/scip_general.h"
    50#include "scip/scip_mem.h"
    51#include "scip/scip_message.h"
    52#include "scip/scip_nlp.h"
    53#include "scip/scip_numerics.h"
    54#include "scip/scip_presol.h"
    55#include "scip/scip_pricer.h"
    56#include "scip/scip_prob.h"
    57#include "scip/scip_probing.h"
    58#include "scip/scip_var.h"
    59
    60#define PRESOL_NAME "redvub"
    61#define PRESOL_DESC "detect redundant variable bound constraints"
    62#define PRESOL_PRIORITY -9000000 /**< priority of the presolver (>= 0: before, < 0: after constraint handlers) */
    63#define PRESOL_MAXROUNDS 0 /**< maximal number of presolving rounds the presolver participates in (-1: no limit) */
    64#define PRESOL_TIMING SCIP_PRESOLTIMING_EXHAUSTIVE /* timing of the presolver (fast, medium, or exhaustive) */
    65
    66#define MAXPAIRCOMP 1000 /**< maximal number of pairwise comparisons */
    67
    68/*
    69 * Local methods
    70 */
    71
    72/** verify if the constraint is a variable upper bound constraint */
    73static
    75 SCIP* scip, /**< SCIP main data structure */
    76 SCIP_MATRIX* matrix, /**< matrix instance */
    77 int row, /**< row index */
    78 SCIP_Real* lowthreshold, /**< low switching threshold */
    79 SCIP_Real* highthreshold, /**< high switching threshold */
    80 int* conidx, /**< variable index of continuous variable */
    81 int* binidx /**< variable index of binary variable */
    82 )
    83{
    84 SCIP_Real* valpnt;
    85 int* rowpnt;
    86 SCIP_Bool isvub;
    87
    88 assert(scip != NULL);
    89 assert(matrix != NULL);
    90 assert(0 <= row && row < SCIPmatrixGetNRows(matrix));
    91 assert(lowthreshold != NULL);
    92 assert(highthreshold != NULL);
    93 assert(conidx != NULL);
    94 assert(binidx != NULL);
    95
    96 isvub = FALSE;
    97
    98 if( SCIPmatrixGetRowNNonzs(matrix, row) == 2 && SCIPmatrixIsRowRhsInfinity(matrix, row) )
    99 {
    100 SCIP_VARTYPE type1;
    101 SCIP_VARTYPE type2;
    102 int idx1;
    103 int idx2;
    104 SCIP_VAR* var1;
    105 SCIP_VAR* var2;
    106 SCIP_Real val1;
    107 SCIP_Real val2;
    108
    109 rowpnt = SCIPmatrixGetRowIdxPtr(matrix, row);
    110 valpnt = SCIPmatrixGetRowValPtr(matrix, row);
    111
    112 idx1 = *rowpnt;
    113 val1 = *valpnt;
    114 var1 = SCIPmatrixGetVar(matrix, idx1);
    115 type1 = SCIPvarGetType(var1);
    116
    117 rowpnt++;
    118 valpnt++;
    119
    120 idx2 = *rowpnt;
    121 val2 = *valpnt;
    122 var2 = SCIPmatrixGetVar(matrix, idx2);
    123 type2 = SCIPvarGetType(var2);
    124
    126 return isvub;
    127
    128 /* we claim that the vub has the structure ax + cy >= b
    129 * with a<0, c>0, x continuous, x>=0, y binary and obj(y)>=0
    130 */
    131 if( (type1 == SCIP_VARTYPE_CONTINUOUS && type2 == SCIP_VARTYPE_BINARY)
    132 && val1 < 0.0 && val2 > 0.0 && SCIPisGE(scip, SCIPvarGetLbGlobal(var1), 0.0)
    133 && SCIPisGE(scip, SCIPvarGetObj(var2), 0.0) )
    134 {
    135 *lowthreshold = SCIPmatrixGetRowLhs(matrix, row) / val1;
    136 *highthreshold = (SCIPmatrixGetRowLhs(matrix, row) - val2) / val1;
    137 *conidx = idx1;
    138 *binidx = idx2;
    139 isvub = TRUE;
    140 }
    141 else if( (type1 == SCIP_VARTYPE_BINARY && type2 == SCIP_VARTYPE_CONTINUOUS)
    142 && val1 > 0.0 && val2 < 0.0 && SCIPisGE(scip, SCIPvarGetLbGlobal(var2), 0.0)
    143 && SCIPisGE(scip, SCIPvarGetObj(var1), 0.0) )
    144 {
    145 *lowthreshold = SCIPmatrixGetRowLhs(matrix, row) / val2;
    146 *highthreshold = (SCIPmatrixGetRowLhs(matrix, row) - val1) / val2;
    147 *conidx = idx2;
    148 *binidx = idx1;
    149 isvub = TRUE;
    150 }
    151 }
    152
    153 return isvub;
    154}
    155
    156/** verify if the constraint is a variable lower bound constraint */
    157static
    159 SCIP* scip, /**< SCIP main data structure */
    160 SCIP_MATRIX* matrix, /**< matrix instance */
    161 int row, /**< row index */
    162 SCIP_Real* lowthreshold, /**< low switching threshold */
    163 SCIP_Real* highthreshold, /**< high switching threshold */
    164 int* conidx, /**< variable index of continuous variable */
    165 int* binidx /**< variable index of binary variable */
    166 )
    167{
    168 SCIP_Real* valpnt;
    169 int* rowpnt;
    170 SCIP_Bool isvlb;
    171
    172 assert(scip != NULL);
    173 assert(matrix != NULL);
    174 assert(0 <= row && row < SCIPmatrixGetNRows(matrix));
    175 assert(lowthreshold != NULL);
    176 assert(highthreshold != NULL);
    177 assert(conidx != NULL);
    178 assert(binidx != NULL);
    179
    180 isvlb = FALSE;
    181
    182 if( SCIPmatrixGetRowNNonzs(matrix, row) == 2 && SCIPmatrixIsRowRhsInfinity(matrix, row) )
    183 {
    184 SCIP_VARTYPE type1;
    185 SCIP_VARTYPE type2;
    186 int idx1;
    187 int idx2;
    188 SCIP_VAR* var1;
    189 SCIP_VAR* var2;
    190 SCIP_Real val1;
    191 SCIP_Real val2;
    192
    193 rowpnt = SCIPmatrixGetRowIdxPtr(matrix, row);
    194 valpnt = SCIPmatrixGetRowValPtr(matrix, row);
    195
    196 idx1 = *rowpnt;
    197 val1 = *valpnt;
    198 var1 = SCIPmatrixGetVar(matrix, idx1);
    199 type1 = SCIPvarGetType(var1);
    200
    201 rowpnt++;
    202 valpnt++;
    203
    204 idx2 = *rowpnt;
    205 val2 = *valpnt;
    206 var2 = SCIPmatrixGetVar(matrix, idx2);
    207 type2 = SCIPvarGetType(var2);
    208
    210 return isvlb;
    211
    212 /* we claim that the vlb has the structure ax + cy >= b
    213 * with a>0, c<0, x continuous, x>=0, y binary and obj(y)>=0
    214 */
    215 if( (type1 == SCIP_VARTYPE_CONTINUOUS && type2 == SCIP_VARTYPE_BINARY)
    216 && val1 > 0.0 && val2 < 0.0 && SCIPisGE(scip, SCIPvarGetLbGlobal(var1), 0.0)
    217 && SCIPisGE(scip, SCIPvarGetObj(var2), 0.0) )
    218 {
    219 *lowthreshold = SCIPmatrixGetRowLhs(matrix, row) / val1;
    220 *highthreshold = (SCIPmatrixGetRowLhs(matrix, row) - val2) / val1;
    221 *conidx = idx1;
    222 *binidx = idx2;
    223 isvlb = TRUE;
    224 }
    225 else if( (type1 == SCIP_VARTYPE_BINARY && type2 == SCIP_VARTYPE_CONTINUOUS)
    226 && val1 < 0.0 && val2 > 0.0 && SCIPisGE(scip, SCIPvarGetLbGlobal(var2), 0.0)
    227 && SCIPisGE(scip, SCIPvarGetObj(var1), 0.0) )
    228 {
    229 *lowthreshold = SCIPmatrixGetRowLhs(matrix, row) / val2;
    230 *highthreshold = (SCIPmatrixGetRowLhs(matrix, row) - val1) / val2;
    231 *conidx = idx2;
    232 *binidx = idx1;
    233 isvlb = TRUE;
    234 }
    235 }
    236
    237 return isvlb;
    238}
    239
    240
    241/** searches for variable upper bound constraints on the same continuous variable with a dominance relation */
    242static
    244 SCIP* scip, /**< SCIP main data structure */
    245 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
    246 int nvubs, /**< number of vubs */
    247 int* vubs, /**< row indices of the vubs */
    248 SCIP_Real* lowthresholds, /**< low switching thresholds */
    249 SCIP_Real* highthresholds, /**< high switching thresholds */
    250 int* conidxs, /**< variable indexes of continuous variable */
    251 int* binidxs, /**< variable indexes of binary variable */
    252 int* nvaragg, /**< number of variables for aggregation */
    253 SCIP_Bool* isvartoagg, /**< flags indicating if variable could be aggregated */
    254 SCIP_VAR** aggvars, /**< pointers to the variables by which the aggregation should be done */
    255 int* ndeletecons, /**< number of deleteable constraints */
    256 SCIP_Bool* deletecons /**< flags which constraints could be deleted */
    257 )
    258{
    259 int i;
    260 int j;
    261 SCIP_Bool uselinearscan;
    262
    263 assert(scip != NULL);
    264 assert(matrix != NULL);
    265 assert(vubs != NULL);
    266 assert(nvubs >= 2);
    267 assert(lowthresholds != NULL);
    268 assert(highthresholds != NULL);
    269 assert(conidxs != NULL);
    270 assert(binidxs != NULL);
    271 assert(nvaragg != NULL);
    272 assert(isvartoagg != NULL);
    273 assert(aggvars != NULL);
    274 assert(ndeletecons != NULL);
    275 assert(deletecons != NULL);
    276
    277 /* use pairwise comparison only for a small number of vub constraints */
    278 if( nvubs >= MAXPAIRCOMP )
    279 uselinearscan = TRUE;
    280 else
    281 uselinearscan = FALSE;
    282
    283 for( i = 0; i < nvubs; i++ )
    284 {
    285 for( j = i+1; j < nvubs; j++ )
    286 {
    287 SCIP_VAR* var1;
    288 SCIP_VAR* var2;
    289
    290 if( !SCIPisEQ(scip, lowthresholds[i], lowthresholds[j]) )
    291 continue;
    292
    293 var1 = SCIPmatrixGetVar(matrix, binidxs[i]);
    294 var2 = SCIPmatrixGetVar(matrix, binidxs[j]);
    295
    296 /* make sure that the binary variables switch synchronously */
    297 if((SCIPmatrixGetColNDownlocks(matrix, binidxs[j]) == 1 &&
    298 SCIPmatrixGetColNDownlocks(matrix, binidxs[i]) == 1 &&
    299 SCIPmatrixGetColNUplocks(matrix, binidxs[j]) == 0 &&
    300 SCIPmatrixGetColNUplocks(matrix, binidxs[i]) == 0) ||
    301 (SCIPvarsHaveCommonClique(var1, FALSE, var2, TRUE, TRUE) &&
    302 SCIPvarsHaveCommonClique(var1, TRUE, var2, FALSE, TRUE)) )
    303 {
    304 if( SCIPisLE(scip, highthresholds[i], highthresholds[j]) )
    305 {
    306#ifdef SCIP_DEBUG
    307 SCIPdebugMsg(scip, "Aggregate variable %s by %s\n", SCIPvarGetName(var2), SCIPvarGetName(var1));
    308 SCIPdebugMsg(scip, "Delete variable upper bound constraint:\n");
    309 SCIP_CALL( SCIPprintCons(scip, SCIPmatrixGetCons(matrix, vubs[j]), NULL) );
    310 SCIPinfoMessage(scip, NULL, "\n");
    311#endif
    312
    313 isvartoagg[binidxs[j]] = TRUE;
    314 aggvars[binidxs[j]] = SCIPmatrixGetVar(matrix, binidxs[i]);
    315 (*nvaragg)++;
    316
    317 deletecons[vubs[j]] = TRUE;
    318 (*ndeletecons)++;
    319 }
    320 else
    321 {
    322 assert(SCIPisGT(scip, highthresholds[i], highthresholds[j]));
    323#ifdef SCIP_DEBUG
    324 SCIPdebugMsg(scip, "Aggregate variable %s by %s\n", SCIPvarGetName(var1), SCIPvarGetName(var2));
    325 SCIPdebugMsg(scip, "Delete variable upper bound constraint:\n");
    326 SCIP_CALL( SCIPprintCons(scip, SCIPmatrixGetCons(matrix, vubs[i]), NULL) );
    327 SCIPinfoMessage(scip, NULL, "\n");
    328#endif
    329
    330 isvartoagg[binidxs[i]] = TRUE;
    331 aggvars[binidxs[i]] = SCIPmatrixGetVar(matrix, binidxs[j]);
    332 (*nvaragg)++;
    333
    334 deletecons[vubs[i]] = TRUE;
    335 (*ndeletecons)++;
    336 }
    337 }
    338
    339 if( uselinearscan )
    340 break;
    341 }
    342 }
    343
    344 return SCIP_OKAY;
    345}
    346
    347/** searches for variable lower bound constraints on the same continuous variable with a dominance relation */
    348static
    350 SCIP* scip, /**< SCIP main data structure */
    351 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
    352 int nvlbs, /**< number of vlbs */
    353 int* vlbs, /**< row indices of the vlbs */
    354 SCIP_Real* lowthresholds, /**< low switching thresholds */
    355 SCIP_Real* highthresholds, /**< high switching thresholds */
    356 int* conidxs, /**< variable indexes of continuous variable */
    357 int* binidxs, /**< variable indexes of binary variable */
    358 int* nvaragg, /**< number of variables for aggregation */
    359 SCIP_Bool* isvartoagg, /**< flags indicating if variable could be aggregated */
    360 SCIP_VAR** aggvars, /**< pointers to the variables by which the aggregation should be done */
    361 int* ndeletecons, /**< number of deleteable constraints */
    362 SCIP_Bool* deletecons /**< flags which constraints could be deleted */
    363
    364 )
    365{
    366 int i;
    367 int j;
    368 SCIP_Bool uselinearscan;
    369
    370 assert(scip != NULL);
    371 assert(matrix != NULL);
    372 assert(vlbs != NULL);
    373 assert(nvlbs >= 2);
    374 assert(lowthresholds != NULL);
    375 assert(highthresholds != NULL);
    376 assert(conidxs != NULL);
    377 assert(binidxs != NULL);
    378 assert(nvaragg != NULL);
    379 assert(isvartoagg != NULL);
    380 assert(aggvars != NULL);
    381 assert(ndeletecons != NULL);
    382 assert(deletecons != NULL);
    383
    384 /* use pairwise comparison only for a small number of vlb constraints */
    385 if( nvlbs >= MAXPAIRCOMP )
    386 uselinearscan = TRUE;
    387 else
    388 uselinearscan = FALSE;
    389
    390 for( i = 0; i < nvlbs; i++ )
    391 {
    392 for( j = i+1; j < nvlbs; j++ )
    393 {
    394 SCIP_VAR* var1;
    395 SCIP_VAR* var2;
    396
    397 if( !SCIPisEQ(scip, lowthresholds[i], lowthresholds[j]) )
    398 continue;
    399
    400 var1 = SCIPmatrixGetVar(matrix, binidxs[i]);
    401 var2 = SCIPmatrixGetVar(matrix, binidxs[j]);
    402
    403 /* make sure that the binary variables switch synchronously */
    404 if((SCIPmatrixGetColNUplocks(matrix, binidxs[j]) == 1 &&
    405 SCIPmatrixGetColNUplocks(matrix, binidxs[i]) == 1 &&
    406 SCIPmatrixGetColNDownlocks(matrix, binidxs[j]) == 0 &&
    407 SCIPmatrixGetColNDownlocks(matrix, binidxs[i]) == 0) ||
    408 (SCIPvarsHaveCommonClique(var1, FALSE, var2, TRUE, TRUE) &&
    409 SCIPvarsHaveCommonClique(var1, TRUE, var2, FALSE, TRUE)) )
    410 {
    411 if( SCIPisGE(scip, highthresholds[i], highthresholds[j]) )
    412 {
    413#ifdef SCIP_DEBUG
    414 SCIPdebugMsg(scip, "Aggregate variable %s by %s\n", SCIPvarGetName(var2), SCIPvarGetName(var1));
    415 SCIPdebugMsg(scip, "Delete variable lower bound constraint:\n");
    416 SCIP_CALL( SCIPprintCons(scip, SCIPmatrixGetCons(matrix, vlbs[j]), NULL) );
    417 SCIPinfoMessage(scip, NULL, "\n");
    418#endif
    419
    420 isvartoagg[binidxs[j]] = TRUE;
    421 aggvars[binidxs[j]] = SCIPmatrixGetVar(matrix, binidxs[i]);
    422 (*nvaragg)++;
    423
    424 deletecons[vlbs[j]] = TRUE;
    425 (*ndeletecons)++;
    426 }
    427 else
    428 {
    429 assert(SCIPisLT(scip, highthresholds[i], highthresholds[j]));
    430#ifdef SCIP_DEBUG
    431 SCIPdebugMsg(scip, "Aggregate variable %s by %s\n", SCIPvarGetName(var1), SCIPvarGetName(var2));
    432 SCIPdebugMsg(scip, "Delete variable lower bound constraint:\n");
    433 SCIP_CALL( SCIPprintCons(scip, SCIPmatrixGetCons(matrix, vlbs[i]), NULL) );
    434 SCIPinfoMessage(scip, NULL, "\n");
    435#endif
    436
    437 isvartoagg[binidxs[i]] = TRUE;
    438 aggvars[binidxs[i]] = SCIPmatrixGetVar(matrix, binidxs[j]);
    439 (*nvaragg)++;
    440
    441 deletecons[vlbs[i]] = TRUE;
    442 (*ndeletecons)++;
    443 }
    444 }
    445
    446 if( uselinearscan )
    447 break;
    448 }
    449 }
    450
    451 return SCIP_OKAY;
    452}
    453
    454/** find variable aggregations and redundant variable bound constraints */
    455static
    457 SCIP* scip, /**< SCIP main data structure */
    458 SCIP_MATRIX* matrix, /**< constraint matrix */
    459 int* nvaragg, /**< number of redundant variables */
    460 SCIP_Bool* isvartoagg, /**< flags indicating which variables could be substituted/aggregated */
    461 SCIP_VAR** aggvars, /**< pointers to the variables by which the aggregation should be done */
    462 int* ndeletecons, /**< number of redundant constraints */
    463 SCIP_Bool* deletecons /**< flags indicating which constraints could be deleted */
    464 )
    465{
    466 int c;
    467 int* colpnt;
    468 int* colend;
    469 int* vbcons;
    470 int nvbcons;
    471 int ncols;
    472 int nrows;
    473 SCIP_Real* lowthresholds;
    474 SCIP_Real* highthresholds;
    475 int* conidxs;
    476 int* binidxs;
    477
    478 ncols = SCIPmatrixGetNColumns(matrix);
    479 nrows = SCIPmatrixGetNRows(matrix);
    480
    481 SCIP_CALL( SCIPallocBufferArray(scip, &binidxs, nrows) );
    482 SCIP_CALL( SCIPallocBufferArray(scip, &conidxs, nrows) );
    483 SCIP_CALL( SCIPallocBufferArray(scip, &lowthresholds, nrows) );
    484 SCIP_CALL( SCIPallocBufferArray(scip, &highthresholds, nrows) );
    485 SCIP_CALL( SCIPallocBufferArray(scip, &vbcons, nrows) );
    486
    487 for( c = 0; c < ncols; c++ )
    488 {
    489 SCIP_VAR* var;
    490
    491 var = SCIPmatrixGetVar(matrix, c);
    492
    493 if( SCIPvarIsIntegral(var) )
    494 continue;
    495
    496 /* search vubs per variable */
    497 nvbcons = 0;
    498 colpnt = SCIPmatrixGetColIdxPtr(matrix, c);
    499 colend = colpnt + SCIPmatrixGetColNNonzs(matrix, c);
    500 for( ; (colpnt < colend); colpnt++ )
    501 {
    502 SCIP_Real lowthreshold;
    503 SCIP_Real highthreshold;
    504 int conidx;
    505 int binidx;
    506
    507 if( isVub(scip, matrix, *colpnt, &lowthreshold, &highthreshold, &conidx, &binidx) )
    508 {
    509 vbcons[nvbcons] = *colpnt;
    510 lowthresholds[nvbcons] = lowthreshold;
    511 highthresholds[nvbcons] = highthreshold;
    512 conidxs[nvbcons] = conidx;
    513 binidxs[nvbcons] = binidx;
    514 nvbcons++;
    515 }
    516 }
    517 if( nvbcons >= 2 )
    518 {
    519 SCIP_CALL( detectDominatingVubs(scip, matrix, nvbcons, vbcons,
    520 lowthresholds, highthresholds, conidxs, binidxs,
    521 nvaragg, isvartoagg, aggvars, ndeletecons, deletecons) );
    522 }
    523
    524 /* search vlbs per variable */
    525 nvbcons = 0;
    526 colpnt = SCIPmatrixGetColIdxPtr(matrix, c);
    527 colend = colpnt + SCIPmatrixGetColNNonzs(matrix, c);
    528 for( ; (colpnt < colend); colpnt++ )
    529 {
    530 SCIP_Real lowthreshold;
    531 SCIP_Real highthreshold;
    532 int conidx;
    533 int binidx;
    534
    535 if( isVlb(scip, matrix, *colpnt, &lowthreshold, &highthreshold, &conidx, &binidx) )
    536 {
    537 vbcons[nvbcons] = *colpnt;
    538 lowthresholds[nvbcons] = lowthreshold;
    539 highthresholds[nvbcons] = highthreshold;
    540 conidxs[nvbcons] = conidx;
    541 binidxs[nvbcons] = binidx;
    542 nvbcons++;
    543 }
    544 }
    545 if( nvbcons >= 2 )
    546 {
    547 SCIP_CALL( detectDominatingVlbs(scip, matrix, nvbcons, vbcons,
    548 lowthresholds, highthresholds, conidxs, binidxs,
    549 nvaragg, isvartoagg, aggvars, ndeletecons, deletecons) );
    550 }
    551 }
    552
    553 SCIPfreeBufferArray(scip, &vbcons);
    554 SCIPfreeBufferArray(scip, &highthresholds);
    555 SCIPfreeBufferArray(scip, &lowthresholds);
    556 SCIPfreeBufferArray(scip, &conidxs);
    557 SCIPfreeBufferArray(scip, &binidxs);
    558
    559 return SCIP_OKAY;
    560}
    561
    562/*
    563 * Callback methods of presolver
    564 */
    565
    566/** copy method for presolver plugins (called when SCIP copies plugins) */
    567static
    568SCIP_DECL_PRESOLCOPY(presolCopyRedvub)
    569{ /*lint --e{715}*/
    570 assert(scip != NULL);
    571 assert(presol != NULL);
    572 assert(strcmp(SCIPpresolGetName(presol), PRESOL_NAME) == 0);
    573
    574 /* call inclusion method of presolver */
    576
    577 return SCIP_OKAY;
    578}
    579
    580/** execution method of presolver */
    581static
    582SCIP_DECL_PRESOLEXEC(presolExecRedvub)
    583{ /*lint --e{715}*/
    584 SCIP_MATRIX* matrix;
    585 SCIP_Bool initialized;
    586 SCIP_Bool complete;
    587 SCIP_Bool infeasible;
    588
    589 assert(result != NULL);
    590 *result = SCIP_DIDNOTRUN;
    591
    593 return SCIP_OKAY;
    594
    596 return SCIP_OKAY;
    597
    598 *result = SCIP_DIDNOTFIND;
    599
    600 matrix = NULL;
    601 SCIP_CALL( SCIPmatrixCreate(scip, &matrix, TRUE, &initialized, &complete, &infeasible,
    602 naddconss, ndelconss, nchgcoefs, nchgbds, nfixedvars) );
    603
    604 /* if infeasibility was detected during matrix creation, return here */
    605 if( infeasible )
    606 {
    607 if( initialized )
    608 SCIPmatrixFree(scip, &matrix);
    609
    610 *result = SCIP_CUTOFF;
    611 return SCIP_OKAY;
    612 }
    613
    614 if( initialized && complete )
    615 {
    616 int nvaragg;
    617 SCIP_Bool* isvartoagg;
    618 int ndeletecons;
    619 SCIP_Bool* deletecons;
    620 SCIP_VAR** aggvars;
    621 int ncols;
    622 int nrows;
    623
    624 ncols = SCIPmatrixGetNColumns(matrix);
    625 nrows = SCIPmatrixGetNRows(matrix);
    626
    627 nvaragg = 0;
    628 ndeletecons = 0;
    629
    630 SCIP_CALL( SCIPallocBufferArray(scip, &isvartoagg, ncols) );
    631 BMSclearMemoryArray(isvartoagg, ncols);
    632
    633 SCIP_CALL( SCIPallocBufferArray(scip, &deletecons, nrows) );
    634 BMSclearMemoryArray(deletecons, nrows);
    635
    636 SCIP_CALL( SCIPallocBufferArray(scip, &aggvars, ncols) );
    637 BMSclearMemoryArray(aggvars, ncols);
    638
    639 SCIP_CALL( findVarAggrRedVbcons(scip, matrix, &nvaragg, isvartoagg, aggvars, &ndeletecons, deletecons) );
    640
    641 if( nvaragg > 0 )
    642 {
    643 int v;
    644 for( v = 0; v < ncols; v++ )
    645 {
    646 if( isvartoagg[v] )
    647 {
    648 SCIP_Bool redundant;
    649 SCIP_Bool aggregated;
    650
    651 /* substitute/aggregate binary variable */
    652 assert(aggvars[v] != NULL);
    653 SCIP_CALL( SCIPaggregateVars(scip, SCIPmatrixGetVar(matrix,v), aggvars[v], 1.0, -1.0,
    654 0.0, &infeasible, &redundant, &aggregated) );
    655
    656 if( infeasible )
    657 {
    658 SCIPdebugMsg(scip, " -> infeasible aggregation\n");
    659 *result = SCIP_CUTOFF;
    660 return SCIP_OKAY;
    661 }
    662
    663 if( aggregated )
    664 {
    665 (*naggrvars)++;
    666
    667 /* set result pointer */
    668 if( (*result) == SCIP_DIDNOTFIND )
    669 *result = SCIP_SUCCESS;
    670 }
    671 }
    672 }
    673 }
    674
    675 if( ndeletecons > 0 )
    676 {
    677 int r;
    678 for( r = 0; r < nrows; r++ )
    679 {
    680 if( deletecons[r] )
    681 {
    682 SCIP_CONS* cons;
    683
    684 /* remove redundant variable bound constraint */
    685 cons = SCIPmatrixGetCons(matrix, r);
    686 SCIP_CALL( SCIPdelCons(scip, cons) );
    687
    688 (*ndelconss)++;
    689
    690 /* set result pointer */
    691 if( (*result) == SCIP_DIDNOTFIND )
    692 *result = SCIP_SUCCESS;
    693 }
    694 }
    695 }
    696
    697 SCIPfreeBufferArray(scip, &aggvars);
    698 SCIPfreeBufferArray(scip, &deletecons);
    699 SCIPfreeBufferArray(scip, &isvartoagg);
    700 }
    701
    702 SCIPmatrixFree(scip, &matrix);
    703
    704 return SCIP_OKAY;
    705}
    706
    707/*
    708 * presolver specific interface methods
    709 */
    710
    711/** creates the redvub presolver and includes it in SCIP */
    713 SCIP* scip /**< SCIP data structure */
    714 )
    715{
    716 SCIP_PRESOL* presol;
    717
    718 /* include presolver */
    720 PRESOL_TIMING, presolExecRedvub, NULL) );
    721
    722 /* set non fundamental callbacks via setter functions */
    723 SCIP_CALL( SCIPsetPresolCopy(scip, presol, presolCopyRedvub) );
    724
    725 return SCIP_OKAY;
    726}
    SCIP_Real * r
    Definition: circlepacking.c:59
    #define NULL
    Definition: def.h:248
    #define SCIP_Bool
    Definition: def.h:91
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define SCIP_CALL(x)
    Definition: def.h:355
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:759
    SCIP_STAGE SCIPgetStage(SCIP *scip)
    Definition: scip_general.c:444
    int SCIPgetNContVars(SCIP *scip)
    Definition: scip_prob.c:2569
    SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:3420
    void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:208
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_RETCODE SCIPincludePresolRedvub(SCIP *scip)
    SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
    Definition: scip_cons.c:2536
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    SCIP_Bool SCIPisNLPEnabled(SCIP *scip)
    Definition: scip_nlp.c:74
    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 SCIPgetNActivePricers(SCIP *scip)
    Definition: scip_pricer.c:348
    SCIP_Bool SCIPinProbing(SCIP *scip)
    Definition: scip_probing.c:98
    SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
    Definition: var.c:23498
    SCIP_RETCODE SCIPaggregateVars(SCIP *scip, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *redundant, SCIP_Bool *aggregated)
    Definition: scip_var.c:10550
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23900
    SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
    Definition: var.c:23453
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
    Definition: var.c:23490
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24120
    SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
    Definition: var.c:16807
    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
    SCIP_Bool SCIPmatrixIsRowRhsInfinity(SCIP_MATRIX *matrix, int row)
    Definition: matrix.c:2095
    int SCIPmatrixGetColNUplocks(SCIP_MATRIX *matrix, int col)
    Definition: matrix.c:1929
    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_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
    static SCIP_RETCODE detectDominatingVlbs(SCIP *scip, SCIP_MATRIX *matrix, int nvlbs, int *vlbs, SCIP_Real *lowthresholds, SCIP_Real *highthresholds, int *conidxs, int *binidxs, int *nvaragg, SCIP_Bool *isvartoagg, SCIP_VAR **aggvars, int *ndeletecons, SCIP_Bool *deletecons)
    static SCIP_Bool isVlb(SCIP *scip, SCIP_MATRIX *matrix, int row, SCIP_Real *lowthreshold, SCIP_Real *highthreshold, int *conidx, int *binidx)
    #define PRESOL_NAME
    Definition: presol_redvub.c:60
    static SCIP_RETCODE detectDominatingVubs(SCIP *scip, SCIP_MATRIX *matrix, int nvubs, int *vubs, SCIP_Real *lowthresholds, SCIP_Real *highthresholds, int *conidxs, int *binidxs, int *nvaragg, SCIP_Bool *isvartoagg, SCIP_VAR **aggvars, int *ndeletecons, SCIP_Bool *deletecons)
    #define MAXPAIRCOMP
    Definition: presol_redvub.c:66
    static SCIP_Bool isVub(SCIP *scip, SCIP_MATRIX *matrix, int row, SCIP_Real *lowthreshold, SCIP_Real *highthreshold, int *conidx, int *binidx)
    Definition: presol_redvub.c:74
    static SCIP_DECL_PRESOLCOPY(presolCopyRedvub)
    #define PRESOL_PRIORITY
    Definition: presol_redvub.c:62
    static SCIP_RETCODE findVarAggrRedVbcons(SCIP *scip, SCIP_MATRIX *matrix, int *nvaragg, SCIP_Bool *isvartoagg, SCIP_VAR **aggvars, int *ndeletecons, SCIP_Bool *deletecons)
    #define PRESOL_MAXROUNDS
    Definition: presol_redvub.c:63
    #define PRESOL_TIMING
    Definition: presol_redvub.c:64
    static SCIP_DECL_PRESOLEXEC(presolExecRedvub)
    #define PRESOL_DESC
    Definition: presol_redvub.c:61
    remove redundant variable upper bound constraints
    public methods for matrix
    public methods for message output
    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 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 SCIP variables
    @ 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_STAGE_PRESOLVING
    Definition: type_set.h:49
    @ SCIP_VARTYPE_CONTINUOUS
    Definition: type_var.h:71
    @ SCIP_VARTYPE_BINARY
    Definition: type_var.h:64
    enum SCIP_Vartype SCIP_VARTYPE
    Definition: type_var.h:73