SCIP

    Solving Constraint Integer Programs

    heur_mutation.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_mutation.c
    26 * @ingroup DEFPLUGINS_HEUR
    27 * @brief LNS heuristic that tries to randomly mutate the incumbent solution
    28 * @author Timo Berthold
    29 */
    30
    31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    32
    34#include "scip/heuristics.h"
    35#include "scip/heur_mutation.h"
    36#include "scip/pub_heur.h"
    37#include "scip/pub_message.h"
    38#include "scip/pub_misc.h"
    39#include "scip/pub_sol.h"
    40#include "scip/pub_var.h"
    41#include "scip/scip_branch.h"
    42#include "scip/scip_cons.h"
    43#include "scip/scip_copy.h"
    44#include "scip/scip_general.h"
    45#include "scip/scip_heur.h"
    46#include "scip/scip_mem.h"
    47#include "scip/scip_message.h"
    48#include "scip/scip_nodesel.h"
    49#include "scip/scip_numerics.h"
    50#include "scip/scip_param.h"
    51#include "scip/scip_prob.h"
    53#include "scip/scip_sol.h"
    54#include "scip/scip_solve.h"
    56
    57
    58#define HEUR_NAME "mutation"
    59#define HEUR_DESC "mutation heuristic randomly fixing variables"
    60#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_LNS
    61#define HEUR_PRIORITY -1103010
    62#define HEUR_FREQ -1
    63#define HEUR_FREQOFS 8
    64#define HEUR_MAXDEPTH -1
    65#define HEUR_TIMING SCIP_HEURTIMING_AFTERNODE
    66#define HEUR_USESSUBSCIP TRUE /**< does the heuristic use a secondary SCIP instance? */
    67
    68#define DEFAULT_NODESOFS 500 /**< number of nodes added to the contingent of the total nodes */
    69#define DEFAULT_MAXNODES 5000 /**< maximum number of nodes to regard in the subproblem */
    70#define DEFAULT_MINIMPROVE 0.01 /**< factor by which Mutation should at least improve the incumbent */
    71#define DEFAULT_MINNODES 500 /**< minimum number of nodes to regard in the subproblem */
    72#define DEFAULT_MINFIXINGRATE 0.8 /**< minimum percentage of integer variables that have to be fixed */
    73#define DEFAULT_NODESQUOT 0.1 /**< subproblem nodes in relation to nodes of the original problem */
    74#define DEFAULT_NWAITINGNODES 200 /**< number of nodes without incumbent change that heuristic should wait */
    75#define DEFAULT_USELPROWS FALSE /**< should subproblem be created out of the rows in the LP rows,
    76 * otherwise, the copy constructors of the constraints handlers are used */
    77#define DEFAULT_COPYCUTS TRUE /**< if DEFAULT_USELPROWS is FALSE, then should all active cuts from the
    78 * cutpool of the original scip be copied to constraints of the subscip */
    79#define DEFAULT_BESTSOLLIMIT -1 /**< limit on number of improving incumbent solutions in sub-CIP */
    80#define DEFAULT_USEUCT FALSE /**< should uct node selection be used at the beginning of the search? */
    81#define DEFAULT_RANDSEED 19 /**< initial random seed */
    82/*
    83 * Data structures
    84 */
    85
    86/** primal heuristic data */
    87struct SCIP_HeurData
    88{
    89 int nodesofs; /**< number of nodes added to the contingent of the total nodes */
    90 int maxnodes; /**< maximum number of nodes to regard in the subproblem */
    91 int minnodes; /**< minimum number of nodes to regard in the subproblem */
    92 SCIP_Real minfixingrate; /**< minimum percentage of integer variables that have to be fixed */
    93 int nwaitingnodes; /**< number of nodes without incumbent change that heuristic should wait */
    94 SCIP_Real minimprove; /**< factor by which Mutation should at least improve the incumbent */
    95 SCIP_Longint usednodes; /**< nodes already used by Mutation in earlier calls */
    96 SCIP_Real nodesquot; /**< subproblem nodes in relation to nodes of the original problem */
    97 SCIP_RANDNUMGEN* randnumgen; /**< random number generator */
    98 SCIP_Bool uselprows; /**< should subproblem be created out of the rows in the LP rows? */
    99 SCIP_Bool copycuts; /**< if uselprows == FALSE, should all active cuts from cutpool be copied
    100 * to constraints in subproblem?
    101 */
    102 int bestsollimit; /**< limit on number of improving incumbent solutions in sub-CIP */
    103 SCIP_Bool useuct; /**< should uct node selection be used at the beginning of the search? */
    104};
    105
    106
    107/*
    108 * Local methods
    109 */
    110
    111/** determine variables and values which should be fixed in the mutation subproblem */
    112static
    114 SCIP* scip, /**< original SCIP data structure */
    115 SCIP_VAR** fixedvars, /**< array to store the variables that should be fixed in the subproblem */
    116 SCIP_Real* fixedvals, /**< array to store the fixing values to fix variables in the subproblem */
    117 int* nfixedvars, /**< pointer to store the number of variables that should be fixed */
    118 SCIP_Real minfixingrate, /**< percentage of integer variables that have to be fixed */
    119 SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
    120 SCIP_Bool* success /**< used to store whether the creation of the subproblem worked */
    121 )
    122{
    123 SCIP_VAR** vars; /* original scip variables */
    124 SCIP_SOL* sol; /* pool of solutions */
    125
    126 int nvars;
    127 int nbinvars;
    128 int nintvars;
    129 int ndiscretevars;
    130 int i;
    131
    132 assert(fixedvars != NULL);
    133 assert(fixedvals != NULL);
    134
    135 /* get required data of the original problem */
    136 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
    137 sol = SCIPgetBestSol(scip);
    138 assert(sol != NULL);
    139
    140 /* compute the number of variables that should be fixed in the subproblem */
    141 *nfixedvars = (int)(minfixingrate * (nbinvars + nintvars));
    142
    143 /* avoid the two corner cases that no or all discrete variables should be fixed */
    144 if( *nfixedvars == 0 || *nfixedvars == nbinvars + nintvars )
    145 {
    146 *success = FALSE;
    147 return SCIP_OKAY;
    148 }
    149 assert(*nfixedvars < nbinvars + nintvars);
    150
    151 ndiscretevars = nbinvars + nintvars;
    152 /* copy the binary and integer variables into fixedvars */
    153 BMScopyMemoryArray(fixedvars, vars, ndiscretevars);
    154
    155 /* shuffle the array randomly */
    156 SCIPrandomPermuteArray(randnumgen, (void **)fixedvars, 0, nbinvars + nintvars);
    157
    158 *success = TRUE;
    159 /* store the fixing values for the subset of variables that should be fixed */
    160 for( i = 0; i < *nfixedvars; ++i )
    161 {
    162 /* fix all randomly marked variables */
    163 SCIP_Real solval;
    164 SCIP_Real lb;
    165 SCIP_Real ub;
    166
    167 solval = SCIPgetSolVal(scip, sol, fixedvars[i]);
    168 lb = SCIPvarGetLbGlobal(fixedvars[i]);
    169 ub = SCIPvarGetUbGlobal(fixedvars[i]);
    170 assert(SCIPisLE(scip, lb, ub));
    171
    172 /* due to dual reductions, it may happen that the solution value is not in
    173 the variable's domain anymore */
    174 if( SCIPisLT(scip, solval, lb) )
    175 solval = lb;
    176 else if( SCIPisGT(scip, solval, ub) )
    177 solval = ub;
    178
    179 /* we cannot fix to infinite solution values, better break in this case */
    180 if( SCIPisInfinity(scip, REALABS(solval)) )
    181 {
    182 *success = FALSE;
    183 break;
    184 }
    185
    186 /* store the possibly adjusted solution value as fixing value */
    187 fixedvals[i] = solval;
    188 }
    189
    190 return SCIP_OKAY;
    191}
    192
    193/** setup and solve mutation sub-SCIP */
    194static
    196 SCIP* scip, /**< SCIP data structure */
    197 SCIP* subscip, /**< sub-SCIP data structure */
    198 SCIP_HEUR* heur, /**< mutation heuristic */
    199 SCIP_VAR** fixedvars, /**< array to store the variables that should be fixed in the subproblem */
    200 SCIP_Real* fixedvals, /**< array to store the fixing values to fix variables in the subproblem */
    201 int nfixedvars, /**< the number of variables that should be fixed */
    202 SCIP_Longint nsubnodes, /**< node limit for the subproblem */
    203 SCIP_RESULT* result /**< pointer to store the result */
    204 )
    205{
    206 SCIP_VAR** subvars; /* subproblem's variables */
    207 SCIP_VAR** vars; /* original problem's variables */
    208 SCIP_HASHMAP* varmapfw; /* mapping of SCIP variables to sub-SCIP variables */
    209 SCIP_HEURDATA* heurdata;
    210 SCIP_Real cutoff; /* objective cutoff for the subproblem */
    211 SCIP_Real upperbound;
    212 int nvars; /* number of original problem's variables */
    213 int i;
    214 SCIP_Bool success;
    215
    216 assert(scip != NULL);
    217 assert(subscip != NULL);
    218 assert(heur != NULL);
    219 assert(fixedvars != NULL);
    220 assert(fixedvals != NULL);
    221
    222 heurdata = SCIPheurGetData(heur);
    223 assert(heurdata != NULL);
    224
    225 vars = SCIPgetVars(scip);
    226 nvars = SCIPgetNVars(scip);
    227
    228 SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
    229
    230 /* create the variable mapping hash map */
    231 SCIP_CALL( SCIPhashmapCreate(&varmapfw, SCIPblkmem(subscip), nvars) );
    232
    233 /* create a problem copy as sub SCIP */
    234 SCIP_CALL( SCIPcopyLargeNeighborhoodSearch(scip, subscip, varmapfw, "mutation", fixedvars, fixedvals, nfixedvars,
    235 heurdata->uselprows, heurdata->copycuts, &success, NULL) );
    236
    237 for( i = 0; i < nvars; i++ )
    238 subvars[i] = (SCIP_VAR*) SCIPhashmapGetImage(varmapfw, vars[i]);
    239
    240 /* free hash map */
    241 SCIPhashmapFree(&varmapfw);
    242
    243 /* do not abort subproblem on CTRL-C */
    244 SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
    245
    246#ifdef SCIP_DEBUG
    247 /* for debugging, enable full output */
    248 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) );
    249 SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 100000000) );
    250#else
    251 /* disable statistic timing inside sub SCIP and output to console */
    252 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
    253 SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
    254#endif
    255
    256 /* set limits for the subproblem */
    257 SCIP_CALL( SCIPcopyLimits(scip, subscip) );
    258 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", nsubnodes) );
    259 SCIP_CALL( SCIPsetIntParam(subscip, "limits/bestsol", heurdata->bestsollimit) );
    260
    261 /* forbid recursive call of heuristics and separators solving subMIPs */
    262 SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );
    263
    264 /* disable cutting plane separation */
    266
    267 /* disable expensive presolving */
    269
    270 /* use best estimate node selection */
    271 if( SCIPfindNodesel(subscip, "estimate") != NULL && !SCIPisParamFixed(subscip, "nodeselection/estimate/stdpriority") )
    272 {
    273 SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/estimate/stdpriority", INT_MAX/4) );
    274 }
    275
    276 /* activate uct node selection at the top of the tree */
    277 if( heurdata->useuct && SCIPfindNodesel(subscip, "uct") != NULL && !SCIPisParamFixed(subscip, "nodeselection/uct/stdpriority") )
    278 {
    279 SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/uct/stdpriority", INT_MAX/2) );
    280 }
    281
    282 /* use inference branching */
    283 if( SCIPfindBranchrule(subscip, "inference") != NULL && !SCIPisParamFixed(subscip, "branching/inference/priority") )
    284 {
    285 SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
    286 }
    287
    288 /* enable conflict analysis, disable analysis of boundexceeding LPs, and restrict conflict pool */
    289 if( !SCIPisParamFixed(subscip, "conflict/enable") )
    290 {
    291 SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/enable", TRUE) );
    292 }
    293 if( !SCIPisParamFixed(subscip, "conflict/useboundlp") )
    294 {
    295 SCIP_CALL( SCIPsetCharParam(subscip, "conflict/useboundlp", 'o') );
    296 }
    297 if( !SCIPisParamFixed(subscip, "conflict/maxstoresize") )
    298 {
    299 SCIP_CALL( SCIPsetIntParam(subscip, "conflict/maxstoresize", 100) );
    300 }
    301
    302 /* speed up sub-SCIP by not checking dual LP feasibility */
    303 SCIP_CALL( SCIPsetBoolParam(subscip, "lp/checkdualfeas", FALSE) );
    304
    305 /* add an objective cutoff */
    307
    308 upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);
    310 {
    311 cutoff = (1 - heurdata->minimprove) * SCIPgetUpperbound(scip)
    312 + heurdata->minimprove * SCIPgetLowerbound(scip);
    313 }
    314 else
    315 {
    316 if( SCIPgetUpperbound(scip) >= 0 )
    317 cutoff = (1 - heurdata->minimprove) * SCIPgetUpperbound(scip);
    318 else
    319 cutoff = (1 + heurdata->minimprove) * SCIPgetUpperbound(scip);
    320 }
    321 cutoff = MIN(upperbound, cutoff);
    322 SCIP_CALL( SCIPsetObjlimit(subscip, cutoff) );
    323
    324 /* solve the subproblem
    325 *
    326 * Errors in solving the subproblem should not kill the overall solving process
    327 * Hence, the return code is caught but only in debug mode, SCIP will stop.
    328 */
    329 SCIPdebugMsg(scip, "Solve Mutation subMIP\n");
    330 SCIP_CALL_ABORT( SCIPsolve(subscip) );
    331
    332 /* transfer variable statistics from sub-SCIP */
    333 SCIP_CALL( SCIPmergeVariableStatistics(subscip, scip, subvars, vars, nvars) );
    334
    335 /* print solving statistics of subproblem if we are in SCIP's debug mode */
    337
    338 heurdata->usednodes += SCIPgetNNodes(subscip);
    339
    340 /* check, whether a solution was found;
    341 * due to numerics, it might happen that not all solutions are feasible -> try all solutions until one was accepted
    342 */
    343 SCIP_CALL( SCIPtranslateSubSols(scip, subscip, heur, subvars, &success, NULL) );
    344 if( success )
    345 *result = SCIP_FOUNDSOL;
    346
    347 /* free subproblem */
    348 SCIPfreeBufferArray(scip, &subvars);
    349
    350 return SCIP_OKAY;
    351}
    352
    353
    354/*
    355 * Callback methods of primal heuristic
    356 */
    357
    358/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
    359static
    360SCIP_DECL_HEURCOPY(heurCopyMutation)
    361{ /*lint --e{715}*/
    362 assert(scip != NULL);
    363 assert(heur != NULL);
    364
    366
    367 /* call inclusion method of primal heuristic */
    369
    370 return SCIP_OKAY;
    371}
    372
    373/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
    374static
    375SCIP_DECL_HEURFREE(heurFreeMutation)
    376{ /*lint --e{715}*/
    377 SCIP_HEURDATA* heurdata;
    378
    379 assert(heur != NULL);
    380 assert(scip != NULL);
    381
    382 /* get heuristic data */
    383 heurdata = SCIPheurGetData(heur);
    384 assert(heurdata != NULL);
    385
    386 /* free heuristic data */
    387 SCIPfreeBlockMemory(scip, &heurdata);
    388 SCIPheurSetData(heur, NULL);
    389
    390 return SCIP_OKAY;
    391}
    392
    393/** initialization method of primal heuristic (called after problem was transformed) */
    394static
    395SCIP_DECL_HEURINIT(heurInitMutation)
    396{ /*lint --e{715}*/
    397 SCIP_HEURDATA* heurdata;
    398
    399 assert(heur != NULL);
    400 assert(scip != NULL);
    401
    402 /* get heuristic's data */
    403 heurdata = SCIPheurGetData(heur);
    404 assert(heurdata != NULL);
    405
    406 /* initialize data */
    407 heurdata->usednodes = 0;
    408
    409 /* create random number generator */
    410 SCIP_CALL( SCIPcreateRandom(scip, &heurdata->randnumgen,
    412
    413 return SCIP_OKAY;
    414}
    415
    416/** deinitialization method of primal heuristic */
    417static
    418SCIP_DECL_HEUREXIT(heurExitMutation)
    419{ /*lint --e{715}*/
    420 SCIP_HEURDATA* heurdata;
    421
    422 assert(heur != NULL);
    423 assert(scip != NULL);
    424
    425 /* get heuristic data */
    426 heurdata = SCIPheurGetData(heur);
    427 assert(heurdata != NULL);
    428
    429 /* free random number generator */
    430 SCIPfreeRandom(scip, &heurdata->randnumgen);
    431
    432 return SCIP_OKAY;
    433}
    434
    435/** execution method of primal heuristic */
    436static
    437SCIP_DECL_HEUREXEC(heurExecMutation)
    438{ /*lint --e{715}*/
    439 SCIP_Longint maxnnodes;
    440 SCIP_Longint nsubnodes; /* node limit for the subproblem */
    441
    442 SCIP_HEURDATA* heurdata; /* heuristic's data */
    443 SCIP* subscip; /* the subproblem created by mutation */
    444 SCIP_VAR** fixedvars; /* array to store variables that should be fixed in the subproblem */
    445 SCIP_Real* fixedvals; /* array to store fixing values for the variables */
    446
    447 SCIP_Real maxnnodesr;
    448
    449 int nfixedvars;
    450 int nbinvars;
    451 int nintvars;
    452
    453 SCIP_Bool success;
    454
    455 SCIP_RETCODE retcode;
    456
    457 assert( heur != NULL );
    458 assert( scip != NULL );
    459 assert( result != NULL );
    460
    461 /* get heuristic's data */
    462 heurdata = SCIPheurGetData(heur);
    463 assert(heurdata != NULL);
    464
    465 *result = SCIP_DELAYED;
    466
    467 /* only call heuristic, if feasible solution is available */
    468 if( SCIPgetNSols(scip) <= 0 )
    469 return SCIP_OKAY;
    470
    471 /* only call heuristic, if the best solution comes from transformed problem */
    472 assert(SCIPgetBestSol(scip) != NULL);
    474 return SCIP_OKAY;
    475
    476 /* only call heuristic, if enough nodes were processed since last incumbent */
    477 if( SCIPgetNNodes(scip) - SCIPgetSolNodenum(scip,SCIPgetBestSol(scip)) < heurdata->nwaitingnodes)
    478 return SCIP_OKAY;
    479
    480 *result = SCIP_DIDNOTRUN;
    481
    482 SCIP_CALL( SCIPgetVarsData(scip, NULL, NULL, &nbinvars, &nintvars, NULL, NULL) );
    483
    484 /* only call heuristic, if discrete variables are present */
    485 if( nbinvars + nintvars == 0 )
    486 return SCIP_OKAY;
    487
    488 /* calculate the maximal number of branching nodes until heuristic is aborted */
    489 maxnnodesr = heurdata->nodesquot * SCIPgetNNodes(scip);
    490
    491 /* reward mutation if it succeeded often, count the setup costs for the sub-MIP as 100 nodes */
    492 maxnnodesr *= 1.0 + 2.0 * (SCIPheurGetNBestSolsFound(heur)+1.0)/(SCIPheurGetNCalls(heur) + 1.0);
    493 maxnnodes = (SCIP_Longint) maxnnodesr - 100 * SCIPheurGetNCalls(heur);
    494 maxnnodes += heurdata->nodesofs;
    495
    496 /* determine the node limit for the current process */
    497 nsubnodes = maxnnodes - heurdata->usednodes;
    498 nsubnodes = MIN(nsubnodes, heurdata->maxnodes);
    499
    500 /* check whether we have enough nodes left to call subproblem solving */
    501 if( nsubnodes < heurdata->minnodes )
    502 return SCIP_OKAY;
    503
    504 if( SCIPisStopped(scip) )
    505 return SCIP_OKAY;
    506
    507 /* check whether there is enough time and memory left */
    508 SCIP_CALL( SCIPcheckCopyLimits(scip, &success) );
    509
    510 if( !success )
    511 return SCIP_OKAY;
    512
    513 SCIP_CALL( SCIPallocBufferArray(scip, &fixedvars, nbinvars + nintvars) );
    514 SCIP_CALL( SCIPallocBufferArray(scip, &fixedvals, nbinvars + nintvars) );
    515
    516 /* determine variables that should be fixed in the mutation subproblem */
    517 SCIP_CALL( determineVariableFixings(scip, fixedvars, fixedvals, &nfixedvars, heurdata->minfixingrate, heurdata->randnumgen, &success) );
    518
    519 /* terminate if it is not possible to create the subproblem */
    520 if( !success )
    521 {
    522 SCIPdebugMsg(scip, "Could not create the subproblem -> skip call\n");
    523 goto TERMINATE;
    524 }
    525
    526 *result = SCIP_DIDNOTFIND;
    527
    528 /* initializing the subproblem */
    529 SCIP_CALL( SCIPcreate(&subscip) );
    530
    531 /* setup and solve the subproblem and catch the return code */
    532 retcode = setupAndSolveSubscipMutation(scip, subscip, heur, fixedvars, fixedvals, nfixedvars, nsubnodes, result);
    533
    534 /* free the subscip in any case */
    535 SCIP_CALL( SCIPfree(&subscip) );
    536 SCIP_CALL( retcode );
    537
    538 /* free storage for subproblem fixings */
    539 TERMINATE:
    540 SCIPfreeBufferArray(scip, &fixedvals);
    541 SCIPfreeBufferArray(scip, &fixedvars);
    542
    543 return SCIP_OKAY;
    544}
    545
    546/*
    547 * primal heuristic specific interface methods
    548 */
    549
    550/** creates the mutation primal heuristic and includes it in SCIP */
    552 SCIP* scip /**< SCIP data structure */
    553 )
    554{
    555 SCIP_HEURDATA* heurdata;
    556 SCIP_HEUR* heur;
    557
    558 /* create Mutation primal heuristic data */
    559 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    560
    561 /* include primal heuristic */
    564 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecMutation, heurdata) );
    565
    566 assert(heur != NULL);
    567
    568 /* primal heuristic is safe to use in exact solving mode */
    569 SCIPheurMarkExact(heur);
    570
    571 /* set non-NULL pointers to callback methods */
    572 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyMutation) );
    573 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeMutation) );
    574 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitMutation) );
    575 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitMutation) );
    576
    577 /* add mutation primal heuristic parameters */
    578 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/nodesofs",
    579 "number of nodes added to the contingent of the total nodes",
    580 &heurdata->nodesofs, FALSE, DEFAULT_NODESOFS, 0, INT_MAX, NULL, NULL) );
    581
    582 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
    583 "maximum number of nodes to regard in the subproblem",
    584 &heurdata->maxnodes, TRUE, DEFAULT_MAXNODES, 0, INT_MAX, NULL, NULL) );
    585
    586 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/minnodes",
    587 "minimum number of nodes required to start the subproblem",
    588 &heurdata->minnodes, TRUE, DEFAULT_MINNODES, 0, INT_MAX, NULL, NULL) );
    589
    590 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/nwaitingnodes",
    591 "number of nodes without incumbent change that heuristic should wait",
    592 &heurdata->nwaitingnodes, TRUE, DEFAULT_NWAITINGNODES, 0, INT_MAX, NULL, NULL) );
    593
    594 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesquot",
    595 "contingent of sub problem nodes in relation to the number of nodes of the original problem",
    596 &heurdata->nodesquot, FALSE, DEFAULT_NODESQUOT, 0.0, 1.0, NULL, NULL) );
    597
    598 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minfixingrate",
    599 "percentage of integer variables that have to be fixed",
    600 &heurdata->minfixingrate, FALSE, DEFAULT_MINFIXINGRATE, SCIPsumepsilon(scip), 1.0-SCIPsumepsilon(scip), NULL, NULL) );
    601
    602 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprove",
    603 "factor by which " HEUR_NAME " should at least improve the incumbent",
    604 &heurdata->minimprove, TRUE, DEFAULT_MINIMPROVE, 0.0, 1.0, NULL, NULL) );
    605
    606 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/uselprows",
    607 "should subproblem be created out of the rows in the LP rows?",
    608 &heurdata->uselprows, TRUE, DEFAULT_USELPROWS, NULL, NULL) );
    609
    610 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/copycuts",
    611 "if uselprows == FALSE, should all active cuts from cutpool be copied to constraints in subproblem?",
    612 &heurdata->copycuts, TRUE, DEFAULT_COPYCUTS, NULL, NULL) );
    613
    614 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/bestsollimit",
    615 "limit on number of improving incumbent solutions in sub-CIP",
    616 &heurdata->bestsollimit, FALSE, DEFAULT_BESTSOLLIMIT, -1, INT_MAX, NULL, NULL) );
    617
    618 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/useuct",
    619 "should uct node selection be used at the beginning of the search?",
    620 &heurdata->useuct, TRUE, DEFAULT_USEUCT, NULL, NULL) );
    621
    622 return SCIP_OKAY;
    623}
    #define NULL
    Definition: def.h:257
    #define SCIP_Longint
    Definition: def.h:150
    #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 SCIP_CALL_ABORT(x)
    Definition: def.h:343
    #define REALABS(x)
    Definition: def.h:191
    #define SCIP_CALL(x)
    Definition: def.h:364
    SCIP_RETCODE SCIPtranslateSubSols(SCIP *scip, SCIP *subscip, SCIP_HEUR *heur, SCIP_VAR **subvars, SCIP_Bool *success, int *solindex)
    Definition: scip_copy.c:1438
    SCIP_RETCODE SCIPcheckCopyLimits(SCIP *sourcescip, SCIP_Bool *success)
    Definition: scip_copy.c:3250
    SCIP_RETCODE SCIPmergeVariableStatistics(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR **sourcevars, SCIP_VAR **targetvars, int nvars)
    Definition: scip_copy.c:1255
    SCIP_RETCODE SCIPcopyLimits(SCIP *sourcescip, SCIP *targetscip)
    Definition: scip_copy.c:3293
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:767
    SCIP_RETCODE SCIPfree(SCIP **scip)
    Definition: scip_general.c:402
    SCIP_RETCODE SCIPcreate(SCIP **scip)
    Definition: scip_general.c:370
    SCIP_RETCODE SCIPsetObjlimit(SCIP *scip, SCIP_Real objlimit)
    Definition: scip_prob.c:1661
    SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
    Definition: scip_prob.c:2115
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    SCIP_VAR ** SCIPgetVars(SCIP *scip)
    Definition: scip_prob.c:2201
    void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
    Definition: misc.c:3095
    void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3284
    SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
    Definition: misc.c:3061
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_Bool SCIPisParamFixed(SCIP *scip, const char *name)
    Definition: scip_param.c:219
    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 SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
    Definition: scip_param.c:545
    SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:139
    SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
    Definition: scip_param.c:487
    SCIP_RETCODE SCIPsetSubscipsOff(SCIP *scip, SCIP_Bool quiet)
    Definition: scip_param.c:904
    SCIP_RETCODE SCIPsetPresolving(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
    Definition: scip_param.c:956
    SCIP_RETCODE SCIPsetCharParam(SCIP *scip, const char *name, char value)
    Definition: scip_param.c:661
    SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:57
    SCIP_RETCODE SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
    Definition: scip_param.c:429
    SCIP_RETCODE SCIPsetSeparating(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
    Definition: scip_param.c:985
    void SCIPrandomPermuteArray(SCIP_RANDNUMGEN *randnumgen, void **array, int begin, int end)
    Definition: misc.c:10294
    SCIP_RETCODE SCIPincludeHeurMutation(SCIP *scip)
    SCIP_BRANCHRULE * SCIPfindBranchrule(SCIP *scip, const char *name)
    Definition: scip_branch.c:304
    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
    SCIP_Longint SCIPheurGetNBestSolsFound(SCIP_HEUR *heur)
    Definition: heur.c:1613
    SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
    Definition: heur.c:1593
    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
    void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
    Definition: heur.c:1378
    BMS_BLKMEM * SCIPblkmem(SCIP *scip)
    Definition: scip_mem.c:57
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    SCIP_NODESEL * SCIPfindNodesel(SCIP *scip, const char *name)
    Definition: scip_nodesel.c:242
    SCIP_SOL * SCIPgetBestSol(SCIP *scip)
    Definition: scip_sol.c:2986
    int SCIPgetNSols(SCIP *scip)
    Definition: scip_sol.c:2887
    SCIP_Bool SCIPsolIsOriginal(SCIP_SOL *sol)
    Definition: sol.c:4155
    SCIP_Longint SCIPgetSolNodenum(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:2221
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1763
    SCIP_RETCODE SCIPsolve(SCIP *scip)
    Definition: scip_solve.c:2611
    SCIP_Real SCIPgetUpperbound(SCIP *scip)
    SCIP_Longint SCIPgetNNodes(SCIP *scip)
    SCIP_RETCODE SCIPprintStatistics(SCIP *scip, FILE *file)
    SCIP_Real SCIPgetLowerbound(SCIP *scip)
    SCIP_RETCODE SCIPcopyLargeNeighborhoodSearch(SCIP *sourcescip, SCIP *subscip, SCIP_HASHMAP *varmap, const char *suffix, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int nfixedvars, SCIP_Bool uselprows, SCIP_Bool copycuts, SCIP_Bool *success, SCIP_Bool *valid)
    Definition: heuristics.c:953
    SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPsumepsilon(SCIP *scip)
    SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24174
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24152
    void SCIPfreeRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen)
    SCIP_RETCODE SCIPcreateRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen, unsigned int initialseed, SCIP_Bool useglobalseed)
    #define DEFAULT_NODESQUOT
    Definition: heur_mutation.c:73
    #define DEFAULT_NWAITINGNODES
    Definition: heur_mutation.c:74
    #define DEFAULT_NODESOFS
    Definition: heur_mutation.c:68
    #define DEFAULT_COPYCUTS
    Definition: heur_mutation.c:77
    #define DEFAULT_MAXNODES
    Definition: heur_mutation.c:69
    #define HEUR_TIMING
    Definition: heur_mutation.c:65
    #define DEFAULT_MINNODES
    Definition: heur_mutation.c:71
    #define HEUR_FREQOFS
    Definition: heur_mutation.c:63
    #define HEUR_DESC
    Definition: heur_mutation.c:59
    #define DEFAULT_MINFIXINGRATE
    Definition: heur_mutation.c:72
    #define DEFAULT_USEUCT
    Definition: heur_mutation.c:80
    #define HEUR_DISPCHAR
    Definition: heur_mutation.c:60
    #define HEUR_MAXDEPTH
    Definition: heur_mutation.c:64
    static SCIP_RETCODE setupAndSolveSubscipMutation(SCIP *scip, SCIP *subscip, SCIP_HEUR *heur, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int nfixedvars, SCIP_Longint nsubnodes, SCIP_RESULT *result)
    #define HEUR_PRIORITY
    Definition: heur_mutation.c:61
    static SCIP_RETCODE determineVariableFixings(SCIP *scip, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int *nfixedvars, SCIP_Real minfixingrate, SCIP_RANDNUMGEN *randnumgen, SCIP_Bool *success)
    static SCIP_DECL_HEUREXEC(heurExecMutation)
    #define DEFAULT_MINIMPROVE
    Definition: heur_mutation.c:70
    #define HEUR_NAME
    Definition: heur_mutation.c:58
    #define DEFAULT_USELPROWS
    Definition: heur_mutation.c:75
    #define DEFAULT_BESTSOLLIMIT
    Definition: heur_mutation.c:79
    static SCIP_DECL_HEUREXIT(heurExitMutation)
    static SCIP_DECL_HEURFREE(heurFreeMutation)
    #define DEFAULT_RANDSEED
    Definition: heur_mutation.c:81
    #define HEUR_FREQ
    Definition: heur_mutation.c:62
    #define HEUR_USESSUBSCIP
    Definition: heur_mutation.c:66
    static SCIP_DECL_HEURINIT(heurInitMutation)
    static SCIP_DECL_HEURCOPY(heurCopyMutation)
    LNS heuristic that tries to randomly mutate the incumbent solution.
    methods commonly used by primal heuristics
    memory allocation routines
    #define BMScopyMemoryArray(ptr, source, num)
    Definition: memory.h:134
    public methods for primal heuristics
    public methods for message output
    #define SCIPdebug(x)
    Definition: pub_message.h:93
    public data structures and miscellaneous methods
    public methods for primal CIP solutions
    public methods for problem variables
    public methods for branching rule plugins and branching
    public methods for constraint handler plugins and constraints
    public methods for problem copies
    general public methods
    public methods for primal heuristic plugins and divesets
    public methods for memory management
    public methods for message handling
    public methods for node selector plugins
    public methods for numerical tolerances
    public methods for SCIP parameter handling
    public methods for global and local (sub)problems
    public methods for random numbers
    public methods for solutions
    public solving methods
    public methods for querying solving statistics
    struct SCIP_HeurData SCIP_HEURDATA
    Definition: type_heur.h:77
    @ SCIP_PARAMSETTING_OFF
    Definition: type_paramset.h:63
    @ SCIP_PARAMSETTING_FAST
    Definition: type_paramset.h:62
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_DELAYED
    Definition: type_result.h:43
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_FOUNDSOL
    Definition: type_result.h:56
    enum SCIP_Result SCIP_RESULT
    Definition: type_result.h:61
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63