SCIP

    Solving Constraint Integer Programs

    prop_dualfix.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_dualfix.c
    26 * @ingroup DEFPLUGINS_PROP
    27 * @brief fixing roundable variables to best bound
    28 * @author Tobias Achterberg
    29 * @author Stefan Heinz
    30 */
    31
    32/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    33
    34#include "scip/prop_dualfix.h"
    35#include "scip/pub_message.h"
    36#include "scip/pub_prop.h"
    37#include "scip/pub_var.h"
    38#include "scip/scip_general.h"
    39#include "scip/scip_message.h"
    40#include "scip/scip_numerics.h"
    41#include "scip/scip_prob.h"
    42#include "scip/scip_probing.h"
    43#include "scip/scip_prop.h"
    44#include "scip/scip_tree.h"
    45#include "scip/scip_var.h"
    46
    47
    48#define PROP_NAME "dualfix"
    49#define PROP_DESC "roundable variables dual fixing"
    50#define PROP_TIMING SCIP_PROPTIMING_BEFORELP
    51#define PROP_PRIORITY +8000000 /**< propagation priority */
    52#define PROP_FREQ 0 /**< propagation frequency */
    53#define PROP_DELAY FALSE /**< should propagation method be delayed, if other propagators found
    54 * reductions? */
    55#define PROP_PRESOL_PRIORITY +8000000 /**< priority of the propagator (>= 0: before, < 0: after constraint handlers) */
    56#define PROP_PRESOL_MAXROUNDS -1 /**< maximal number of propving rounds the propver participates in (-1: no limit) */
    57#define PROP_PRESOLTIMING SCIP_PRESOLTIMING_FAST /* timing of the presolving method (fast, medium, or exhaustive) */
    58
    59
    60/**@name Local methods
    61 *
    62 * @{
    63 */
    64
    65/** perform dual presolving */
    66static
    68 SCIP* scip, /**< SCIP data structure */
    69 int* nfixedvars, /**< pointer to store number of fixed variables */
    70 SCIP_Bool* unbounded, /**< pointer to store if an unboundness was detected */
    71 SCIP_Bool* cutoff /**< pointer to store if a cutoff was detected */
    72 )
    73{
    74 SCIP_VAR** vars;
    75 int nvars;
    76 int v;
    77
    78 assert(nfixedvars != NULL);
    79 assert(unbounded != NULL);
    80 assert(cutoff != NULL);
    81
    82 /* get active problem variables */
    83 vars = SCIPgetVars(scip);
    84 nvars = SCIPgetNVars(scip);
    85
    86 /* look for fixable variables
    87 * loop backwards, since a variable fixing can change the current and the subsequent slots in the vars array
    88 */
    89 for( v = nvars - 1; v >= 0; --v )
    90 {
    91 SCIP_VAR* var;
    93 SCIP_Real obj;
    94 SCIP_Bool infeasible;
    95 SCIP_Bool fixed;
    96
    97 var = vars[v];
    98 assert(var != NULL);
    99
    100 /* don't perform dual presolving operations on deleted variables */
    101 if( SCIPvarIsDeleted(var) )
    102 continue;
    103
    104 /* ignore already fixed variables */
    106 continue;
    107
    108 obj = SCIPvarGetObj(var);
    109
    110 /* if the objective coefficient of the variable is 0 and it may be rounded both
    111 * up and down, then fix it to the closest feasible value to 0 */
    112 if( SCIPisZero(scip, obj) && SCIPvarMayRoundDown(var) && SCIPvarMayRoundUp(var) )
    113 {
    114 SCIP_Real roundbound;
    115
    117 if( SCIPisLT(scip, bound, 0.0) )
    118 {
    119 if( SCIPisLE(scip, 0.0, SCIPvarGetUbGlobal(var)) )
    120 bound = 0.0;
    121 else
    122 {
    123 /* try to take an integer value, only for polishing */
    124 roundbound = SCIPfloor(scip, SCIPvarGetUbGlobal(var));
    125
    126 if( roundbound < bound )
    128 else
    129 bound = roundbound;
    130 }
    131 }
    132 else
    133 {
    134 /* try to take an integer value, only for polishing */
    135 roundbound = SCIPceil(scip, bound);
    136
    137 if( roundbound < SCIPvarGetUbGlobal(var) )
    138 bound = roundbound;
    139 }
    140 SCIPdebugMsg(scip, "fixing variable <%s> with objective 0 to %g\n", SCIPvarGetName(var), bound);
    141 }
    142 else
    143 {
    144 /* if it is always possible to round variable in direction of objective value, fix it to its proper bound */
    145 if( SCIPvarMayRoundDown(var) && !SCIPisNegative(scip, obj) )
    146 {
    148 if ( SCIPisInfinity(scip, -bound) )
    149 {
    150 /* variable can be fixed to -infinity */
    152 {
    153 /* Fixing variables to infinity is not allowed after presolving, since LP-solvers cannot handle this
    154 * consistently. We thus have to ignore this (should better be handled in presolving). */
    155 continue;
    156 }
    158 {
    159 /* Variable is only contained in one constraint: we hope that the corresponding constraint handler is
    160 * clever enough to set/aggregate the variable to something more useful than -infinity and do nothing
    161 * here. */
    162 continue;
    163 }
    164 }
    165 SCIPdebugMsg(scip, "fixing variable <%s> with objective %g and %d uplocks to lower bound %g\n",
    167 }
    168 else if( SCIPvarMayRoundUp(var) && !SCIPisPositive(scip, obj) )
    169 {
    171 if ( SCIPisInfinity(scip, bound) )
    172 {
    173 /* variable can be fixed to infinity */
    175 {
    176 /* Fixing variables to infinity is not allowed after presolving, since LP-solvers cannot handle this
    177 * consistently. We thus have to ignore this (should better be handled in presolving). */
    178 continue;
    179 }
    181 {
    182 /* Variable is only contained in one constraint: we hope that the corresponding constraint handler is
    183 * clever enough to set/aggregate the variable to something more useful than +infinity and do nothing
    184 * here */
    185 continue;
    186 }
    187 }
    188 SCIPdebugMsg(scip, "fixing variable <%s> with objective %g and %d downlocks to upper bound %g\n",
    190 }
    191 else
    192 continue;
    193 }
    194
    196 {
    197 if( !SCIPisZero(scip, obj) )
    198 {
    199 SCIPdebugMsg(scip, " -> unbounded fixing\n");
    201 "problem infeasible or unbounded: variable <%s> with objective %.15g can be made infinitely %s\n",
    202 SCIPvarGetName(var), SCIPvarGetObj(var), bound < 0.0 ? "small" : "large");
    203
    204 *unbounded = TRUE;
    205 }
    206
    207 SCIPdebugMsg(scip, "changed my mind; not applying fixing of variable <%s> to infinity\n", SCIPvarGetName(var));
    208 return SCIP_OKAY;
    209 }
    210
    211 /* apply the fixing */
    212 SCIPdebugMsg(scip, "apply fixing of variable %s to %g\n", SCIPvarGetName(var), bound);
    213 SCIP_CALL( SCIPfixVar(scip, var, bound, &infeasible, &fixed) );
    214
    215 if( infeasible )
    216 {
    217 SCIPdebugMsg(scip, " -> infeasible fixing\n");
    218 *cutoff = TRUE;
    219 return SCIP_OKAY;
    220 }
    221
    222 /* SCIPfixVar only changes bounds if not already feaseq.
    223 * Only if in presolve and not probing, variables will always be fixed.
    224 */
    225 assert(fixed || (SCIPisFeasEQ(scip, bound, SCIPvarGetLbLocal(var))
    227 (*nfixedvars)++;
    228 }
    229
    230 return SCIP_OKAY;
    231}
    232
    233/**@} */
    234
    235/**@name Callback methods
    236 *
    237 * @{
    238 */
    239
    240/** copy method for constraint handler plugins (called when SCIP copies plugins) */
    241static
    242SCIP_DECL_PROPCOPY(propCopyDualfix)
    243{ /*lint --e{715}*/
    244 assert(scip != NULL);
    245 assert(prop != NULL);
    246
    248
    249 /* call inclusion method of propagator */
    251
    252 return SCIP_OKAY;
    253}
    254
    255/** presolving method of propagator */
    256static
    257SCIP_DECL_PROPPRESOL(propPresolDualfix)
    258{ /*lint --e{715}*/
    259 SCIP_Bool cutoff;
    260 SCIP_Bool unbounded;
    261 int oldnfixedvars;
    262
    263 assert(prop != NULL);
    264 assert(result != NULL);
    265
    267
    268 *result = SCIP_DIDNOTRUN;
    269
    271 return SCIP_OKAY;
    272
    273 cutoff = FALSE;
    274 unbounded = FALSE;
    275 oldnfixedvars = *nfixedvars;
    276
    277 SCIP_CALL( performDualfix(scip, nfixedvars, &unbounded, &cutoff) );
    278
    279 /* evaluate propagation result */
    280 if( cutoff )
    281 *result = SCIP_CUTOFF;
    282 else if( unbounded )
    283 *result = SCIP_UNBOUNDED;
    284 else if( *nfixedvars > oldnfixedvars )
    285 *result = SCIP_SUCCESS;
    286 else
    287 *result = SCIP_DIDNOTFIND;
    288
    289 return SCIP_OKAY;
    290}
    291
    292/** execution method of propagator */
    293static
    294SCIP_DECL_PROPEXEC(propExecDualfix)
    295{ /*lint --e{715}*/
    296 int nfixedvars;
    297 SCIP_Bool cutoff;
    298 SCIP_Bool unbounded;
    299
    300 assert(prop != NULL);
    301 assert(result != NULL);
    302
    304
    305 *result = SCIP_DIDNOTRUN;
    306
    307 /** @warning Don't run in probing or in repropagation since this can lead to wrong conclusion
    308 *
    309 * do not run if propagation w.r.t. current objective is not allowed
    310 */
    312 return SCIP_OKAY;
    313
    314 cutoff = FALSE;
    315 unbounded = FALSE;
    316 nfixedvars = 0;
    317
    318 SCIP_CALL( performDualfix(scip, &nfixedvars, &unbounded, &cutoff) );
    319
    320 /* evaluate propagation result */
    321 if( cutoff )
    322 *result = SCIP_CUTOFF;
    323 else if( unbounded )
    324 *result = SCIP_UNBOUNDED;
    325 else if( nfixedvars > 0 )
    326 *result = SCIP_REDUCEDDOM;
    327 else
    328 *result = SCIP_DIDNOTFIND;
    329
    330 return SCIP_OKAY;
    331}
    332
    333
    334/**@} */
    335
    336
    337/** creates the dual fixing propagator and includes it in SCIP */
    339 SCIP* scip /**< SCIP data structure */
    340 )
    341{
    342 SCIP_PROP* prop;
    343
    344 /* include propagator */
    346 assert(prop != NULL);
    347
    348 SCIP_CALL( SCIPsetPropCopy(scip, prop, propCopyDualfix) );
    350
    351 return SCIP_OKAY;
    352}
    static long bound
    #define NULL
    Definition: def.h:257
    #define SCIP_Bool
    Definition: def.h:100
    #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 REALABS(x)
    Definition: def.h:191
    #define SCIP_CALL(x)
    Definition: def.h:364
    SCIP_STAGE SCIPgetStage(SCIP *scip)
    Definition: scip_general.c:444
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    SCIP_VAR ** SCIPgetVars(SCIP *scip)
    Definition: scip_prob.c:2201
    void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:225
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_RETCODE SCIPincludePropDualfix(SCIP *scip)
    Definition: prop_dualfix.c:338
    SCIP_Bool SCIPinProbing(SCIP *scip)
    Definition: scip_probing.c:98
    SCIP_RETCODE SCIPsetPropPresol(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPPRESOL((*proppresol)), int presolpriority, int presolmaxrounds, SCIP_PRESOLTIMING presoltiming)
    Definition: scip_prop.c:283
    const char * SCIPpropGetName(SCIP_PROP *prop)
    Definition: prop.c:951
    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_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPinRepropagation(SCIP *scip)
    Definition: scip_tree.c:146
    SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
    Definition: var.c:23566
    SCIP_Bool SCIPvarMayRoundUp(SCIP_VAR *var)
    Definition: var.c:4478
    int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4380
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24300
    SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR *var)
    Definition: var.c:4467
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23932
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24174
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23299
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24266
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24152
    SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
    Definition: scip_var.c:10318
    int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4322
    SCIP_Bool SCIPallowStrongDualReds(SCIP *scip)
    Definition: scip_var.c:10984
    #define PROP_PRESOL_MAXROUNDS
    Definition: prop_dualfix.c:56
    #define PROP_PRESOLTIMING
    Definition: prop_dualfix.c:57
    #define PROP_DESC
    Definition: prop_dualfix.c:49
    static SCIP_DECL_PROPPRESOL(propPresolDualfix)
    Definition: prop_dualfix.c:257
    #define PROP_NAME
    Definition: prop_dualfix.c:48
    static SCIP_DECL_PROPCOPY(propCopyDualfix)
    Definition: prop_dualfix.c:242
    #define PROP_DELAY
    Definition: prop_dualfix.c:53
    #define PROP_TIMING
    Definition: prop_dualfix.c:50
    static SCIP_RETCODE performDualfix(SCIP *scip, int *nfixedvars, SCIP_Bool *unbounded, SCIP_Bool *cutoff)
    Definition: prop_dualfix.c:67
    static SCIP_DECL_PROPEXEC(propExecDualfix)
    Definition: prop_dualfix.c:294
    #define PROP_FREQ
    Definition: prop_dualfix.c:52
    #define PROP_PRIORITY
    Definition: prop_dualfix.c:51
    #define PROP_PRESOL_PRIORITY
    Definition: prop_dualfix.c:55
    fixing roundable variables to best bound
    public methods for message output
    public methods for propagators
    public methods for problem variables
    general public methods
    public methods for message handling
    public methods for numerical tolerances
    public methods for global and local (sub)problems
    public methods for the probing mode
    public methods for propagator plugins
    public methods for the branch-and-bound tree
    public methods for SCIP variables
    @ SCIP_VERBLEVEL_NORMAL
    Definition: type_message.h:60
    @ 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_UNBOUNDED
    Definition: type_result.h:47
    @ SCIP_SUCCESS
    Definition: type_result.h:58
    @ 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_PRESOLVING
    Definition: type_set.h:49
    @ SCIP_LOCKTYPE_MODEL
    Definition: type_var.h:141