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-2026 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file 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
    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
    533
    534 /* call inclusion method of constraint handler */
    536
    537 return SCIP_OKAY;
    538}
    539
    540/** destructor of propagator to free user data (called when SCIP is exiting) */
    541/**! [SnippetPropFreeRedcost] */
    542static
    543SCIP_DECL_PROPFREE(propFreeRedcost)
    544{ /*lint --e{715}*/
    545 SCIP_PROPDATA* propdata;
    546
    547 /* free propagator data */
    548 propdata = SCIPpropGetData(prop);
    549 assert(propdata != NULL);
    550
    551 SCIPfreeBlockMemory(scip, &propdata);
    552
    553 SCIPpropSetData(prop, NULL);
    554
    555 return SCIP_OKAY;
    556}
    557/**! [SnippetPropFreeRedcost] */
    558
    559/** solving process initialization method of propagator (called when branch and bound process is about to begin) */
    560static
    561SCIP_DECL_PROPINITSOL(propInitsolRedcost)
    562{
    563 SCIP_PROPDATA* propdata;
    564
    565 propdata = SCIPpropGetData(prop);
    566 assert(propdata != NULL);
    567
    568 propdata->usefullimplics = FALSE;
    569 propdata->maxredcost = 0.0;
    570
    571 return SCIP_OKAY;
    572}
    573
    574/** reduced cost propagation method for an LP solution */
    575static
    576SCIP_DECL_PROPEXEC(propExecRedcost)
    577{ /*lint --e{715}*/
    578 SCIP_PROPDATA* propdata;
    579 SCIP_COL** cols;
    580 SCIP_Real requiredredcost;
    581 SCIP_Real cutoffbound;
    582 SCIP_Real lpobjval;
    583 SCIP_Bool propbinvars;
    584 SCIP_Bool cutoff;
    585 int nchgbds;
    586 int ncols;
    587 int c;
    588
    589 *result = SCIP_DIDNOTRUN;
    590
    591 /* in case we have a zero objective function, we skip the reduced cost propagator */
    592 if( SCIPgetNObjVars(scip) == 0 )
    593 return SCIP_OKAY;
    594
    595 /* propagator can only be applied during solving stage */
    597 return SCIP_OKAY;
    598
    599 /* we cannot apply reduced cost fixing, if we want to solve exactly */
    600 /**@todo implement reduced cost fixing with interval arithmetics */
    601 if( SCIPisExact(scip) )
    602 return SCIP_OKAY;
    603
    604 /* only call propagator, if the current node has an LP */
    606 return SCIP_OKAY;
    607
    608 /* only call propagator, if an optimal LP solution is at hand */
    610 return SCIP_OKAY;
    611
    612 /* only call propagator, if the current LP is a valid relaxation */
    613 if( !SCIPisLPRelax(scip) )
    614 return SCIP_OKAY;
    615
    616 /* we cannot apply reduced cost strengthening, if no simplex basis is available */
    617 if( !SCIPisLPSolBasic(scip) )
    618 return SCIP_OKAY;
    619
    620 /* do not run if propagation w.r.t. objective is not allowed */
    622 return SCIP_OKAY;
    623
    624 /* get current cutoff bound */
    625 cutoffbound = SCIPgetCutoffbound(scip);
    626
    627 /* reduced cost strengthening can only be applied, if we have a finite cutoff */
    628 if( SCIPisInfinity(scip, cutoffbound) )
    629 return SCIP_OKAY;
    630
    631 /* get LP columns */
    632 cols = SCIPgetLPCols(scip);
    633 ncols = SCIPgetNLPCols(scip);
    634
    635 /* do nothing if the LP has no columns (is empty) */
    636 if( ncols == 0 )
    637 return SCIP_OKAY;
    638
    639 /* get propagator data */
    640 propdata = SCIPpropGetData(prop);
    641 assert(propdata != NULL);
    642
    643 /* do nothing if active pricer are present and force flag is not TRUE */
    644 if( !propdata->force && SCIPgetNActivePricers(scip) > 0 )
    645 return SCIP_OKAY;
    646
    647 /* check if all integral variables are fixed and the continuous variables should not be propagated */
    648 if( !propdata->continuous && SCIPgetNPseudoBranchCands(scip) == 0 )
    649 return SCIP_OKAY;
    650
    651 /* get LP objective value */
    652 lpobjval = SCIPgetLPObjval(scip);
    653
    654 /* check if binary variables should be propagated */
    655 propbinvars = (SCIPgetDepth(scip) == 0) || (cutoffbound - lpobjval < 5 * propdata->maxredcost);
    656
    657 /* skip the propagator if the problem has only binary variables and those should not be propagated */
    658 if( !propbinvars && SCIPgetNVars(scip) == SCIPgetNBinVars(scip) )
    659 return SCIP_OKAY;
    660
    661 *result = SCIP_DIDNOTFIND;
    662 cutoff = FALSE;
    663 nchgbds = 0;
    664
    665 /* compute the required reduced cost which are needed for a binary variable to be fixed */
    666 requiredredcost = cutoffbound - lpobjval;
    667
    668 SCIPdebugMsg(scip, "lpobjval <%g>, cutoffbound <%g>, max reduced <%g>, propgate binary %u, use implics %u\n",
    669 lpobjval, cutoffbound, propdata->maxredcost, propbinvars, propdata->usefullimplics);
    670
    671 /* check reduced costs for non-basic columns */
    672 for( c = 0; c < ncols && !cutoff; ++c )
    673 {
    674 SCIP_VAR* var;
    675
    676 var = SCIPcolGetVar(cols[c]);
    677
    678 /* skip continuous variables in case the corresponding parameter is set */
    679 if( !propdata->continuous && !SCIPvarIsIntegral(var) )
    680 continue;
    681
    682 if( SCIPvarIsBinary(var) )
    683 {
    684 if( propbinvars )
    685 {
    686 if( SCIPgetDepth(scip) == 0 )
    687 {
    688 SCIP_CALL( propagateRootRedcostBinvar(scip, propdata, var, cols[c], cutoffbound, &nchgbds) );
    689 }
    690 else
    691 {
    692 SCIP_CALL( propagateRedcostBinvar(scip, propdata, var, cols[c], requiredredcost, &nchgbds, &cutoff) );
    693 }
    694 }
    695 }
    696 else
    697 {
    698 SCIP_CALL( propagateRedcostVar(scip, var, cols[c], lpobjval, cutoffbound, &nchgbds) );
    699 }
    700 }
    701
    702 if( cutoff )
    703 {
    704 *result = SCIP_CUTOFF;
    705
    706 SCIPdebugMsg(scip, "node %" SCIP_LONGINT_FORMAT ": detected cutoff\n",
    708 }
    709 else if( nchgbds > 0 )
    710 {
    711 *result = SCIP_REDUCEDDOM;
    712
    713 SCIPdebugMsg(scip, "node %" SCIP_LONGINT_FORMAT ": %d bound changes (max redcost <%g>)\n",
    714 SCIPnodeGetNumber(SCIPgetCurrentNode(scip)) , nchgbds, propdata->maxredcost);
    715 }
    716
    717 return SCIP_OKAY;
    718}
    719
    720/**@} */
    721
    722/** creates the redcost propagator and includes it in SCIP */
    724 SCIP* scip /**< SCIP data structure */
    725 )
    726{
    727 SCIP_PROPDATA* propdata;
    728 SCIP_PROP* prop;
    729
    730 /* create redcost propagator data */
    731 SCIP_CALL( SCIPallocBlockMemory(scip, &propdata) );
    732
    733 /* include propagator */
    735 propExecRedcost, propdata) );
    736
    737 assert(prop != NULL);
    738
    739 /* set optional callbacks via setter functions */
    740 SCIP_CALL( SCIPsetPropCopy(scip, prop, propCopyRedcost) );
    741 SCIP_CALL( SCIPsetPropInitsol(scip, prop, propInitsolRedcost) );
    742 SCIP_CALL( SCIPsetPropFree(scip, prop, propFreeRedcost) );
    743
    744 /* add redcost propagator parameters */
    746 "propagating/" PROP_NAME "/continuous",
    747 "should reduced cost fixing be also applied to continuous variables?",
    748 &propdata->continuous, FALSE, DEFAULT_CONTINUOUS, NULL, NULL) );
    750 "propagating/" PROP_NAME "/useimplics",
    751 "should implications be used to strength the reduced cost for binary variables?",
    752 &propdata->useimplics, FALSE, DEFAULT_USEIMPLICS, NULL, NULL) );
    754 "propagating/" PROP_NAME "/force",
    755 "should the propagator be forced even if active pricer are present?",
    756 &propdata->force, TRUE, DEFAULT_FORCE, NULL, NULL) );
    757
    758 return SCIP_OKAY;
    759}
    #define NULL
    Definition: def.h:257
    #define SCIP_INVALID
    Definition: def.h:187
    #define SCIP_Bool
    Definition: def.h:100
    #define MAX3(x, y, z)
    Definition: def.h:237
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define MAX(x, y)
    Definition: def.h:229
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:157
    #define SCIP_CALL(x)
    Definition: def.h:364
    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:723
    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:8513
    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:23510
    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:24300
    SCIP_Real SCIPvarGetBestRootSol(SCIP_VAR *var)
    Definition: var.c:19509
    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:23299
    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:23522
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24266
    SCIP_Real SCIPgetVarRedcost(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:2608
    SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
    Definition: var.c:19576
    SCIP_Real SCIPvarGetBestRootLPObjval(SCIP_VAR *var)
    Definition: var.c:19610
    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:543
    static SCIP_DECL_PROPEXEC(propExecRedcost)
    Definition: prop_redcost.c:576
    #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:561
    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
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_STAGE_SOLVING
    Definition: type_set.h:53