SCIP

    Solving Constraint Integer Programs

    heur_trysol.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_trysol.c
    26 * @ingroup DEFPLUGINS_HEUR
    27 * @brief primal heuristic that tries a given solution
    28 * @author Marc Pfetsch
    29 *
    30 * This heuristic takes a solution from somewhere else via the function SCIPheurPassSolTrySol(). It
    31 * then tries to commit this solution. It is mainly used by cons_indicator, which tries to correct a
    32 * given solution, but cannot directly submit this solution, because it is a constraint handler and
    33 * not a heuristic.
    34 */
    35
    36/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    37
    38#include "scip/heur_trysol.h"
    39#include "scip/pub_heur.h"
    40#include "scip/pub_message.h"
    41#include "scip/pub_sol.h"
    42#include "scip/scip_heur.h"
    43#include "scip/scip_mem.h"
    44#include "scip/scip_message.h"
    45#include "scip/scip_numerics.h"
    46#include "scip/scip_prob.h"
    47#include "scip/scip_sol.h"
    48
    49
    50#define HEUR_NAME "trysol"
    51#define HEUR_DESC "try solution heuristic"
    52#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_TRIVIAL
    53#define HEUR_PRIORITY -3000010 /* should process after all other heuristics */
    54#define HEUR_FREQ 1
    55#define HEUR_FREQOFS 0
    56#define HEUR_MAXDEPTH -1
    57#define HEUR_TIMING SCIP_HEURTIMING_DURINGLPLOOP | SCIP_HEURTIMING_BEFOREPRESOL | SCIP_HEURTIMING_BEFORENODE
    58#define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
    59
    60
    61/*
    62 * Data structures
    63 */
    64
    65
    66/** primal heuristic data */
    67struct SCIP_HeurData
    68{
    69 SCIP_SOL* trysol; /**< storing solution passed to heuristic which has to tried (NULL if none) */
    70 SCIP_SOL* addsol; /**< storing solution passed to heuristic which can be added without checking (NULL if none) */
    71 SCIP_Bool rec; /**< whether we are within our own call */
    72};
    73
    74
    75/*
    76 * Callback methods of primal heuristic
    77 */
    78
    79/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
    80static
    81SCIP_DECL_HEURCOPY(heurCopyTrySol)
    82{ /*lint --e{715}*/
    83 assert(scip != NULL);
    84 assert(heur != NULL);
    85
    87
    88 /* call inclusion method of primal heuristic */
    90
    91 return SCIP_OKAY;
    92}
    93
    94/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
    95static
    96SCIP_DECL_HEURFREE(heurFreeTrySol)
    97{ /*lint --e{715}*/
    98 SCIP_HEURDATA* heurdata;
    99
    100 assert( heur != NULL );
    101 assert( scip != NULL );
    102
    104
    105 SCIPdebugMsg(scip, "free method of trysol primal heuristic.\n");
    106
    107 /* get heuristic data */
    108 heurdata = SCIPheurGetData(heur);
    109 assert(heurdata != NULL);
    110
    111 SCIPfreeBlockMemory(scip, &heurdata);
    112
    113 return SCIP_OKAY;
    114}
    115
    116
    117/** deinitialization method of primal heuristic (called before transformed problem is freed) */
    118static
    120{ /*lint --e{715}*/
    121 SCIP_HEURDATA* heurdata;
    122
    123 assert( heur != NULL );
    124 assert( scip != NULL );
    125
    127
    128 SCIPdebugMsg(scip, "exit method of trysol primal heuristic.\n");
    129
    130 /* get heuristic data */
    131 heurdata = SCIPheurGetData(heur);
    132 assert(heurdata != NULL);
    133
    134 /* free solution if one is still present */
    135 if( heurdata->trysol != NULL )
    136 SCIP_CALL( SCIPfreeSol(scip, &heurdata->trysol) );
    137 assert( heurdata->trysol == NULL );
    138
    139 /* free solution if one is still present */
    140 if( heurdata->addsol != NULL )
    141 SCIP_CALL( SCIPfreeSol(scip, &heurdata->addsol) );
    142 assert( heurdata->trysol == NULL );
    143
    144 return SCIP_OKAY;
    145}
    146
    147
    148/** execution method of primal heuristic */
    149static
    150SCIP_DECL_HEUREXEC(heurExecTrySol)
    151{ /*lint --e{715}*/
    152 SCIP_HEURDATA* heurdata;
    153 SCIP_Bool stored;
    154#ifdef SCIP_DEBUG
    155 SCIP_Real obj;
    156#endif
    157
    158 assert( heur != NULL );
    159 assert( scip != NULL );
    160 assert( result != NULL );
    161
    163
    164 *result = SCIP_DIDNOTRUN;
    165
    166 /* get heuristic data */
    167 heurdata = SCIPheurGetData(heur);
    168 assert(heurdata != NULL);
    169
    170 /* only run if solution present */
    171 if( heurdata->addsol == NULL && heurdata->trysol == NULL )
    172 return SCIP_OKAY;
    173
    174 SCIPdebugMsg(scip, "exec method of trysol primal heuristic.\n");
    175 *result = SCIP_DIDNOTFIND;
    176 heurdata->rec = TRUE;
    177
    178 if( heurdata->trysol != NULL )
    179 {
    180 /* try solution and free it - check everything, because we are not sure */
    181#ifdef SCIP_DEBUG
    182 obj = SCIPgetSolOrigObj(scip, heurdata->trysol);
    183#endif
    184
    185 SCIP_CALL( SCIPtrySolFree(scip, &heurdata->trysol, FALSE, FALSE, TRUE, TRUE, TRUE, &stored) );
    186
    187 if( stored )
    188 {
    189#ifdef SCIP_DEBUG
    190 SCIPdebugMsg(scip, "Found feasible solution of value %g.\n", obj);
    191#endif
    192 *result = SCIP_FOUNDSOL;
    193 }
    194 }
    195
    196 if( heurdata->addsol != NULL )
    197 {
    198#ifdef SCIP_DEBUG
    199 obj = SCIPgetSolOrigObj(scip, heurdata->addsol);
    200#endif
    201
    202 SCIP_CALL( SCIPaddSolFree(scip, &heurdata->addsol, &stored) );
    203
    204 if( stored )
    205 {
    206#ifdef SCIP_DEBUG
    207 SCIPdebugMsg(scip, "Found feasible solution of value %g.\n", obj);
    208#endif
    209 *result = SCIP_FOUNDSOL;
    210 }
    211 }
    212
    213 assert( heurdata->trysol == NULL );
    214 assert( heurdata->addsol == NULL );
    215
    216 heurdata->rec = FALSE;
    217
    218 return SCIP_OKAY;
    219}
    220
    221/*
    222 * primal heuristic specific interface methods
    223 */
    224
    225/** creates the trysol primal heuristic and includes it in SCIP */
    227 SCIP* scip /**< SCIP data structure */
    228 )
    229{
    230 SCIP_HEURDATA* heurdata;
    231 SCIP_HEUR* heur;
    232
    233 /* create heuristic data */
    234 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    235 heurdata->trysol = NULL;
    236 heurdata->addsol = NULL;
    237 heurdata->rec = FALSE;
    238
    239 /* include primal heuristic */
    242 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecTrySol, heurdata) );
    243
    244 assert(heur != NULL);
    245
    246 /* primal heuristic is safe to use in exact solving mode */
    247 SCIPheurMarkExact(heur);
    248
    249 /* set non-NULL pointers to callback methods */
    250 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyTrySol) );
    251 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeTrySol) );
    252 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitTrySol) );
    253
    254 return SCIP_OKAY;
    255}
    256
    257
    258/** pass solution to trysol heuristic */
    260 SCIP* scip, /**< SCIP data structure */
    261 SCIP_HEUR* heur, /**< trysol heuristic */
    262 SCIP_SOL* sol /**< solution to be passed */
    263 )
    264{
    265 SCIP_HEURDATA* heurdata;
    266
    267 assert( scip != NULL );
    268 assert( heur != NULL );
    269 assert( sol != NULL );
    270
    272
    273 /* get heuristic data */
    274 heurdata = SCIPheurGetData(heur);
    275 assert(heurdata != NULL);
    276
    277 /* only store solution if we are not within our own SCIPtrySol() call */
    278 if( ! heurdata->rec )
    279 {
    280 if( heurdata->trysol == NULL || (SCIPgetObjsense(scip) == SCIP_OBJSENSE_MAXIMIZE &&
    281 SCIPisGT(scip, SCIPgetSolOrigObj(scip, sol), SCIPgetSolOrigObj(scip, heurdata->trysol))) ||
    282 SCIPisLT(scip, SCIPgetSolOrigObj(scip, sol), SCIPgetSolOrigObj(scip, heurdata->trysol)) )
    283 {
    284 if( heurdata->trysol != NULL )
    285 {
    286 /* free previous solution */
    287 SCIP_CALL( SCIPfreeSol(scip, &heurdata->trysol) );
    288 }
    289
    290 SCIPdebugMsg(scip, "Received solution of value %g.\n", SCIPgetSolOrigObj(scip, sol));
    291 SCIP_CALL( SCIPcreateSolCopy(scip, &heurdata->trysol, sol) );
    292 SCIP_CALL( SCIPunlinkSol(scip, heurdata->trysol) );
    293 SCIPsolSetHeur(heurdata->trysol, heur);
    294 }
    295 }
    296
    297 return SCIP_OKAY;
    298}
    299
    300/** pass solution to trysol heuristic which just gets added (without checking feasibility */
    302 SCIP* scip, /**< SCIP data structure */
    303 SCIP_HEUR* heur, /**< trysol heuristic */
    304 SCIP_SOL* sol /**< solution to be passed */
    305 )
    306{
    307 SCIP_HEURDATA* heurdata;
    308
    309 assert( scip != NULL );
    310 assert( heur != NULL );
    311 assert( sol != NULL );
    312
    314
    315 /* get heuristic data */
    316 heurdata = SCIPheurGetData(heur);
    317 assert(heurdata != NULL);
    318
    319 /* only store solution if we are not within our own SCIPtrySol() call */
    320 if( ! heurdata->rec )
    321 {
    322 if( heurdata->addsol == NULL || (SCIPgetObjsense(scip) == SCIP_OBJSENSE_MAXIMIZE &&
    323 SCIPisGT(scip, SCIPgetSolOrigObj(scip, sol), SCIPgetSolOrigObj(scip, heurdata->addsol))) ||
    324 SCIPisLT(scip, SCIPgetSolOrigObj(scip, sol), SCIPgetSolOrigObj(scip, heurdata->addsol)) )
    325 {
    326 if( heurdata->addsol != NULL )
    327 {
    328 /* free previous solution */
    329 SCIP_CALL( SCIPfreeSol(scip, &heurdata->addsol) );
    330 }
    331
    332 SCIPdebugMsg(scip, "Received solution of value %g.\n", SCIPgetSolOrigObj(scip, sol));
    333 SCIP_CALL( SCIPcreateSolCopy(scip, &heurdata->addsol, sol) );
    334 SCIP_CALL( SCIPunlinkSol(scip, heurdata->addsol) );
    335 SCIPsolSetHeur(heurdata->addsol, heur);
    336 }
    337 }
    338
    339 return SCIP_OKAY;
    340}
    #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 SCIP_CALL(x)
    Definition: def.h:364
    SCIP_OBJSENSE SCIPgetObjsense(SCIP *scip)
    Definition: scip_prob.c:1400
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_RETCODE SCIPheurPassSolTrySol(SCIP *scip, SCIP_HEUR *heur, SCIP_SOL *sol)
    Definition: heur_trysol.c:259
    SCIP_RETCODE SCIPheurPassSolAddSol(SCIP *scip, SCIP_HEUR *heur, SCIP_SOL *sol)
    Definition: heur_trysol.c:301
    SCIP_RETCODE SCIPincludeHeurTrySol(SCIP *scip)
    Definition: heur_trysol.c:226
    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
    void SCIPheurMarkExact(SCIP_HEUR *heur)
    Definition: heur.c:1457
    const char * SCIPheurGetName(SCIP_HEUR *heur)
    Definition: heur.c:1467
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    SCIP_RETCODE SCIPcreateSolCopy(SCIP *scip, SCIP_SOL **sol, SCIP_SOL *sourcesol)
    Definition: scip_sol.c:882
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1250
    SCIP_RETCODE SCIPaddSolFree(SCIP *scip, SCIP_SOL **sol, SCIP_Bool *stored)
    Definition: scip_sol.c:3914
    SCIP_RETCODE SCIPunlinkSol(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1504
    SCIP_RETCODE SCIPtrySolFree(SCIP *scip, SCIP_SOL **sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
    Definition: scip_sol.c:4114
    SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1890
    void SCIPsolSetHeur(SCIP_SOL *sol, SCIP_HEUR *heur)
    Definition: sol.c:4319
    SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    static SCIP_DECL_HEURFREE(heurFreeTrySol)
    Definition: heur_trysol.c:96
    #define HEUR_TIMING
    Definition: heur_trysol.c:57
    #define HEUR_FREQOFS
    Definition: heur_trysol.c:55
    #define HEUR_DESC
    Definition: heur_trysol.c:51
    static SCIP_DECL_HEUREXEC(heurExecTrySol)
    Definition: heur_trysol.c:150
    #define HEUR_DISPCHAR
    Definition: heur_trysol.c:52
    #define HEUR_MAXDEPTH
    Definition: heur_trysol.c:56
    #define HEUR_PRIORITY
    Definition: heur_trysol.c:53
    #define HEUR_NAME
    Definition: heur_trysol.c:50
    static SCIP_DECL_HEUREXITSOL(heurExitTrySol)
    Definition: heur_trysol.c:119
    static SCIP_DECL_HEURCOPY(heurCopyTrySol)
    Definition: heur_trysol.c:81
    #define HEUR_FREQ
    Definition: heur_trysol.c:54
    #define HEUR_USESSUBSCIP
    Definition: heur_trysol.c:58
    primal heuristic that tries a given solution
    public methods for primal heuristics
    public methods for message output
    public methods for primal CIP solutions
    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 global and local (sub)problems
    public methods for solutions
    struct SCIP_HeurData SCIP_HEURDATA
    Definition: type_heur.h:77
    @ SCIP_OBJSENSE_MAXIMIZE
    Definition: type_prob.h:47
    @ 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