SCIP

    Solving Constraint Integer Programs

    heur_coefdiving.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_coefdiving.c
    26 * @ingroup DEFPLUGINS_HEUR
    27 * @brief LP diving heuristic that chooses fixings w.r.t. the matrix coefficients
    28 * @author Tobias Achterberg
    29 * @author Marc Pfetsch
    30 *
    31 * Indicator constraints are taken into account if present.
    32 */
    33
    34/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    35
    37#include "scip/heuristics.h"
    38#include "scip/pub_heur.h"
    39#include "scip/pub_message.h"
    40#include "scip/pub_misc.h"
    41#include "scip/pub_var.h"
    42#include "scip/scip_heur.h"
    43#include "scip/scip_lp.h"
    44#include "scip/scip_mem.h"
    45#include "scip/scip_numerics.h"
    46#include "scip/scip_sol.h"
    47
    48
    49#define HEUR_NAME "coefdiving"
    50#define HEUR_DESC "LP diving heuristic that chooses fixings w.r.t. the matrix coefficients"
    51#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_DIVING
    52#define HEUR_PRIORITY -1001000
    53#define HEUR_FREQ -1
    54#define HEUR_FREQOFS 1
    55#define HEUR_MAXDEPTH -1
    56#define HEUR_TIMING SCIP_HEURTIMING_AFTERLPPLUNGE
    57#define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
    58#define DIVESET_DIVETYPES SCIP_DIVETYPE_INTEGRALITY | SCIP_DIVETYPE_SOS1VARIABLE /**< bit mask that represents all supported dive types */
    59#define DIVESET_ISPUBLIC TRUE /**< is this dive set publicly available (ie., can be used by other primal heuristics?) */
    60
    61
    62/*
    63 * Default parameter settings
    64 */
    65
    66#define DEFAULT_MINRELDEPTH 0.0 /**< minimal relative depth to start diving */
    67#define DEFAULT_MAXRELDEPTH 1.0 /**< maximal relative depth to start diving */
    68#define DEFAULT_MAXLPITERQUOT 0.05 /**< maximal fraction of diving LP iterations compared to node LP iterations */
    69#define DEFAULT_MAXLPITEROFS 1000 /**< additional number of allowed LP iterations */
    70#define DEFAULT_MAXDIVEUBQUOT 0.8 /**< maximal quotient (curlowerbound - lowerbound)/(cutoffbound - lowerbound)
    71 * where diving is performed (0.0: no limit) */
    72#define DEFAULT_MAXDIVEAVGQUOT 0.0 /**< maximal quotient (curlowerbound - lowerbound)/(avglowerbound - lowerbound)
    73 * where diving is performed (0.0: no limit) */
    74#define DEFAULT_MAXDIVEUBQUOTNOSOL 0.1 /**< maximal UBQUOT when no solution was found yet (0.0: no limit) */
    75#define DEFAULT_MAXDIVEAVGQUOTNOSOL 0.0 /**< maximal AVGQUOT when no solution was found yet (0.0: no limit) */
    76#define DEFAULT_BACKTRACK TRUE /**< use one level of backtracking if infeasibility is encountered? */
    77#define DEFAULT_LPRESOLVEDOMCHGQUOT 0.15 /**< percentage of immediate domain changes during probing to trigger LP resolve */
    78#define DEFAULT_LPSOLVEFREQ 0 /**< LP solve frequency for diving heuristics */
    79#define DEFAULT_ONLYLPBRANCHCANDS FALSE /**< should only LP branching candidates be considered instead of the slower but
    80 * more general constraint handler diving variable selection? */
    81#define DEFAULT_RANDSEED 83 /**< default random seed */
    82
    83/* locally defined heuristic data */
    84struct SCIP_HeurData
    85{
    86 SCIP_SOL* sol; /**< working solution */
    87};
    88
    89/*
    90 * local methods
    91 */
    92
    93/*
    94 * Callback methods
    95 */
    96
    97/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
    98static
    99SCIP_DECL_HEURCOPY(heurCopyCoefdiving)
    100{ /*lint --e{715}*/
    101 assert(scip != NULL);
    102 assert(heur != NULL);
    103
    105
    106 /* call inclusion method of constraint handler */
    108
    109 return SCIP_OKAY;
    110}
    111
    112/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
    113static
    114SCIP_DECL_HEURFREE(heurFreeCoefdiving) /*lint --e{715}*/
    115{ /*lint --e{715}*/
    116 SCIP_HEURDATA* heurdata;
    117
    118 assert(heur != NULL);
    119 assert(scip != NULL);
    120
    122
    123 /* free heuristic data */
    124 heurdata = SCIPheurGetData(heur);
    125 assert(heurdata != NULL);
    126 SCIPfreeBlockMemory(scip, &heurdata);
    127 SCIPheurSetData(heur, NULL);
    128
    129 return SCIP_OKAY;
    130}
    131
    132
    133/** initialization method of primal heuristic (called after problem was transformed) */
    134static
    135SCIP_DECL_HEURINIT(heurInitCoefdiving) /*lint --e{715}*/
    136{ /*lint --e{715}*/
    137 SCIP_HEURDATA* heurdata;
    138
    139 assert(heur != NULL);
    140
    142
    143 /* get heuristic data */
    144 heurdata = SCIPheurGetData(heur);
    145 assert(heurdata != NULL);
    146
    147 /* create working solution */
    148 SCIP_CALL( SCIPcreateSol(scip, &heurdata->sol, heur) );
    149
    150 return SCIP_OKAY;
    151}
    152
    153
    154/** deinitialization method of primal heuristic (called before transformed problem is freed) */
    155static
    156SCIP_DECL_HEUREXIT(heurExitCoefdiving) /*lint --e{715}*/
    157{ /*lint --e{715}*/
    158 SCIP_HEURDATA* heurdata;
    159
    160 assert(heur != NULL);
    161
    163
    164 /* get heuristic data */
    165 heurdata = SCIPheurGetData(heur);
    166 assert(heurdata != NULL);
    167
    168 /* free working solution */
    169 SCIP_CALL( SCIPfreeSol(scip, &heurdata->sol) );
    170
    171 return SCIP_OKAY;
    172}
    173
    174
    175/** execution method of primal heuristic */
    176static
    177SCIP_DECL_HEUREXEC(heurExecCoefdiving) /*lint --e{715}*/
    178{ /*lint --e{715}*/
    179 SCIP_HEURDATA* heurdata;
    180 SCIP_DIVESET* diveset;
    181
    182 heurdata = SCIPheurGetData(heur);
    183 assert(heurdata != NULL);
    184
    185 assert(SCIPheurGetNDivesets(heur) > 0);
    186 assert(SCIPheurGetDivesets(heur) != NULL);
    187 diveset = SCIPheurGetDivesets(heur)[0];
    188 assert(diveset != NULL);
    189
    190 SCIP_CALL( SCIPperformGenericDivingAlgorithm(scip, diveset, heurdata->sol, heur, result, nodeinfeasible, -1L, -1, -1.0, SCIP_DIVECONTEXT_SINGLE) );
    191
    192 return SCIP_OKAY;
    193}
    194
    195/** returns a score for the given candidate -- the best candidate maximizes the diving score */
    196static
    197SCIP_DECL_DIVESETGETSCORE(divesetGetScoreCoefdiving)
    198{
    199 SCIP_Bool mayrounddown = SCIPvarMayRoundDown(cand);
    200 SCIP_Bool mayroundup = SCIPvarMayRoundUp(cand);
    201
    202 if( mayrounddown || mayroundup )
    203 {
    204 /* choose rounding direction:
    205 * - if variable may be rounded in both directions, round corresponding to the fractionality
    206 * - otherwise, round in the infeasible direction
    207 */
    208 if( mayrounddown && mayroundup )
    209 {
    210 assert( divetype != SCIP_DIVETYPE_SOS1VARIABLE );
    211
    212 /* try to avoid variability; decide randomly if the LP solution can contain some noise */
    213 if( SCIPisEQ(scip, candsfrac, 0.5) )
    214 *roundup = (SCIPrandomGetInt(SCIPdivesetGetRandnumgen(diveset), 0, 1) == 0);
    215 else
    216 *roundup = (candsfrac > 0.5);
    217 }
    218 else
    219 *roundup = mayrounddown;
    220 }
    221 else
    222 {
    223 /* the candidate may not be rounded */
    224 int nlocksdown = SCIPvarGetNLocksDownType(cand, SCIP_LOCKTYPE_MODEL);
    225 int nlocksup = SCIPvarGetNLocksUpType(cand, SCIP_LOCKTYPE_MODEL);
    226 *roundup = (nlocksdown > nlocksup || (nlocksdown == nlocksup && candsfrac > 0.5));
    227 }
    228
    229 if( *roundup )
    230 {
    231 switch( divetype )
    232 {
    234 candsfrac = 1.0 - candsfrac;
    235 break;
    237 if ( SCIPisFeasPositive(scip, candsol) )
    238 candsfrac = 1.0 - candsfrac;
    239 break;
    240 default:
    241 SCIPerrorMessage("Error: Unsupported diving type\n");
    242 SCIPABORT();
    243 return SCIP_INVALIDDATA; /*lint !e527*/
    244 } /*lint !e788*/
    246 }
    247 else
    248 {
    249 if ( divetype == SCIP_DIVETYPE_SOS1VARIABLE && SCIPisFeasNegative(scip, candsol) )
    250 candsfrac = 1.0 - candsfrac;
    252 }
    253
    254 /* penalize too small fractions */
    255 if( SCIPisEQ(scip, candsfrac, 0.01) )
    256 {
    257 /* try to avoid variability; decide randomly if the LP solution can contain some noise.
    258 * use a 1:SCIP_PROBINGSCORE_PENALTYRATIO chance for scaling the score
    259 */
    261 (*score) *= 0.01;
    262 }
    263 else if( candsfrac < 0.01 )
    264 (*score) *= 0.01;
    265
    266 /* prefer decisions on binary variables */
    267 if( !SCIPvarIsBinary(cand) )
    268 (*score) *= 0.1;
    269
    270 /* penalize the variable if it may be rounded. */
    271 if( mayrounddown || mayroundup )
    272 (*score) -= SCIPgetNLPRows(scip);
    273
    274 /* check, if candidate is new best candidate: prefer unroundable candidates in any case */
    275 assert( (0.0 < candsfrac && candsfrac < 1.0) || SCIPvarIsBinary(cand) || divetype == SCIP_DIVETYPE_SOS1VARIABLE );
    276
    277 return SCIP_OKAY;
    278}
    279
    280/*
    281 * heuristic specific interface methods
    282 */
    283
    284#define divesetAvailableCoefdiving NULL
    285
    286/** creates the coefdiving heuristic and includes it in SCIP */
    288 SCIP* scip /**< SCIP data structure */
    289 )
    290{
    291 SCIP_HEURDATA* heurdata;
    292 SCIP_HEUR* heur;
    293
    294 /* create coefdiving primal heuristic data */
    295 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    296
    297 /* include primal heuristic */
    300 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecCoefdiving, heurdata) );
    301
    302 assert(heur != NULL);
    303
    304 /* primal heuristic is safe to use in exact solving mode */
    305 SCIPheurMarkExact(heur);
    306
    307 /* set non-NULL pointers to callback methods */
    308 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyCoefdiving) );
    309 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeCoefdiving) );
    310 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitCoefdiving) );
    311 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitCoefdiving) );
    312
    313 /* create a diveset (this will automatically install some additional parameters for the heuristic)*/
    317 DIVESET_ISPUBLIC, DIVESET_DIVETYPES, divesetGetScoreCoefdiving, divesetAvailableCoefdiving) );
    318
    319 return SCIP_OKAY;
    320}
    321
    #define NULL
    Definition: def.h:257
    #define SCIP_PROBINGSCORE_PENALTYRATIO
    Definition: def.h:312
    #define SCIP_Bool
    Definition: def.h:100
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIPABORT()
    Definition: def.h:336
    #define SCIP_CALL(x)
    Definition: def.h:364
    SCIP_RETCODE SCIPincludeHeurCoefdiving(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
    int SCIPgetNLPRows(SCIP *scip)
    Definition: scip_lp.c:632
    #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 SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPvarMayRoundUp(SCIP_VAR *var)
    Definition: var.c:4478
    SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
    Definition: var.c:23510
    int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4380
    SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR *var)
    Definition: var.c:4467
    int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4322
    int SCIPrandomGetInt(SCIP_RANDNUMGEN *randnumgen, int minrandval, int maxrandval)
    Definition: misc.c:10223
    #define DEFAULT_ONLYLPBRANCHCANDS
    #define DEFAULT_MAXDIVEUBQUOT
    #define divesetAvailableCoefdiving
    #define DEFAULT_LPRESOLVEDOMCHGQUOT
    #define HEUR_TIMING
    static SCIP_DECL_HEURFREE(heurFreeCoefdiving)
    #define DEFAULT_MAXLPITERQUOT
    #define HEUR_FREQOFS
    #define HEUR_DESC
    static SCIP_DECL_HEURCOPY(heurCopyCoefdiving)
    #define DEFAULT_MAXDIVEAVGQUOT
    #define DEFAULT_LPSOLVEFREQ
    #define DEFAULT_BACKTRACK
    #define DEFAULT_MAXDIVEUBQUOTNOSOL
    #define HEUR_DISPCHAR
    #define HEUR_MAXDEPTH
    #define HEUR_PRIORITY
    #define DEFAULT_MAXRELDEPTH
    #define DEFAULT_MAXLPITEROFS
    static SCIP_DECL_HEUREXIT(heurExitCoefdiving)
    #define DEFAULT_MAXDIVEAVGQUOTNOSOL
    #define HEUR_NAME
    #define DEFAULT_RANDSEED
    #define DIVESET_DIVETYPES
    static SCIP_DECL_HEURINIT(heurInitCoefdiving)
    static SCIP_DECL_HEUREXEC(heurExecCoefdiving)
    #define DIVESET_ISPUBLIC
    #define HEUR_FREQ
    #define DEFAULT_MINRELDEPTH
    #define HEUR_USESSUBSCIP
    static SCIP_DECL_DIVESETGETSCORE(divesetGetScoreCoefdiving)
    LP diving heuristic that chooses fixings w.r.t. the matrix coefficients.
    methods commonly used by primal heuristics
    public methods for primal heuristics
    public methods for message output
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    public data structures and miscellaneous methods
    public methods for problem variables
    public methods for primal heuristic plugins and divesets
    public methods for the LP relaxation, rows and columns
    public methods for memory management
    public methods for numerical tolerances
    public methods for solutions
    SCIP_SOL * sol
    Definition: struct_heur.h:71
    struct SCIP_HeurData SCIP_HEURDATA
    Definition: type_heur.h:77
    #define SCIP_DIVETYPE_SOS1VARIABLE
    Definition: type_heur.h:61
    #define SCIP_DIVETYPE_INTEGRALITY
    Definition: type_heur.h:60
    @ SCIP_DIVECONTEXT_SINGLE
    Definition: type_heur.h:69
    @ 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_LOCKTYPE_MODEL
    Definition: type_var.h:141