SCIP

    Solving Constraint Integer Programs

    heur_pscostdiving.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_pscostdiving.c
    26 * @ingroup DEFPLUGINS_HEUR
    27 * @brief LP diving heuristic that chooses fixings w.r.t. the pseudo cost values
    28 * @author Tobias Achterberg
    29 */
    30
    31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    32
    33#include "scip/heuristics.h"
    35#include "scip/pub_heur.h"
    36#include "scip/pub_message.h"
    37#include "scip/pub_misc.h"
    38#include "scip/pub_var.h"
    39#include "scip/scip_heur.h"
    40#include "scip/scip_mem.h"
    41#include "scip/scip_numerics.h"
    42#include "scip/scip_prob.h"
    43#include "scip/scip_sol.h"
    44#include "scip/scip_var.h"
    45
    46
    47#define HEUR_NAME "pscostdiving"
    48#define HEUR_DESC "LP diving heuristic that chooses fixings w.r.t. the pseudo cost values"
    49#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_DIVING
    50#define HEUR_PRIORITY -1002000
    51#define HEUR_FREQ 10
    52#define HEUR_FREQOFS 2
    53#define HEUR_MAXDEPTH -1
    54#define HEUR_TIMING SCIP_HEURTIMING_AFTERLPPLUNGE
    55#define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
    56#define DIVESET_DIVETYPES SCIP_DIVETYPE_INTEGRALITY /**< bit mask that represents all supported dive types */
    57#define DIVESET_ISPUBLIC TRUE /**< is this dive set publicly available (ie., can be used by other primal heuristics?) */
    58
    59
    60/*
    61 * Default parameter settings
    62 */
    63
    64#define DEFAULT_MINRELDEPTH 0.0 /**< minimal relative depth to start diving */
    65#define DEFAULT_MAXRELDEPTH 1.0 /**< maximal relative depth to start diving */
    66#define DEFAULT_MAXLPITERQUOT 0.05 /**< maximal fraction of diving LP iterations compared to node LP iterations */
    67#define DEFAULT_MAXLPITEROFS 1000 /**< additional number of allowed LP iterations */
    68#define DEFAULT_MAXDIVEUBQUOT 0.8 /**< maximal quotient (curlowerbound - lowerbound)/(cutoffbound - lowerbound)
    69 * where diving is performed (0.0: no limit) */
    70#define DEFAULT_MAXDIVEAVGQUOT 0.0 /**< maximal quotient (curlowerbound - lowerbound)/(avglowerbound - lowerbound)
    71 * where diving is performed (0.0: no limit) */
    72#define DEFAULT_MAXDIVEUBQUOTNOSOL 0.1 /**< maximal UBQUOT when no solution was found yet (0.0: no limit) */
    73#define DEFAULT_MAXDIVEAVGQUOTNOSOL 0.0 /**< maximal AVGQUOT when no solution was found yet (0.0: no limit) */
    74#define DEFAULT_BACKTRACK TRUE /**< use one level of backtracking if infeasibility is encountered? */
    75#define DEFAULT_LPRESOLVEDOMCHGQUOT 0.15 /**< percentage of immediate domain changes during probing to trigger LP resolve */
    76#define DEFAULT_LPSOLVEFREQ 0 /**< LP solve frequency for diving heuristics */
    77#define DEFAULT_ONLYLPBRANCHCANDS TRUE /**< should only LP branching candidates be considered instead of the slower but
    78 * more general constraint handler diving variable selection? */
    79#define DEFAULT_RANDSEED 103 /**< initial random seed */
    80
    81
    82/* locally defined heuristic data */
    83struct SCIP_HeurData
    84{
    85 SCIP_SOL* sol; /**< working solution */
    86};
    87
    88/*
    89 * local methods
    90 */
    91
    92/*
    93 * Callback methods
    94 */
    95
    96/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
    97static
    98SCIP_DECL_HEURCOPY(heurCopyPscostdiving)
    99{ /*lint --e{715}*/
    100 assert(scip != NULL);
    101 assert(heur != NULL);
    102
    104
    105 /* call inclusion method of primal heuristic */
    107
    108 return SCIP_OKAY;
    109}
    110
    111/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
    112static
    113SCIP_DECL_HEURFREE(heurFreePscostdiving) /*lint --e{715}*/
    114{ /*lint --e{715}*/
    115 SCIP_HEURDATA* heurdata;
    116
    117 assert(heur != NULL);
    118 assert(scip != NULL);
    119
    121
    122 /* free heuristic data */
    123 heurdata = SCIPheurGetData(heur);
    124 assert(heurdata != NULL);
    125 SCIPfreeBlockMemory(scip, &heurdata);
    126 SCIPheurSetData(heur, NULL);
    127
    128 return SCIP_OKAY;
    129}
    130
    131
    132/** initialization method of primal heuristic (called after problem was transformed) */
    133static
    134SCIP_DECL_HEURINIT(heurInitPscostdiving) /*lint --e{715}*/
    135{ /*lint --e{715}*/
    136 SCIP_HEURDATA* heurdata;
    137
    138 assert(heur != NULL);
    139
    141
    142 /* get heuristic data */
    143 heurdata = SCIPheurGetData(heur);
    144 assert(heurdata != NULL);
    145
    146 /* create working solution */
    147 SCIP_CALL( SCIPcreateSol(scip, &heurdata->sol, heur) );
    148
    149 return SCIP_OKAY;
    150}
    151
    152
    153/** deinitialization method of primal heuristic (called before transformed problem is freed) */
    154static
    155SCIP_DECL_HEUREXIT(heurExitPscostdiving) /*lint --e{715}*/
    156{ /*lint --e{715}*/
    157 SCIP_HEURDATA* heurdata;
    158
    159 assert(heur != NULL);
    160
    162
    163 /* get heuristic data */
    164 heurdata = SCIPheurGetData(heur);
    165 assert(heurdata != NULL);
    166
    167 /* free working solution */
    168 SCIP_CALL( SCIPfreeSol(scip, &heurdata->sol) );
    169
    170 return SCIP_OKAY;
    171}
    172
    173/** execution method of primal heuristic */
    174static
    175SCIP_DECL_HEUREXEC(heurExecPscostdiving) /*lint --e{715}*/
    176{ /*lint --e{715}*/
    177 SCIP_HEURDATA* heurdata;
    178 SCIP_DIVESET* diveset;
    179
    180 heurdata = SCIPheurGetData(heur);
    181 assert(heurdata != NULL);
    182 assert(SCIPheurGetNDivesets(heur) > 0);
    183 assert(SCIPheurGetDivesets(heur) != NULL);
    184 diveset = SCIPheurGetDivesets(heur)[0];
    185 assert(diveset != NULL);
    186
    187 *result = SCIP_DIDNOTRUN;
    188
    189 /* terminate if there are no integer variables (note that, e.g., SOS1 variables may be present) */
    191 return SCIP_OKAY;
    192
    193 SCIP_CALL( SCIPperformGenericDivingAlgorithm(scip, diveset, heurdata->sol, heur, result, nodeinfeasible, -1L, -1, -1.0, SCIP_DIVECONTEXT_SINGLE) );
    194
    195 return SCIP_OKAY;
    196}
    197
    198
    199/** returns a score for the given candidate -- the best candidate maximizes the diving score */
    200static
    201SCIP_DECL_DIVESETGETSCORE(divesetGetScorePscostdiving)
    202{
    203 SCIP_Real pscostdown;
    204 SCIP_Real pscostup;
    205 SCIP_Real pscostquot;
    206
    207 SCIP_Bool mayrounddown;
    208 SCIP_Bool mayroundup;
    209
    210 mayrounddown = SCIPvarMayRoundDown(cand);
    211 mayroundup = SCIPvarMayRoundUp(cand);
    212
    213 /* bound fractions to not prefer variables that are nearly integral */
    214 candsfrac = MAX(candsfrac, 0.1);
    215 candsfrac = MIN(candsfrac, 0.9);
    216
    217 pscostdown = SCIPgetVarPseudocostVal(scip, cand, 0.0 - candsfrac);
    218 pscostup = SCIPgetVarPseudocostVal(scip, cand, 1.0 - candsfrac);
    219
    220 /* determine the candidate direction. if the variable may be trivially rounded in one direction, take the other direction;
    221 * otherwise, consider first the direction from the root solution, second the candidate fractionality, and
    222 * last the direction of smaller pseudo costs
    223 *
    224 * to avoid performance variability caused by numerics we use random numbers to decide whether we want to roundup or
    225 * round down if the values to compare are equal within tolerances.
    226 */
    227 assert(pscostdown >= 0.0 && pscostup >= 0.0);
    228 if( mayrounddown != mayroundup )
    229 *roundup = mayrounddown;
    230 else if( SCIPisLT(scip, candsol, SCIPvarGetRootSol(cand) - 0.4)
    231 || (SCIPisEQ(scip, candsol, SCIPvarGetRootSol(cand) - 0.4) && SCIPrandomGetInt(SCIPdivesetGetRandnumgen(diveset), 0, 1) == 0) )
    232 *roundup = FALSE;
    233 else if( SCIPisGT(scip, candsol, SCIPvarGetRootSol(cand) + 0.4)
    234 || (SCIPisEQ(scip, candsol, SCIPvarGetRootSol(cand) + 0.4) && SCIPrandomGetInt(SCIPdivesetGetRandnumgen(diveset), 0, 1) == 0) )
    235 *roundup = TRUE;
    236 else if( SCIPisLT(scip, candsfrac, 0.3)
    237 || (SCIPisEQ(scip, candsfrac, 0.3) && SCIPrandomGetInt(SCIPdivesetGetRandnumgen(diveset), 0, 1) == 0) )
    238 *roundup = FALSE;
    239 else if( SCIPisGT(scip, candsfrac, 0.7)
    240 || (SCIPisEQ(scip, candsfrac, 0.7) && SCIPrandomGetInt(SCIPdivesetGetRandnumgen(diveset), 0, 1) == 0) )
    241 *roundup = TRUE;
    242 else if( SCIPisEQ(scip, pscostdown, pscostup) )
    243 *roundup = (SCIPrandomGetInt(SCIPdivesetGetRandnumgen(diveset), 0, 1) == 0);
    244 else if( pscostdown > pscostup )
    245 *roundup = TRUE;
    246 else
    247 *roundup = FALSE;
    248
    249 if( *roundup )
    250 pscostquot = sqrt(candsfrac) * (1.0 + pscostdown) / (1.0 + pscostup);
    251 else
    252 pscostquot = sqrt(1.0 - candsfrac) * (1.0 + pscostup) / (1.0 + pscostdown);
    253
    254 /* prefer decisions on binary variables */
    255 if( SCIPvarIsBinary(cand) && !(SCIPvarMayRoundDown(cand) || SCIPvarMayRoundUp(cand)))
    256 pscostquot *= 1000.0;
    257
    258 assert(pscostquot >= 0);
    259 *score = pscostquot;
    260
    261 return SCIP_OKAY;
    262}
    263
    264#define divesetAvailablePscostdiving NULL
    265
    266/*
    267 * heuristic specific interface methods
    268 */
    269
    270/** creates the pscostdiving heuristic and includes it in SCIP */
    272 SCIP* scip /**< SCIP data structure */
    273 )
    274{
    275 SCIP_HEURDATA* heurdata;
    276 SCIP_HEUR* heur;
    277
    278 /* create Pscostdiving primal heuristic data */
    279 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    280
    281 /* include primal heuristic */
    284 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecPscostdiving, heurdata) );
    285
    286 assert(heur != NULL);
    287
    288 /* primal heuristic is safe to use in exact solving mode */
    289 SCIPheurMarkExact(heur);
    290
    291 /* set non-NULL pointers to callback methods */
    292 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyPscostdiving) );
    293 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreePscostdiving) );
    294 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitPscostdiving) );
    295 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitPscostdiving) );
    296
    297 /* create a diveset (this will automatically install some additional parameters for the heuristic)*/
    301 DIVESET_ISPUBLIC, DIVESET_DIVETYPES, divesetGetScorePscostdiving, divesetAvailablePscostdiving) );
    302
    303 return SCIP_OKAY;
    304}
    305
    #define NULL
    Definition: def.h:257
    #define SCIP_Bool
    Definition: def.h:100
    #define MIN(x, y)
    Definition: def.h:233
    #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_CALL(x)
    Definition: def.h:364
    int SCIPgetNContVars(SCIP *scip)
    Definition: scip_prob.c:2569
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    int SCIPgetNContImplVars(SCIP *scip)
    Definition: scip_prob.c:2522
    SCIP_RETCODE SCIPincludeHeurPscostdiving(SCIP *scip)
    SCIP_RETCODE SCIPcreateDiveset(SCIP *scip, SCIP_DIVESET **diveset, SCIP_HEUR *heur, const char *name, SCIP_Real minreldepth, SCIP_Real maxreldepth, SCIP_Real maxlpiterquot, SCIP_Real maxdiveubquot, SCIP_Real maxdiveavgquot, SCIP_Real maxdiveubquotnosol, SCIP_Real maxdiveavgquotnosol, SCIP_Real lpresolvedomchgquot, int lpsolvefreq, int maxlpiterofs, unsigned int initialseed, SCIP_Bool backtrack, SCIP_Bool onlylpbranchcands, SCIP_Bool ispublic, SCIP_Bool specificsos1score, SCIP_DECL_DIVESETGETSCORE((*divesetgetscore)), SCIP_DECL_DIVESETAVAILABLE((*divesetavailable)))
    Definition: scip_heur.c:323
    SCIP_RANDNUMGEN * SCIPdivesetGetRandnumgen(SCIP_DIVESET *diveset)
    Definition: heur.c:720
    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
    SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
    Definition: scip_heur.c:215
    int SCIPheurGetNDivesets(SCIP_HEUR *heur)
    Definition: heur.c:1675
    void SCIPheurMarkExact(SCIP_HEUR *heur)
    Definition: heur.c:1457
    SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
    Definition: scip_heur.c:199
    const char * SCIPheurGetName(SCIP_HEUR *heur)
    Definition: heur.c:1467
    SCIP_DIVESET ** SCIPheurGetDivesets(SCIP_HEUR *heur)
    Definition: heur.c:1665
    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 SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:514
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1250
    SCIP_RETCODE SCIPperformGenericDivingAlgorithm(SCIP *scip, SCIP_DIVESET *diveset, SCIP_SOL *worksol, SCIP_HEUR *heur, SCIP_RESULT *result, SCIP_Bool nodeinfeasible, SCIP_Longint iterlim, int nodelimit, SCIP_Real lpresolvedomchgquot, SCIP_DIVECONTEXT divecontext)
    Definition: heuristics.c:221
    SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPvarMayRoundUp(SCIP_VAR *var)
    Definition: var.c:4478
    SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
    Definition: var.c:23510
    SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR *var)
    Definition: var.c:4467
    SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
    Definition: var.c:19144
    SCIP_Real SCIPgetVarPseudocostVal(SCIP *scip, SCIP_VAR *var, SCIP_Real solvaldelta)
    Definition: scip_var.c:11188
    int SCIPrandomGetInt(SCIP_RANDNUMGEN *randnumgen, int minrandval, int maxrandval)
    Definition: misc.c:10223
    #define DEFAULT_ONLYLPBRANCHCANDS
    #define DEFAULT_MAXDIVEUBQUOT
    #define DEFAULT_LPRESOLVEDOMCHGQUOT
    #define HEUR_TIMING
    #define DEFAULT_MAXLPITERQUOT
    #define HEUR_FREQOFS
    #define HEUR_DESC
    static SCIP_DECL_DIVESETGETSCORE(divesetGetScorePscostdiving)
    #define DEFAULT_MAXDIVEAVGQUOT
    #define DEFAULT_LPSOLVEFREQ
    #define DEFAULT_BACKTRACK
    #define DEFAULT_MAXDIVEUBQUOTNOSOL
    #define HEUR_DISPCHAR
    #define HEUR_MAXDEPTH
    #define HEUR_PRIORITY
    static SCIP_DECL_HEURCOPY(heurCopyPscostdiving)
    #define DEFAULT_MAXRELDEPTH
    #define DEFAULT_MAXLPITEROFS
    #define divesetAvailablePscostdiving
    #define DEFAULT_MAXDIVEAVGQUOTNOSOL
    static SCIP_DECL_HEURINIT(heurInitPscostdiving)
    #define HEUR_NAME
    static SCIP_DECL_HEUREXIT(heurExitPscostdiving)
    #define DEFAULT_RANDSEED
    #define DIVESET_DIVETYPES
    #define DIVESET_ISPUBLIC
    #define HEUR_FREQ
    #define DEFAULT_MINRELDEPTH
    #define HEUR_USESSUBSCIP
    static SCIP_DECL_HEURFREE(heurFreePscostdiving)
    static SCIP_DECL_HEUREXEC(heurExecPscostdiving)
    LP diving heuristic that chooses fixings w.r.t. the pseudo cost values.
    methods commonly used by primal heuristics
    public methods for primal heuristics
    public methods for message output
    public data structures and miscellaneous methods
    public methods for problem variables
    public methods for primal heuristic plugins and divesets
    public methods for memory management
    public methods for numerical tolerances
    public methods for global and local (sub)problems
    public methods for solutions
    public methods for SCIP variables
    SCIP_SOL * sol
    Definition: struct_heur.h:71
    struct SCIP_HeurData SCIP_HEURDATA
    Definition: type_heur.h:77
    @ SCIP_DIVECONTEXT_SINGLE
    Definition: type_heur.h:69
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63