SCIP

    Solving Constraint Integer Programs

    heur_fixandinfer.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 heur_fixandinfer.c
    26 * @ingroup DEFPLUGINS_HEUR
    27 * @brief fix-and-infer primal heuristic
    28 * @author Tobias Achterberg
    29 */
    30
    31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    32
    34#include "scip/pub_heur.h"
    35#include "scip/pub_message.h"
    36#include "scip/pub_var.h"
    37#include "scip/scip_branch.h"
    38#include "scip/scip_general.h"
    39#include "scip/scip_heur.h"
    40#include "scip/scip_mem.h"
    41#include "scip/scip_message.h"
    42#include "scip/scip_numerics.h"
    43#include "scip/scip_param.h"
    44#include "scip/scip_prob.h"
    45#include "scip/scip_probing.h"
    46#include "scip/scip_sol.h"
    47#include "scip/scip_tree.h"
    48#include "scip/scip_var.h"
    49
    50
    51#define HEUR_NAME "fixandinfer"
    52#define HEUR_DESC "iteratively fixes variables and propagates inferences"
    53#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_PROP
    54#define HEUR_PRIORITY -500000
    55#define HEUR_FREQ -1 /* at the moment, the heuristic seems to be useless */
    56#define HEUR_FREQOFS 0
    57#define HEUR_MAXDEPTH -1
    58#define HEUR_TIMING SCIP_HEURTIMING_AFTERNODE
    59#define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
    60
    61#define MAXDIVEDEPTH 100
    62
    63
    64/*
    65 * Default parameter settings
    66 */
    67
    68#define DEFAULT_PROPROUNDS 0 /**< maximal number of propagation rounds in probing subproblems */
    69#define DEFAULT_MINFIXINGS 100 /**< minimal number of fixings to apply before dive may be aborted */
    70
    71
    72/*
    73 * Data structures
    74 */
    75
    76/** primal heuristic data */
    77struct SCIP_HeurData
    78{
    79 int proprounds; /**< maximal number of propagation rounds in probing subproblems */
    80 int minfixings; /**< minimal number of fixings to apply before dive may be aborted */
    81};
    82
    83
    84/*
    85 * Local methods
    86 */
    87
    88/** selects a variable and fixes it to its current pseudo solution value */
    89static
    91 SCIP* scip, /**< SCIP data structure */
    92 SCIP_VAR** pseudocands, /**< array of unfixed variables */
    93 int npseudocands, /**< number of unfixed variables */
    94 SCIP_Real large /**< large value to be used instead of infinity */
    95 )
    96{
    97 SCIP_VAR* var;
    98 SCIP_Real bestscore;
    99 SCIP_Real score;
    100 SCIP_Real solval;
    101 int bestcand;
    102 int ncands;
    103 int c;
    104
    105 assert(pseudocands != NULL);
    106 assert(npseudocands > 0);
    107
    108 /* if existing, choose one of the highest priority binary variables; if no high priority binary variables
    109 * exist, choose a variable among all unfixed integral variables
    110 */
    112 if( ncands == 0 )
    113 ncands = npseudocands;
    114
    115 /* select variable to tighten the domain for */
    116 bestscore = -SCIPinfinity(scip);
    117 bestcand = -1;
    118 for( c = 0; c < ncands; ++c )
    119 {
    120 score = SCIPgetVarAvgInferenceScore(scip, pseudocands[c]);
    121 if( score > bestscore )
    122 {
    123 bestscore = score;
    124 bestcand = c;
    125 }
    126 }
    127 assert(bestcand != -1);
    128
    129 /* fix variable to its current pseudo solution value */
    130 var = pseudocands[bestcand];
    131 solval = SCIPgetVarSol(scip, var);
    132
    133 /* adapt solution value if it is infinite */
    134 if( SCIPisInfinity(scip, solval) )
    135 {
    136 SCIP_Real lb;
    138 lb = SCIPvarGetLbLocal(var);
    139
    140 /* adapt fixing value by changing it to a large value */
    141 if( SCIPisInfinity(scip, -lb) )
    142 solval = SCIPceil(scip, large);
    143 else if( !SCIPisInfinity(scip, SCIPceil(scip, lb+large)) )
    144 solval = SCIPceil(scip, lb+large);
    145 }
    146 else if( SCIPisInfinity(scip, -solval) )
    147 {
    148 SCIP_Real ub;
    149 assert(SCIPisInfinity(scip, -SCIPvarGetLbLocal(var)));
    150 ub = SCIPvarGetUbLocal(var);
    151
    152 /* adapt fixing value by changing it to a large negative value */
    153 if( SCIPisInfinity(scip, ub) )
    154 solval = SCIPfloor(scip, -large);
    155 else if( !SCIPisInfinity(scip, -SCIPfloor(scip, ub-large)) )
    156 solval = SCIPfloor(scip, ub-large);
    157 }
    158
    159 assert(SCIPisFeasIntegral(scip, solval)); /* in probing, we always have the pseudo solution */
    160 SCIPdebugMsg(scip, " -> fixed variable <%s>[%g,%g] = %g (%d candidates left)\n",
    161 SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), solval, npseudocands - 1);
    162 SCIP_CALL( SCIPfixVarProbing(scip, var, solval) );
    163
    164 return SCIP_OKAY;
    165}
    166
    167
    168/*
    169 * Callback methods of primal heuristic
    170 */
    171
    172/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
    173static
    174SCIP_DECL_HEURCOPY(heurCopyFixandinfer)
    175{ /*lint --e{715}*/
    176 assert(scip != NULL);
    177 assert(heur != NULL);
    178
    180
    181 /* call inclusion method of primal heuristic */
    183
    184 return SCIP_OKAY;
    185}
    186
    187/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
    188static
    189SCIP_DECL_HEURFREE(heurFreeFixandinfer) /*lint --e{715}*/
    190{ /*lint --e{715}*/
    191 SCIP_HEURDATA* heurdata;
    192
    193 /* free heuristic data */
    194 heurdata = SCIPheurGetData(heur);
    195 assert(heurdata != NULL);
    196 SCIPfreeBlockMemory(scip, &heurdata);
    197 SCIPheurSetData(heur, NULL);
    198
    199 return SCIP_OKAY;
    200}
    201
    202
    203/** execution method of primal heuristic */
    204static
    205SCIP_DECL_HEUREXEC(heurExecFixandinfer)
    206{ /*lint --e{715}*/
    207 SCIP_HEURDATA* heurdata;
    208 SCIP_VAR** cands;
    209 int ncands;
    210 int startncands;
    211 int divedepth;
    212 SCIP_Bool cutoff;
    213 SCIP_Real large;
    214
    215 *result = SCIP_DIDNOTRUN;
    216
    217 /* do not call heuristic of node was already detected to be infeasible */
    218 if( nodeinfeasible )
    219 return SCIP_OKAY;
    220
    221 /* we cannot run on problems with continuous variables */
    222 if( SCIPgetNContVars(scip) > 0 )
    223 return SCIP_OKAY;
    224
    225 /* get unfixed variables */
    226 SCIP_CALL( SCIPgetPseudoBranchCands(scip, &cands, &ncands, NULL) );
    227 if( ncands == 0 )
    228 return SCIP_OKAY;
    229
    230 /* get heuristic data */
    231 heurdata = SCIPheurGetData(heur);
    232 assert(heurdata != NULL);
    233
    234 /* fix variables and propagate inferences as long as the problem is still feasible and there are
    235 * unfixed integral variables
    236 */
    237 cutoff = FALSE;
    238 divedepth = 0;
    239 startncands = ncands;
    240
    241 /* start probing */
    243
    245 {
    247 return SCIP_OKAY;
    248 }
    249
    250 SCIPdebugMsg(scip, "starting fix-and-infer heuristic with %d unfixed integral variables\n", ncands);
    251
    252 *result = SCIP_DIDNOTFIND;
    253
    254 /* create next probing node */
    256
    257 /* determine large value to set variables to */
    258 large = SCIPinfinity(scip);
    259 if( !SCIPisInfinity(scip, 0.1 / SCIPfeastol(scip)) )
    260 large = 0.1 / SCIPfeastol(scip);
    261
    262 while( !cutoff && ncands > 0
    263 && (divedepth < heurdata->minfixings || (startncands - ncands) * 2 * MAXDIVEDEPTH >= startncands * divedepth)
    264 && !SCIPisStopped(scip) )
    265 {
    266 divedepth++;
    267
    268 /* fix next variable */
    269 SCIP_CALL( fixVariable(scip, cands, ncands, large) );
    270
    271 /* propagate the fixing */
    272 SCIP_CALL( SCIPpropagateProbing(scip, heurdata->proprounds, &cutoff, NULL) );
    273
    274 /* get remaining unfixed variables */
    275 if( !cutoff )
    276 {
    277 SCIP_CALL( SCIPgetPseudoBranchCands(scip, &cands, &ncands, NULL) );
    278 }
    279 }
    280
    281 /* check, if we are still feasible */
    282 if( cutoff )
    283 {
    284 SCIPdebugMsg(scip, "propagation detected a cutoff\n");
    285 }
    286 else if( ncands == 0 )
    287 {
    288 SCIP_Bool success;
    289
    290 success = FALSE;
    291
    292 /* try to add solution to SCIP */
    293 SCIP_CALL( SCIPtryCurrentSol(scip, heur, FALSE, FALSE, FALSE, TRUE, &success) );
    294
    295 if( success )
    296 {
    297 SCIPdebugMsg(scip, "found primal feasible solution\n");
    298 *result = SCIP_FOUNDSOL;
    299 }
    300 else
    301 {
    302 SCIPdebugMsg(scip, "primal solution was rejected\n");
    303 }
    304 }
    305 else
    306 {
    307 SCIPdebugMsg(scip, "probing was aborted (probing depth: %d, fixed: %d/%d)", divedepth, startncands - ncands, startncands);
    308 }
    309
    310 /* end probing */
    312
    313 return SCIP_OKAY;
    314}
    315
    316
    317/*
    318 * primal heuristic specific interface methods
    319 */
    320
    321/** creates the fix-and-infer primal heuristic and includes it in SCIP */
    323 SCIP* scip /**< SCIP data structure */
    324 )
    325{
    326 SCIP_HEURDATA* heurdata;
    327 SCIP_HEUR* heur;
    328
    329 /* create Fixandinfer primal heuristic data */
    330 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    331
    332 /* include primal heuristic */
    335 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecFixandinfer, heurdata) );
    336
    337 assert(heur != NULL);
    338
    339 /* primal heuristic is safe to use in exact solving mode */
    340 SCIPheurMarkExact(heur);
    341
    342 /* set non-NULL pointers to callback methods */
    343 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyFixandinfer) );
    344 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeFixandinfer) );
    345
    346 /* fixandinfer heuristic parameters */
    348 "heuristics/fixandinfer/proprounds",
    349 "maximal number of propagation rounds in probing subproblems (-1: no limit, 0: auto)",
    350 &heurdata->proprounds, TRUE, DEFAULT_PROPROUNDS, -1, INT_MAX, NULL, NULL) );
    352 "heuristics/fixandinfer/minfixings",
    353 "minimal number of fixings to apply before dive may be aborted",
    354 &heurdata->minfixings, TRUE, DEFAULT_MINFIXINGS, 0, INT_MAX, NULL, NULL) );
    355
    356 return SCIP_OKAY;
    357}
    #define NULL
    Definition: def.h:257
    #define SCIP_MAXTREEDEPTH
    Definition: def.h:306
    #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 SCIP_CALL(x)
    Definition: def.h:364
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:767
    int SCIPgetNContVars(SCIP *scip)
    Definition: scip_prob.c:2569
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:83
    SCIP_RETCODE SCIPincludeHeurFixandinfer(SCIP *scip)
    int SCIPgetNPrioPseudoBranchBins(SCIP *scip)
    Definition: scip_branch.c:803
    SCIP_RETCODE SCIPgetPseudoBranchCands(SCIP *scip, SCIP_VAR ***pseudocands, int *npseudocands, int *npriopseudocands)
    Definition: scip_branch.c:741
    SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
    Definition: scip_heur.c:167
    SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
    Definition: heur.c:1368
    SCIP_RETCODE SCIPincludeHeurBasic(SCIP *scip, SCIP_HEUR **heur, const char *name, const char *desc, char dispchar, int priority, int freq, int freqofs, int maxdepth, SCIP_HEURTIMING timingmask, SCIP_Bool usessubscip, SCIP_DECL_HEUREXEC((*heurexec)), SCIP_HEURDATA *heurdata)
    Definition: scip_heur.c:122
    SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
    Definition: scip_heur.c:183
    void SCIPheurMarkExact(SCIP_HEUR *heur)
    Definition: heur.c:1457
    const char * SCIPheurGetName(SCIP_HEUR *heur)
    Definition: heur.c:1467
    void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
    Definition: heur.c:1378
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    SCIP_RETCODE SCIPpropagateProbing(SCIP *scip, int maxproprounds, SCIP_Bool *cutoff, SCIP_Longint *ndomredsfound)
    Definition: scip_probing.c:581
    SCIP_RETCODE SCIPstartProbing(SCIP *scip)
    Definition: scip_probing.c:120
    SCIP_RETCODE SCIPnewProbingNode(SCIP *scip)
    Definition: scip_probing.c:166
    SCIP_RETCODE SCIPfixVarProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval)
    Definition: scip_probing.c:419
    SCIP_RETCODE SCIPendProbing(SCIP *scip)
    Definition: scip_probing.c:261
    SCIP_RETCODE SCIPtryCurrentSol(SCIP *scip, SCIP_HEUR *heur, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
    Definition: scip_sol.c:4212
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPfeastol(SCIP *scip)
    SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
    int SCIPgetDepth(SCIP *scip)
    Definition: scip_tree.c:672
    SCIP_Real SCIPgetVarAvgInferenceScore(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:11945
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24300
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23299
    SCIP_Real SCIPgetVarSol(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:3051
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24266
    #define HEUR_TIMING
    static SCIP_DECL_HEURFREE(heurFreeFixandinfer)
    #define HEUR_FREQOFS
    #define HEUR_DESC
    static SCIP_DECL_HEUREXEC(heurExecFixandinfer)
    #define HEUR_DISPCHAR
    #define HEUR_MAXDEPTH
    #define HEUR_PRIORITY
    #define DEFAULT_PROPROUNDS
    #define HEUR_NAME
    #define DEFAULT_MINFIXINGS
    #define HEUR_FREQ
    #define HEUR_USESSUBSCIP
    #define MAXDIVEDEPTH
    static SCIP_DECL_HEURCOPY(heurCopyFixandinfer)
    static SCIP_RETCODE fixVariable(SCIP *scip, SCIP_VAR **pseudocands, int npseudocands, SCIP_Real large)
    fix-and-infer primal heuristic
    public methods for primal heuristics
    public methods for message output
    public methods for problem variables
    public methods for branching rule plugins and branching
    general public methods
    public methods for primal heuristic plugins and divesets
    public methods for memory management
    public methods for message handling
    public methods for numerical tolerances
    public methods for SCIP parameter handling
    public methods for global and local (sub)problems
    public methods for the probing mode
    public methods for solutions
    public methods for the branch-and-bound tree
    public methods for SCIP variables
    struct SCIP_HeurData SCIP_HEURDATA
    Definition: type_heur.h:77
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_FOUNDSOL
    Definition: type_result.h:56
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63