Scippy

    SCIP

    Solving Constraint Integer Programs

    prop_redcost.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 prop_redcost.c
    26 * @ingroup DEFPLUGINS_PROP
    27 * @brief propagator using the LP reduced cost and the cutoff bound
    28 * @author Tobias Achterberg
    29 * @author Stefan Heinz
    30 * @author Matthias Miltenberger
    31 * @author Michael Winkler
    32 *
    33 * This propagator uses the reduced cost of an optimal solved LP relaxation to propagate the variables against the
    34 * cutoff bound.
    35 */
    36
    37/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    38
    39#include "lpi/type_lpi.h"
    40#include "scip/prop_redcost.h"
    41#include "scip/pub_lp.h"
    42#include "scip/pub_message.h"
    43#include "scip/pub_prop.h"
    44#include "scip/pub_tree.h"
    45#include "scip/pub_var.h"
    46#include "scip/scip_branch.h"
    47#include "scip/scip_exact.h"
    48#include "scip/scip_general.h"
    49#include "scip/scip_lp.h"
    50#include "scip/scip_mem.h"
    51#include "scip/scip_message.h"
    52#include "scip/scip_numerics.h"
    53#include "scip/scip_param.h"
    54#include "scip/scip_pricer.h"
    55#include "scip/scip_prob.h"
    56#include "scip/scip_prop.h"
    58#include "scip/scip_tree.h"
    59#include "scip/scip_var.h"
    60#include <string.h>
    61
    62/**@name Propagator properties
    63 *
    64 * @{
    65 */
    66
    67#define PROP_NAME "redcost"
    68#define PROP_DESC "reduced cost strengthening propagator"
    69#define PROP_TIMING SCIP_PROPTIMING_DURINGLPLOOP | SCIP_PROPTIMING_AFTERLPLOOP
    70#define PROP_PRIORITY +1000000 /**< propagator priority */
    71#define PROP_FREQ 1 /**< propagator frequency */
    72#define PROP_DELAY FALSE /**< should propagation method be delayed, if other propagators found reductions? */
    73
    74/**@} */
    75
    76
    77/**@name Default parameter values
    78 *
    79 * @{
    80 */
    81
    82#define DEFAULT_CONTINUOUS FALSE /**< should reduced cost fixing be also applied to continuous variables? */
    83#define DEFAULT_USEIMPLICS FALSE /**< should implications be used to strength the reduced cost for binary variables? */
    84#define DEFAULT_FORCE FALSE /**< should the propagator be forced even if active pricer are present? Note that
    85 * the reductions are always valid, but installing an upper bound on priced
    86 * variables may lead to problems in pricing (existing variables at their upper
    87 * bound may be priced again since they may have negative reduced costs) */
    88
    89/**@} */
    90
    91
    92/*
    93 * Data structures
    94 */
    95
    96
    97/** propagator data */
    98struct SCIP_PropData
    99{
    100 SCIP_Bool continuous; /**< should reduced cost fixing be also applied to continuous variables? */
    101 SCIP_Real maxredcost; /**< maximum reduced cost of a single binary variable */
    102 SCIP_Bool usefullimplics; /**< are the implied reduced cost useful */
    103 SCIP_Bool useimplics; /**< should implications be used to strength the reduced cost for binary variables? */
    104 SCIP_Bool force; /**< should the propagator be forced even if active pricer are present? */
    105};
    106
    107
    108/**@name Local methods
    109 *
    110 * @{
    111 */
    112
    113/** propagate the given binary variable/column using the root reduced cost stored in the SCIP internal data structures
    114 * and check if the implications can be useful. Depending on that implications are used or not used during the search to
    115 * strength the reduced costs.
    116 */
    117static
    119 SCIP* scip, /**< SCIP data structure */
    120 SCIP_PROPDATA* propdata, /**< propagator data structure */
    121 SCIP_VAR* var, /**< variable to use for propagation */
    122 SCIP_COL* col, /**< LP column of the variable */
    123 SCIP_Real cutoffbound, /**< the current cutoff bound */
    124 int* nchgbds /**< pointer to count the number of bound changes */
    125 )
    126{
    127 SCIP_Real rootredcost;
    128 SCIP_Real rootsol;
    129 SCIP_Real rootlpobjval;
    130
    131 assert(scip != NULL);
    132 assert(SCIPgetDepth(scip) == 0);
    133
    134 /* skip binary variable if it is locally fixed */
    135 if( SCIPvarGetLbLocal(var) > 0.5 || SCIPvarGetUbLocal(var) < 0.5 )
    136 return SCIP_OKAY;
    137
    138 rootredcost = SCIPvarGetBestRootRedcost(var);
    139 rootsol = SCIPvarGetBestRootSol(var);
    140 rootlpobjval = SCIPvarGetBestRootLPObjval(var);
    141
    142 if( SCIPisDualfeasZero(scip, rootredcost) )
    143 return SCIP_OKAY;
    144
    145 assert(rootlpobjval != SCIP_INVALID); /*lint !e777*/
    146
    147 if( rootsol > 0.5 )
    148 {
    149 /* SCIPisLPDualReliable should always return TRUE if the dual feasibility check is enabled and the LP claims to
    150 * have a dual feasible solution. if the check is disabled the dual solution might be incorrect and the assert
    151 * might fail. however, if the user decides to disable the dual feasibility check (which also can lead to wrong
    152 * cutoffs) we don't want to skip propagating with reduced costs as an unexpected side-effect.
    153 */
    154 assert(!SCIPisLPDualReliable(scip) || !SCIPisDualfeasPositive(scip, rootredcost));
    155
    156 /* update maximum reduced cost of a single binary variable */
    157 propdata->maxredcost = MAX(propdata->maxredcost, -rootredcost);
    158
    159 if( rootlpobjval - rootredcost > cutoffbound )
    160 {
    161 SCIPdebugMsg(scip, "globally fix binary variable <%s> to 1.0\n", SCIPvarGetName(var));
    162
    163 SCIP_CALL( SCIPchgVarLb(scip, var, 1.0) );
    164 (*nchgbds)++;
    165 return SCIP_OKAY;
    166 }
    167 }
    168 else
    169 {
    170 /* SCIPisLPDualReliable should always return TRUE if the dual feasibility check is enabled and the LP claims to
    171 * have a dual feasible solution. if the check is disabled the dual solution might be incorrect and the assert
    172 * might fail. however, if the user decides to disable the dual feasibility check (which also can lead to wrong
    173 * cutoffs) we don't want to skip propagating with reduced costs as an unexpected side-effect.
    174 */
    175 assert(!SCIPisLPDualReliable(scip) || !SCIPisDualfeasNegative(scip, rootredcost));
    176
    177 /* update maximum reduced cost of a single binary variable */
    178 propdata->maxredcost = MAX(propdata->maxredcost, rootredcost);
    179
    180 if( rootlpobjval + rootredcost > cutoffbound )
    181 {
    182 SCIPdebugMsg(scip, "globally fix binary variable <%s> to 0.0\n", SCIPvarGetName(var));
    183
    184 SCIP_CALL( SCIPchgVarUb(scip, var, 0.0) );
    185 (*nchgbds)++;
    186 return SCIP_OKAY;
    187 }
    188 }
    189
    190 /* evaluate if the implications are useful; the implications are seen to be useful if they provide an increase for
    191 * the root reduced costs
    192 */
    193 if( !propdata->usefullimplics )
    194 {
    195 SCIP_Real lbredcost;
    196 SCIP_Real ubredcost;
    197
    198 lbredcost = SCIPgetVarImplRedcost(scip, var, FALSE);
    199 assert(!SCIPisDualfeasPositive(scip, lbredcost));
    200
    201 ubredcost = SCIPgetVarImplRedcost(scip, var, TRUE);
    202 assert(!SCIPisDualfeasNegative(scip, ubredcost));
    203
    204 switch( SCIPcolGetBasisStatus(col) )
    205 {
    207 ubredcost -= SCIPgetVarRedcost(scip, var);
    208
    209 /* SCIPisLPDualReliable should always return TRUE if the dual feasibility check is enabled and the LP claims to
    210 * have a dual feasible solution. if the check is disabled the dual solution might be incorrect and the assert
    211 * might fail. however, if the user decides to disable the dual feasibility check (which also can lead to wrong
    212 * cutoffs) we don't want to skip propagating with reduced costs as an unexpected side-effect.
    213 */
    214 assert(!SCIPisLPDualReliable(scip) || !SCIPisDualfeasNegative(scip, ubredcost));
    215 break;
    216
    218 lbredcost -= SCIPgetVarRedcost(scip, var);
    219
    220 /* SCIPisLPDualReliable should always return TRUE if the dual feasibility check is enabled and the LP claims to
    221 * have a dual feasible solution. if the check is disabled the dual solution might be incorrect and the assert
    222 * might fail. however, if the user decides to disable the dual feasibility check (which also can lead to wrong
    223 * cutoffs) we don't want to skip propagating with reduced costs as an unexpected side-effect.
    224 */
    225 assert(!SCIPisLPDualReliable(scip) || !SCIPisDualfeasPositive(scip, lbredcost));
    226 break;
    227
    230 default:
    231 break;
    232 }
    233
    234 propdata->usefullimplics = (lbredcost < 0.0) || (ubredcost > 0.0);
    235 }
    236
    237 return SCIP_OKAY;
    238}
    239
    240/** propagate the given binary variable/column using the reduced cost */
    241static
    243 SCIP* scip, /**< SCIP data structure */
    244 SCIP_PROPDATA* propdata, /**< propagator data structure */
    245 SCIP_VAR* var, /**< variable to use for propagation */
    246 SCIP_COL* col, /**< LP column of the variable */
    247 SCIP_Real requiredredcost, /**< required reduset cost to be able to fix a binary variable */
    248 int* nchgbds, /**< pointer to count the number of bound changes */
    249 SCIP_Bool* cutoff /**< pointer to store if an cutoff was detected */
    250 )
    251{
    252 SCIP_Real lbredcost;
    253 SCIP_Real ubredcost;
    254 SCIP_Real redcost;
    255
    256 /* skip binary variable if it is locally fixed */
    257 if( SCIPvarGetLbLocal(var) > 0.5 || SCIPvarGetUbLocal(var) < 0.5 )
    258 return SCIP_OKAY;
    259
    260 /* first use the redcost cost to fix the binary variable */
    261 switch( SCIPcolGetBasisStatus(col) )
    262 {
    264 redcost = SCIPgetVarRedcost(scip, var);
    265
    266 /* SCIPisLPDualReliable should always return TRUE if the dual feasibility check is enabled and the LP claims to
    267 * have a dual feasible solution. if the check is disabled the dual solution might be incorrect and the assert
    268 * might fail. however, if the user decides to disable the dual feasibility check (which also can lead to wrong
    269 * cutoffs) we don't want to skip propagating with reduced costs as an unexpected side-effect.
    270 */
    272
    273 if( redcost > requiredredcost )
    274 {
    275 SCIPdebugMsg(scip, "variable <%s>: fixed 0.0 (requiredredcost <%g>, redcost <%g>)\n",
    276 SCIPvarGetName(var), requiredredcost, redcost);
    277
    278 SCIP_CALL( SCIPchgVarUb(scip, var, 0.0) );
    279 (*nchgbds)++;
    280 return SCIP_OKAY;
    281 }
    282 break;
    283
    285 redcost = SCIPgetVarRedcost(scip, var);
    286
    287 /* SCIPisLPDualReliable should always return TRUE if the dual feasibility check is enabled and the LP claims to
    288 * have a dual feasible solution. if the check is disabled the dual solution might be incorrect and the assert
    289 * might fail. however, if the user decides to disable the dual feasibility check (which also can lead to wrong
    290 * cutoffs) we don't want to skip propagating with reduced costs as an unexpected side-effect.
    291 */
    293
    294 if( -redcost > requiredredcost )
    295 {
    296 SCIPdebugMsg(scip, "variable <%s>: fixed 1.0 (requiredredcost <%g>, redcost <%g>)\n",
    297 SCIPvarGetName(var), requiredredcost, redcost);
    298
    299 SCIP_CALL( SCIPchgVarLb(scip, var, 1.0) );
    300 (*nchgbds)++;
    301 return SCIP_OKAY;
    302 }
    303 break;
    304
    306 return SCIP_OKAY;
    307
    309 /* SCIPisLPDualReliable should always return TRUE if the dual feasibility check is enabled and the LP claims to
    310 * have a dual feasible solution. if the check is disabled the dual solution might be incorrect and the assert
    311 * might fail. however, if the user decides to disable the dual feasibility check (which also can lead to wrong
    312 * cutoffs) we don't want to skip propagating with reduced costs as an unexpected side-effect.
    313 */
    315 return SCIP_OKAY;
    316
    317 default:
    318 SCIPerrorMessage("invalid basis state\n");
    319 return SCIP_INVALIDDATA;
    320 }
    321
    322 /* second, if the implications should be used and if the implications are seen to be promising use the implied
    323 * reduced costs to fix the binary variable
    324 */
    325 if( propdata->useimplics && propdata->usefullimplics )
    326 {
    327 /* collect implied reduced costs if the variable would be fixed to its lower bound */
    328 lbredcost = SCIPgetVarImplRedcost(scip, var, FALSE);
    329
    330 /* SCIPisLPDualReliable should always return TRUE if the dual feasibility check is enabled and the LP claims to
    331 * have a dual feasible solution. if the check is disabled the dual solution might be incorrect and the assert
    332 * might fail. however, if the user decides to disable the dual feasibility check (which also can lead to wrong
    333 * cutoffs) we don't want to skip propagating with reduced costs as an unexpected side-effect.
    334 */
    337
    338 /* collect implied reduced costs if the variable would be fixed to its upper bound */
    339 ubredcost = SCIPgetVarImplRedcost(scip, var, TRUE);
    342
    343 if( -lbredcost > requiredredcost && ubredcost > requiredredcost )
    344 {
    345 SCIPdebugMsg(scip, "variable <%s>: cutoff (requiredredcost <%g>, lbredcost <%g>, ubredcost <%g>)\n",
    346 SCIPvarGetName(var), requiredredcost, lbredcost, ubredcost);
    347
    348 (*cutoff) = TRUE;
    349 }
    350 else if( -lbredcost > requiredredcost )
    351 {
    352 SCIPdebugMsg(scip, "variable <%s>: fixed 1.0 (requiredredcost <%g>, redcost <%g>, lbredcost <%g>)\n",
    353 SCIPvarGetName(var), requiredredcost, redcost, lbredcost);
    354
    355 SCIP_CALL( SCIPchgVarLb(scip, var, 1.0) );
    356 (*nchgbds)++;
    357 }
    358 else if( ubredcost > requiredredcost )
    359 {
    360 SCIPdebugMsg(scip, "variable <%s>: fixed 0.0 (requiredredcost <%g>, redcost <%g>, ubredcost <%g>)\n",
    361 SCIPvarGetName(var), requiredredcost, redcost, ubredcost);
    362
    363 SCIP_CALL( SCIPchgVarUb(scip, var, 0.0) );
    364 (*nchgbds)++;
    365 }
    366
    367 /* update maximum reduced cost of a single binary variable */
    368 propdata->maxredcost = MAX3(propdata->maxredcost, -lbredcost, ubredcost);
    369 }
    370
    371 return SCIP_OKAY;
    372}
    373
    374/** propagate the given none binary variable/column using the reduced cost */
    375static
    377 SCIP* scip, /**< SCIP data structure */
    378 SCIP_VAR* var, /**< variable to use for propagation */
    379 SCIP_COL* col, /**< LP column of the variable */
    380 SCIP_Real lpobjval, /**< objective value of the current LP */
    381 SCIP_Real cutoffbound, /**< the current cutoff bound */
    382 int* nchgbds /**< pointer to count the number of bound changes */
    383 )
    384{
    385 SCIP_Real redcost;
    386
    387 switch( SCIPcolGetBasisStatus(col) )
    388 {
    390 redcost = SCIPgetColRedcost(scip, col);
    391
    392 /* SCIPisLPDualReliable should always return TRUE if the dual feasibility check is enabled and the LP claims to
    393 * have a dual feasible solution. if the check is disabled the dual solution might be incorrect and the assert
    394 * might fail. however, if the user decides to disable the dual feasibility check (which also can lead to wrong
    395 * cutoffs) we don't want to skip propagating with reduced costs as an unexpected side-effect.
    396 */
    399
    400 if( SCIPisDualfeasPositive(scip, redcost) )
    401 {
    402 SCIP_Real oldlb;
    403 SCIP_Real oldub;
    404
    405 oldlb = SCIPvarGetLbLocal(var);
    406 oldub = SCIPvarGetUbLocal(var);
    407 assert(SCIPisEQ(scip, oldlb, SCIPcolGetLb(col)));
    408 assert(SCIPisEQ(scip, oldub, SCIPcolGetUb(col)));
    409
    410 if( SCIPisFeasLT(scip, oldlb, oldub) )
    411 {
    412 SCIP_Real newub;
    413 SCIP_Bool strengthen;
    414
    415 /* calculate reduced cost based bound */
    416 newub = (cutoffbound - lpobjval) / redcost + oldlb;
    417
    418 /* check, if new bound is good enough:
    419 * - integer variables: take all possible strengthenings
    420 * - continuous variables: strengthening must cut part of the variable's dynamic range, and
    421 * at least 20% of the current domain
    422 */
    423 if( SCIPvarIsIntegral(var) )
    424 {
    425 newub = SCIPadjustedVarUb(scip, var, newub);
    426 strengthen = (newub < oldub - 0.5);
    427 }
    428 else
    429 strengthen = (newub < SCIPcolGetMaxPrimsol(col) && newub <= 0.2 * oldlb + 0.8 * oldub);
    430
    431 if( strengthen )
    432 {
    433 /* strengthen upper bound */
    434 SCIPdebugMsg(scip, "redcost strengthening upper bound: <%s> [%g,%g] -> [%g,%g] (ub=%g, lb=%g, redcost=%g)\n",
    435 SCIPvarGetName(var), oldlb, oldub, oldlb, newub, cutoffbound, lpobjval, redcost);
    436 SCIP_CALL( SCIPchgVarUb(scip, var, newub) );
    437 (*nchgbds)++;
    438 }
    439 }
    440 }
    441 break;
    442
    444 break;
    445
    447 redcost = SCIPgetColRedcost(scip, col);
    448
    449 /* SCIPisLPDualReliable should always return TRUE if the dual feasibility check is enabled and the LP claims to
    450 * have a dual feasible solution. if the check is disabled the dual solution might be incorrect and the assert
    451 * might fail. however, if the user decides to disable the dual feasibility check (which also can lead to wrong
    452 * cutoffs) we don't want to skip propagating with reduced costs as an unexpected side-effect.
    453 */
    456
    457 if( SCIPisDualfeasNegative(scip, redcost) )
    458 {
    459 SCIP_Real oldlb;
    460 SCIP_Real oldub;
    461
    462 oldlb = SCIPvarGetLbLocal(var);
    463 oldub = SCIPvarGetUbLocal(var);
    464 assert(SCIPisEQ(scip, oldlb, SCIPcolGetLb(col)));
    465 assert(SCIPisEQ(scip, oldub, SCIPcolGetUb(col)));
    466
    467 if( SCIPisFeasLT(scip, oldlb, oldub) )
    468 {
    469 SCIP_Real newlb;
    470 SCIP_Bool strengthen;
    471
    472 /* calculate reduced cost based bound */
    473 newlb = (cutoffbound - lpobjval) / redcost + oldub;
    474
    475 /* check, if new bound is good enough:
    476 * - integer variables: take all possible strengthenings
    477 * - continuous variables: strengthening must cut part of the variable's dynamic range, and
    478 * at least 20% of the current domain
    479 */
    480 if( SCIPvarIsIntegral(var) )
    481 {
    482 newlb = SCIPadjustedVarLb(scip, var, newlb);
    483 strengthen = (newlb > oldlb + 0.5);
    484 }
    485 else
    486 strengthen = (newlb > SCIPcolGetMinPrimsol(col) && newlb >= 0.8 * oldlb + 0.2 * oldub);
    487
    488 /* check, if new bound is good enough: at least 20% strengthening for continuous variables */
    489 if( strengthen )
    490 {
    491 /* strengthen lower bound */
    492 SCIPdebugMsg(scip, "redcost strengthening lower bound: <%s> [%g,%g] -> [%g,%g] (ub=%g, lb=%g, redcost=%g)\n",
    493 SCIPvarGetName(var), oldlb, oldub, newlb, oldub, cutoffbound, lpobjval, redcost);
    494 SCIP_CALL( SCIPchgVarLb(scip, var, newlb) );
    495 (*nchgbds)++;
    496 }
    497 }
    498 }
    499 break;
    500
    502 /* SCIPisLPDualReliable should always return TRUE if the dual feasibility check is enabled and the LP claims to
    503 * have a dual feasible solution. if the check is disabled the dual solution might be incorrect and the assert
    504 * might fail. however, if the user decides to disable the dual feasibility check (which also can lead to wrong
    505 * cutoffs) we don't want to skip propagating with reduced costs as an unexpected side-effect.
    506 */
    508 break;
    509
    510 default:
    511 SCIPerrorMessage("invalid basis state\n");
    512 return SCIP_INVALIDDATA;
    513 }
    514
    515 return SCIP_OKAY;
    516}
    517
    518/**@} */
    519
    520/**@name Callback methods of propagator
    521 *
    522 * @{
    523 */
    524
    525/** copy method for propagator plugins (called when SCIP copies plugins) */
    526static
    527SCIP_DECL_PROPCOPY(propCopyRedcost)
    528{ /*lint --e{715}*/
    529 assert(scip != NULL);
    530 assert(prop != NULL);
    531 assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
    532
    533 /* call inclusion method of constraint handler */
    535
    536 return SCIP_OKAY;
    537}
    538
    539/** destructor of propagator to free user data (called when SCIP is exiting) */
    540/**! [SnippetPropFreeRedcost] */
    541static
    542SCIP_DECL_PROPFREE(propFreeRedcost)
    543{ /*lint --e{715}*/
    544 SCIP_PROPDATA* propdata;
    545
    546 /* free propagator data */
    547 propdata = SCIPpropGetData(prop);
    548 assert(propdata != NULL);
    549
    550 SCIPfreeBlockMemory(scip, &propdata);
    551
    552 SCIPpropSetData(prop, NULL);
    553
    554 return SCIP_OKAY;
    555}
    556/**! [SnippetPropFreeRedcost] */
    557
    558/** solving process initialization method of propagator (called when branch and bound process is about to begin) */
    559static
    560SCIP_DECL_PROPINITSOL(propInitsolRedcost)
    561{
    562 SCIP_PROPDATA* propdata;
    563
    564 propdata = SCIPpropGetData(prop);
    565 assert(propdata != NULL);
    566
    567 propdata->usefullimplics = FALSE;
    568 propdata->maxredcost = 0.0;
    569
    570 return SCIP_OKAY;
    571}
    572
    573/** reduced cost propagation method for an LP solution */
    574static
    575SCIP_DECL_PROPEXEC(propExecRedcost)
    576{ /*lint --e{715}*/
    577 SCIP_PROPDATA* propdata;
    578 SCIP_COL** cols;
    579 SCIP_Real requiredredcost;
    580 SCIP_Real cutoffbound;
    581 SCIP_Real lpobjval;
    582 SCIP_Bool propbinvars;
    583 SCIP_Bool cutoff;
    584 int nchgbds;
    585 int ncols;
    586 int c;
    587
    588 *result = SCIP_DIDNOTRUN;
    589
    590 /* in case we have a zero objective function, we skip the reduced cost propagator */
    591 if( SCIPgetNObjVars(scip) == 0 )
    592 return SCIP_OKAY;
    593
    594 /* propagator can only be applied during solving stage */
    596 return SCIP_OKAY;
    597
    598 /* we cannot apply reduced cost fixing, if we want to solve exactly */
    599 /**@todo implement reduced cost fixing with interval arithmetics */
    600 if( SCIPisExact(scip) )
    601 return SCIP_OKAY;
    602
    603 /* only call propagator, if the current node has an LP */
    605 return SCIP_OKAY;
    606
    607 /* only call propagator, if an optimal LP solution is at hand */
    609 return SCIP_OKAY;
    610
    611 /* only call propagator, if the current LP is a valid relaxation */
    612 if( !SCIPisLPRelax(scip) )
    613 return SCIP_OKAY;
    614
    615 /* we cannot apply reduced cost strengthening, if no simplex basis is available */
    616 if( !SCIPisLPSolBasic(scip) )
    617 return SCIP_OKAY;
    618
    619 /* do not run if propagation w.r.t. objective is not allowed */
    621 return SCIP_OKAY;
    622
    623 /* get current cutoff bound */
    624 cutoffbound = SCIPgetCutoffbound(scip);
    625
    626 /* reduced cost strengthening can only be applied, if we have a finite cutoff */
    627 if( SCIPisInfinity(scip, cutoffbound) )
    628 return SCIP_OKAY;
    629
    630 /* get LP columns */
    631 cols = SCIPgetLPCols(scip);
    632 ncols = SCIPgetNLPCols(scip);
    633
    634 /* do nothing if the LP has no columns (is empty) */
    635 if( ncols == 0 )
    636 return SCIP_OKAY;
    637
    638 /* get propagator data */
    639 propdata = SCIPpropGetData(prop);
    640 assert(propdata != NULL);
    641
    642 /* do nothing if active pricer are present and force flag is not TRUE */
    643 if( !propdata->force && SCIPgetNActivePricers(scip) > 0 )
    644 return SCIP_OKAY;
    645
    646 /* check if all integral variables are fixed and the continuous variables should not be propagated */
    647 if( !propdata->continuous && SCIPgetNPseudoBranchCands(scip) == 0 )
    648 return SCIP_OKAY;
    649
    650 /* get LP objective value */
    651 lpobjval = SCIPgetLPObjval(scip);
    652
    653 /* check if binary variables should be propagated */
    654 propbinvars = (SCIPgetDepth(scip) == 0) || (cutoffbound - lpobjval < 5 * propdata->maxredcost);
    655
    656 /* skip the propagator if the problem has only binary variables and those should not be propagated */
    657 if( !propbinvars && SCIPgetNVars(scip) == SCIPgetNBinVars(scip) )
    658 return SCIP_OKAY;
    659
    660 *result = SCIP_DIDNOTFIND;
    661 cutoff = FALSE;
    662 nchgbds = 0;
    663
    664 /* compute the required reduced cost which are needed for a binary variable to be fixed */
    665 requiredredcost = cutoffbound - lpobjval;
    666
    667 SCIPdebugMsg(scip, "lpobjval <%g>, cutoffbound <%g>, max reduced <%g>, propgate binary %u, use implics %u\n",
    668 lpobjval, cutoffbound, propdata->maxredcost, propbinvars, propdata->usefullimplics);
    669
    670 /* check reduced costs for non-basic columns */
    671 for( c = 0; c < ncols && !cutoff; ++c )
    672 {
    673 SCIP_VAR* var;
    674
    675 var = SCIPcolGetVar(cols[c]);
    676
    677 /* skip continuous variables in case the corresponding parameter is set */
    678 if( !propdata->continuous && !SCIPvarIsIntegral(var) )
    679 continue;
    680
    681 if( SCIPvarIsBinary(var) )
    682 {
    683 if( propbinvars )
    684 {
    685 if( SCIPgetDepth(scip) == 0 )
    686 {
    687 SCIP_CALL( propagateRootRedcostBinvar(scip, propdata, var, cols[c], cutoffbound, &nchgbds) );
    688 }
    689 else
    690 {
    691 SCIP_CALL( propagateRedcostBinvar(scip, propdata, var, cols[c], requiredredcost, &nchgbds, &cutoff) );
    692 }
    693 }
    694 }
    695 else
    696 {
    697 SCIP_CALL( propagateRedcostVar(scip, var, cols[c], lpobjval, cutoffbound, &nchgbds) );
    698 }
    699 }
    700
    701 if( cutoff )
    702 {
    703 *result = SCIP_CUTOFF;
    704
    705 SCIPdebugMsg(scip, "node %" SCIP_LONGINT_FORMAT ": detected cutoff\n",
    707 }
    708 else if( nchgbds > 0 )
    709 {
    710 *result = SCIP_REDUCEDDOM;
    711
    712 SCIPdebugMsg(scip, "node %" SCIP_LONGINT_FORMAT ": %d bound changes (max redcost <%g>)\n",
    713 SCIPnodeGetNumber(SCIPgetCurrentNode(scip)) , nchgbds, propdata->maxredcost);
    714 }
    715
    716 return SCIP_OKAY;
    717}
    718
    719/**@} */
    720
    721/** creates the redcost propagator and includes it in SCIP */
    723 SCIP* scip /**< SCIP data structure */
    724 )
    725{
    726 SCIP_PROPDATA* propdata;
    727 SCIP_PROP* prop;
    728
    729 /* create redcost propagator data */
    730 SCIP_CALL( SCIPallocBlockMemory(scip, &propdata) );
    731
    732 /* include propagator */
    734 propExecRedcost, propdata) );
    735
    736 assert(prop != NULL);
    737
    738 /* set optional callbacks via setter functions */
    739 SCIP_CALL( SCIPsetPropCopy(scip, prop, propCopyRedcost) );
    740 SCIP_CALL( SCIPsetPropInitsol(scip, prop, propInitsolRedcost) );
    741 SCIP_CALL( SCIPsetPropFree(scip, prop, propFreeRedcost) );
    742
    743 /* add redcost propagator parameters */
    745 "propagating/" PROP_NAME "/continuous",
    746 "should reduced cost fixing be also applied to continuous variables?",
    747 &propdata->continuous, FALSE, DEFAULT_CONTINUOUS, NULL, NULL) );
    749 "propagating/" PROP_NAME "/useimplics",
    750 "should implications be used to strength the reduced cost for binary variables?",
    751 &propdata->useimplics, FALSE, DEFAULT_USEIMPLICS, NULL, NULL) );
    753 "propagating/" PROP_NAME "/force",
    754 "should the propagator be forced even if active pricer are present?",
    755 &propdata->force, TRUE, DEFAULT_FORCE, NULL, NULL) );
    756
    757 return SCIP_OKAY;
    758}
    #define NULL
    Definition: def.h:248
    #define SCIP_INVALID
    Definition: def.h:178
    #define SCIP_Bool
    Definition: def.h:91
    #define MAX3(x, y, z)
    Definition: def.h:228
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:148
    #define SCIP_CALL(x)
    Definition: def.h:355
    SCIP_STAGE SCIPgetStage(SCIP *scip)
    Definition: scip_general.c:444
    int SCIPgetNObjVars(SCIP *scip)
    Definition: scip_prob.c:2616
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    int SCIPgetNBinVars(SCIP *scip)
    Definition: scip_prob.c:2293
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:57
    SCIP_RETCODE SCIPincludePropRedcost(SCIP *scip)
    Definition: prop_redcost.c:722
    int SCIPgetNPseudoBranchCands(SCIP *scip)
    Definition: scip_branch.c:766
    SCIP_Real SCIPgetColRedcost(SCIP *scip, SCIP_COL *col)
    Definition: scip_lp.c:1163
    SCIP_Real SCIPcolGetMinPrimsol(SCIP_COL *col)
    Definition: lp.c:17392
    SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
    Definition: lp.c:17425
    SCIP_Real SCIPcolGetLb(SCIP_COL *col)
    Definition: lp.c:17346
    SCIP_Real SCIPcolGetUb(SCIP_COL *col)
    Definition: lp.c:17356
    SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
    Definition: lp.c:17414
    SCIP_Real SCIPcolGetMaxPrimsol(SCIP_COL *col)
    Definition: lp.c:17402
    SCIP_Bool SCIPisExact(SCIP *scip)
    Definition: scip_exact.c:193
    SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
    Definition: scip_lp.c:87
    SCIP_Bool SCIPisLPRelax(SCIP *scip)
    Definition: scip_lp.c:231
    SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
    Definition: scip_lp.c:174
    SCIP_COL ** SCIPgetLPCols(SCIP *scip)
    Definition: scip_lp.c:512
    SCIP_Real SCIPgetLPObjval(SCIP *scip)
    Definition: scip_lp.c:253
    int SCIPgetNLPCols(SCIP *scip)
    Definition: scip_lp.c:533
    SCIP_Bool SCIPisLPSolBasic(SCIP *scip)
    Definition: scip_lp.c:673
    SCIP_Bool SCIPisLPDualReliable(SCIP *scip)
    Definition: scip_lp.c:213
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
    Definition: tree.c:8483
    int SCIPgetNActivePricers(SCIP *scip)
    Definition: scip_pricer.c:348
    void SCIPpropSetData(SCIP_PROP *prop, SCIP_PROPDATA *propdata)
    Definition: prop.c:801
    SCIP_RETCODE SCIPsetPropInitsol(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPINITSOL((*propinitsol)))
    Definition: scip_prop.c:219
    SCIP_PROPDATA * SCIPpropGetData(SCIP_PROP *prop)
    Definition: prop.c:791
    const char * SCIPpropGetName(SCIP_PROP *prop)
    Definition: prop.c:951
    SCIP_RETCODE SCIPsetPropFree(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPFREE((*propfree)))
    Definition: scip_prop.c:171
    SCIP_RETCODE SCIPsetPropCopy(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPCOPY((*propcopy)))
    Definition: scip_prop.c:155
    SCIP_RETCODE SCIPincludePropBasic(SCIP *scip, SCIP_PROP **propptr, const char *name, const char *desc, int priority, int freq, SCIP_Bool delay, SCIP_PROPTIMING timingmask, SCIP_DECL_PROPEXEC((*propexec)), SCIP_PROPDATA *propdata)
    Definition: scip_prop.c:118
    SCIP_Real SCIPgetCutoffbound(SCIP *scip)
    SCIP_Bool SCIPisDualfeasNegative(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisDualfeasPositive(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisDualfeasZero(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    int SCIPgetDepth(SCIP *scip)
    Definition: scip_tree.c:672
    SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
    Definition: scip_tree.c:91
    SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
    Definition: var.c:23478
    SCIP_RETCODE SCIPchgVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
    Definition: scip_var.c:5697
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24268
    SCIP_Real SCIPvarGetBestRootSol(SCIP_VAR *var)
    Definition: var.c:19480
    SCIP_RETCODE SCIPchgVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
    Definition: scip_var.c:5875
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    SCIP_Real SCIPadjustedVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real ub)
    Definition: scip_var.c:5634
    SCIP_Real SCIPadjustedVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real lb)
    Definition: scip_var.c:5570
    SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
    Definition: var.c:23490
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24234
    SCIP_Real SCIPgetVarRedcost(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:2608
    SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
    Definition: var.c:19547
    SCIP_Real SCIPvarGetBestRootLPObjval(SCIP_VAR *var)
    Definition: var.c:19581
    SCIP_Real SCIPgetVarImplRedcost(SCIP *scip, SCIP_VAR *var, SCIP_Bool varfixing)
    Definition: scip_var.c:2653
    SCIP_Bool SCIPallowWeakDualReds(SCIP *scip)
    Definition: scip_var.c:10998
    #define PROP_DESC
    Definition: prop_redcost.c:68
    #define PROP_NAME
    Definition: prop_redcost.c:67
    static SCIP_DECL_PROPFREE(propFreeRedcost)
    Definition: prop_redcost.c:542
    static SCIP_DECL_PROPEXEC(propExecRedcost)
    Definition: prop_redcost.c:575
    #define PROP_DELAY
    Definition: prop_redcost.c:72
    #define DEFAULT_CONTINUOUS
    Definition: prop_redcost.c:82
    #define PROP_TIMING
    Definition: prop_redcost.c:69
    #define DEFAULT_USEIMPLICS
    Definition: prop_redcost.c:83
    static SCIP_DECL_PROPCOPY(propCopyRedcost)
    Definition: prop_redcost.c:527
    static SCIP_DECL_PROPINITSOL(propInitsolRedcost)
    Definition: prop_redcost.c:560
    static SCIP_RETCODE propagateRedcostBinvar(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_VAR *var, SCIP_COL *col, SCIP_Real requiredredcost, int *nchgbds, SCIP_Bool *cutoff)
    Definition: prop_redcost.c:242
    static SCIP_RETCODE propagateRedcostVar(SCIP *scip, SCIP_VAR *var, SCIP_COL *col, SCIP_Real lpobjval, SCIP_Real cutoffbound, int *nchgbds)
    Definition: prop_redcost.c:376
    #define PROP_FREQ
    Definition: prop_redcost.c:71
    #define DEFAULT_FORCE
    Definition: prop_redcost.c:84
    #define PROP_PRIORITY
    Definition: prop_redcost.c:70
    static SCIP_RETCODE propagateRootRedcostBinvar(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_VAR *var, SCIP_COL *col, SCIP_Real cutoffbound, int *nchgbds)
    Definition: prop_redcost.c:118
    propagator using the LP reduced cost and the cutoff bound
    public methods for LP management
    public methods for message output
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    public methods for propagators
    public methods for branch and bound tree
    public methods for problem variables
    public methods for branching rule plugins and branching
    public methods for exact solving
    general public methods
    public methods for the LP relaxation, rows and columns
    public methods for memory management
    public methods for message handling
    public methods for numerical tolerances
    public methods for SCIP parameter handling
    public methods for variable pricer plugins
    public methods for global and local (sub)problems
    public methods for propagator plugins
    public methods for querying solving statistics
    public methods for the branch-and-bound tree
    public methods for SCIP variables
    @ SCIP_LPSOLSTAT_OPTIMAL
    Definition: type_lp.h:44
    type definitions for specific LP solvers interface
    @ SCIP_BASESTAT_BASIC
    Definition: type_lpi.h:92
    @ SCIP_BASESTAT_UPPER
    Definition: type_lpi.h:93
    @ SCIP_BASESTAT_LOWER
    Definition: type_lpi.h:91
    @ SCIP_BASESTAT_ZERO
    Definition: type_lpi.h:94
    struct SCIP_PropData SCIP_PROPDATA
    Definition: type_prop.h:52
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_CUTOFF
    Definition: type_result.h:48
    @ SCIP_REDUCEDDOM
    Definition: type_result.h:51
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_INVALIDDATA
    Definition: type_retcode.h:52
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_STAGE_SOLVING
    Definition: type_set.h:53