Scippy

    SCIP

    Solving Constraint Integer Programs

    heur_rins.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-2025 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_rins.c
    26 * @ingroup DEFPLUGINS_HEUR
    27 * @brief LNS heuristic that combines the incumbent with the LP optimum
    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_rins.h"
    36#include "scip/pub_event.h"
    37#include "scip/pub_heur.h"
    38#include "scip/pub_message.h"
    39#include "scip/pub_misc.h"
    40#include "scip/pub_sol.h"
    41#include "scip/pub_var.h"
    42#include "scip/scip_branch.h"
    43#include "scip/scip_cons.h"
    44#include "scip/scip_copy.h"
    45#include "scip/scip_event.h"
    46#include "scip/scip_general.h"
    47#include "scip/scip_heur.h"
    48#include "scip/scip_lp.h"
    49#include "scip/scip_mem.h"
    50#include "scip/scip_message.h"
    51#include "scip/scip_nodesel.h"
    52#include "scip/scip_numerics.h"
    53#include "scip/scip_param.h"
    54#include "scip/scip_prob.h"
    55#include "scip/scip_sol.h"
    56#include "scip/scip_solve.h"
    58#include <string.h>
    59
    60#define HEUR_NAME "rins"
    61#define HEUR_DESC "relaxation induced neighborhood search by Danna, Rothberg, and Le Pape"
    62#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_LNS
    63#define HEUR_PRIORITY -1101000
    64#define HEUR_FREQ 15
    65#define HEUR_FREQOFS 0
    66#define HEUR_MAXDEPTH -1
    67#define HEUR_TIMING SCIP_HEURTIMING_AFTERLPNODE
    68#define HEUR_USESSUBSCIP TRUE /**< does the heuristic use a secondary SCIP instance? */
    69
    70#define DEFAULT_NODESOFS 500 /* number of nodes added to the contingent of the total nodes */
    71#define DEFAULT_MAXNODES 5000 /* maximum number of nodes to regard in the subproblem */
    72#define DEFAULT_MINNODES 50 /* minimum number of nodes to regard in the subproblem */
    73#define DEFAULT_MINIMPROVE 0.01 /* factor by which RINS should at least improve the incumbent */
    74#define DEFAULT_MINFIXINGRATE 0.3 /* minimum percentage of integer variables that have to be fixed */
    75#define DEFAULT_NODESQUOT 0.3 /* subproblem nodes in relation to nodes of the original problem */
    76#define DEFAULT_LPLIMFAC 2.0 /* factor by which the limit on the number of LP depends on the node limit */
    77#define DEFAULT_NWAITINGNODES 200 /* number of nodes without incumbent change that heuristic should wait */
    78#define DEFAULT_USELPROWS FALSE /* should subproblem be created out of the rows in the LP rows,
    79 * otherwise, the copy constructors of the constraints handlers are used */
    80#define DEFAULT_COPYCUTS TRUE /* if DEFAULT_USELPROWS is FALSE, then should all active cuts from the cutpool
    81 * of the original scip be copied to constraints of the subscip
    82 */
    83#define DEFAULT_USEUCT FALSE /* should uct node selection be used at the beginning of the search? */
    85/* event handler properties */
    86#define EVENTHDLR_NAME "Rins"
    87#define EVENTHDLR_DESC "LP event handler for " HEUR_NAME " heuristic"
    88
    89/*
    90 * Data structures
    91 */
    92
    93/** primal heuristic data */
    94struct SCIP_HeurData
    95{
    96 int nodesofs; /**< number of nodes added to the contingent of the total nodes */
    97 int maxnodes; /**< maximum number of nodes to regard in the subproblem */
    98 int minnodes; /**< minimum number of nodes to regard in the subproblem */
    99 SCIP_Real minfixingrate; /**< minimum percentage of integer variables that have to be fixed */
    100 int nwaitingnodes; /**< number of nodes without incumbent change that heuristic should wait */
    101 SCIP_Real minimprove; /**< factor by which RINS should at least improve the incumbent */
    102 SCIP_Real nodelimit; /**< the nodelimit employed in the current sub-SCIP, for the event handler*/
    103 SCIP_Real lplimfac; /**< factor by which the limit on the number of LP depends on the node limit */
    104 SCIP_Longint usednodes; /**< nodes already used by RINS in earlier calls */
    105 SCIP_Real nodesquot; /**< subproblem nodes in relation to nodes of the original problem */
    106 SCIP_Bool uselprows; /**< should subproblem be created out of the rows in the LP rows? */
    107 SCIP_Bool copycuts; /**< if uselprows == FALSE, should all active cuts from cutpool be copied
    108 * to constraints in subproblem?
    109 */
    110 SCIP_Bool useuct; /**< should uct node selection be used at the beginning of the search? */
    111};
    112
    113/*
    114 * Local methods
    115 */
    116
    117
    118
    119
    120/** determines variable fixings for RINS
    121 *
    122 * RINS fixes variables with matching solution values in the current LP and the
    123 * incumbent solution
    124 */
    125static
    127 SCIP* scip, /**< original SCIP data structure */
    128 SCIP_VAR** fixedvars, /**< array to store source SCIP variables that should be fixed in the copy */
    129 SCIP_Real* fixedvals, /**< array to store fixing values for variables that should be fixed in the copy */
    130 int* nfixedvars, /**< pointer to store the number of variables that RINS can fix */
    131 int fixedvarssize, /**< size of the buffer arrays to store potential fixings */
    132 SCIP_Real minfixingrate, /**< percentage of integer variables that have to be fixed */
    133 SCIP_Bool* success /**< pointer to store whether sufficiently many variable fixings were found */
    134 )
    135{
    136 SCIP_SOL* bestsol; /* incumbent solution of the original problem */
    137 SCIP_VAR** vars; /* original scip variables */
    138 SCIP_Real fixingrate;
    139
    140 int nvars;
    141 int nbinvars;
    142 int nintvars;
    143 int i;
    144 int fixingcounter;
    145
    146 assert(fixedvals != NULL);
    147 assert(fixedvars != NULL);
    148 assert(nfixedvars != NULL);
    149
    150 /* get required data of the original problem */
    151 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
    152 bestsol = SCIPgetBestSol(scip);
    153 assert(bestsol != NULL);
    154
    155 fixingcounter = 0;
    156 assert(fixedvarssize >= nbinvars + nintvars);
    157
    158 /* determine variables to fix in the subproblem */
    159 for( i = 0; i < nbinvars + nintvars; i++ )
    160 {
    161 SCIP_Real lpsolval;
    162 SCIP_Real solval;
    163
    164 /* get the current LP solution and the incumbent solution for each variable */
    165 lpsolval = SCIPvarGetLPSol(vars[i]);
    166 solval = SCIPgetSolVal(scip, bestsol, vars[i]);
    167
    168 /* iff both solutions are equal, variable is stored to be fixed */
    169 if( SCIPisFeasEQ(scip, lpsolval, solval) )
    170 {
    171 /* store the fixing and increase the number of fixed variables */
    172 fixedvars[fixingcounter] = vars[i];
    173 fixedvals[fixingcounter] = solval;
    174 fixingcounter++;
    175 }
    176 }
    177
    178 /* store the number of fixings */
    179 *nfixedvars = fixingcounter;
    180
    181 /* abort, if all variables should be fixed */
    182 if( fixingcounter == nbinvars + nintvars )
    183 {
    184 *success = FALSE;
    185 return SCIP_OKAY;
    186 }
    187 else
    188 fixingrate = (SCIP_Real)fixingcounter / (SCIP_Real)(MAX(nbinvars + nintvars, 1));
    189
    190 /* abort, if the amount of fixed variables is insufficient */
    191 if( fixingrate < minfixingrate )
    192 {
    193 *success = FALSE;
    194 return SCIP_OKAY;
    195 }
    196
    197 *success = TRUE;
    198 return SCIP_OKAY;
    199}
    200
    201static
    202SCIP_DECL_EVENTEXEC(eventExecRins);
    204/** wrapper for the part of heuristic that runs a subscip. Wrapper is needed to avoid possible ressource leaks */
    205static
    207 SCIP* scip, /**< original SCIP data structure */
    208 SCIP* subscip, /**< SCIP structure of the subproblem */
    209 SCIP_HEUR* heur, /**< Heuristic pointer */
    210 SCIP_HEURDATA* heurdata, /**< Heuristic's data */
    211 SCIP_VAR** vars, /**< original problem's variables */
    212 SCIP_VAR** fixedvars, /**< Fixed variables of original SCIP */
    213 SCIP_Real* fixedvals, /**< Fixed values of original SCIP */
    214 SCIP_RESULT* result, /**< Result pointer */
    215 int nvars, /**< Number of variables */
    216 int nfixedvars, /**< Number of fixed variables */
    217 SCIP_Longint nnodes /**< Number of nodes in the b&b tree */
    218 )
    219{
    220 SCIP_VAR** subvars; /* variables of the subscip */
    221 SCIP_HASHMAP* varmapfw; /* hashmap for mapping between vars of scip and subscip */
    222 SCIP_EVENTHDLR* eventhdlr; /* event handler for LP events */
    223 SCIP_Real upperbound; /* upperbound of the original SCIP */
    224 SCIP_Real cutoff; /* objective cutoff for the subproblem */
    225
    226 SCIP_Bool success;
    227
    228 int i;
    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, "rins", fixedvars, fixedvals, nfixedvars,
    235 heurdata->uselprows, heurdata->copycuts, &success, NULL) );
    236
    237 eventhdlr = NULL;
    238 /* create event handler for LP events */
    239 SCIP_CALL( SCIPincludeEventhdlrBasic(subscip, &eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC, eventExecRins, NULL) );
    240 if( eventhdlr == NULL )
    241 {
    242 SCIPerrorMessage("event handler for " HEUR_NAME " heuristic not found.\n");
    243 return SCIP_PLUGINNOTFOUND;
    244 }
    245
    246 /* copy subproblem variables from map to obtain the same order */
    247 SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
    248 for( i = 0; i < nvars; i++ )
    249 subvars[i] = (SCIP_VAR*) SCIPhashmapGetImage(varmapfw, vars[i]);
    250
    251 /* free hash map */
    252 SCIPhashmapFree(&varmapfw);
    253
    254 /* do not abort subproblem on CTRL-C */
    255 SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
    256
    257#ifdef SCIP_DEBUG
    258 /* for debugging, enable full output */
    259 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", SCIP_VERBLEVEL_FULL) );
    260 SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 100000000) );
    261#else
    262 /* disable statistic timing inside sub SCIP and output to console */
    263 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", (int) SCIP_VERBLEVEL_NONE) );
    264 SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
    265#endif
    266
    267 /* set limits for the subproblem */
    268 SCIP_CALL( SCIPcopyLimits(scip, subscip) );
    269 heurdata->nodelimit = nnodes;
    270 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", nnodes) );
    271 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/stallnodes", MAX(10, nnodes/10)) );
    272 SCIP_CALL( SCIPsetIntParam(subscip, "limits/bestsol", 3) );
    273
    274 /* forbid recursive call of heuristics and separators solving subMIPs */
    275 SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );
    276
    277 /* disable cutting plane separation */
    279
    280 /* disable expensive presolving */
    282
    283 /* use best estimate node selection */
    284 if( SCIPfindNodesel(subscip, "estimate") != NULL && !SCIPisParamFixed(subscip, "nodeselection/estimate/stdpriority") )
    285 {
    286 SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/estimate/stdpriority", INT_MAX/4) );
    287 }
    288
    289 /* activate uct node selection at the top of the tree */
    290 if( heurdata->useuct && SCIPfindNodesel(subscip, "uct") != NULL && !SCIPisParamFixed(subscip, "nodeselection/uct/stdpriority") )
    291 {
    292 SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/uct/stdpriority", INT_MAX/2) );
    293 }
    294
    295 /* use inference branching */
    296 if( SCIPfindBranchrule(subscip, "inference") != NULL && !SCIPisParamFixed(subscip, "branching/inference/priority") )
    297 {
    298 SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
    299 }
    300
    301 /* enable conflict analysis, disable analysis of boundexceeding LPs, and restrict conflict pool */
    302 if( !SCIPisParamFixed(subscip, "conflict/enable") )
    303 {
    304 SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/enable", TRUE) );
    305 }
    306 if( !SCIPisParamFixed(subscip, "conflict/useboundlp") )
    307 {
    308 SCIP_CALL( SCIPsetCharParam(subscip, "conflict/useboundlp", 'o') );
    309 }
    310 if( !SCIPisParamFixed(subscip, "conflict/maxstoresize") )
    311 {
    312 SCIP_CALL( SCIPsetIntParam(subscip, "conflict/maxstoresize", 100) );
    313 }
    314
    315 /* speed up sub-SCIP by not checking dual LP feasibility */
    316 SCIP_CALL( SCIPsetBoolParam(subscip, "lp/checkdualfeas", FALSE) );
    317
    318 /* add an objective cutoff */
    320
    321 upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);
    323 {
    324 cutoff = (1 - heurdata->minimprove) * SCIPgetUpperbound(scip) + heurdata->minimprove * SCIPgetLowerbound(scip);
    325 }
    326 else
    327 {
    328 if( SCIPgetUpperbound(scip) >= 0 )
    329 cutoff = (1 - heurdata->minimprove) * SCIPgetUpperbound(scip);
    330 else
    331 cutoff = (1 + heurdata->minimprove) * SCIPgetUpperbound(scip);
    332 }
    333 cutoff = MIN(upperbound, cutoff);
    334 SCIP_CALL( SCIPsetObjlimit(subscip, cutoff) );
    335
    336 /* catch LP events of sub-SCIP */
    337 SCIP_CALL( SCIPtransformProb(subscip) );
    338 SCIP_CALL( SCIPcatchEvent(subscip, SCIP_EVENTTYPE_LPSOLVED, eventhdlr, (SCIP_EVENTDATA*) heurdata, NULL) );
    339
    340 /* Errors in solving the subproblem should not kill the overall solving process
    341 * Hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
    342 */
    343 /* solve the subproblem */
    344 SCIP_CALL_ABORT( SCIPsolve(subscip) );
    345
    346 /* drop LP events of sub-SCIP */
    347 SCIP_CALL( SCIPdropEvent(subscip, SCIP_EVENTTYPE_LPSOLVED, eventhdlr, (SCIP_EVENTDATA*) heurdata, -1) );
    348
    349 /* we try to merge variable statistics with those of our main SCIP */
    350 SCIP_CALL( SCIPmergeVariableStatistics(subscip, scip, subvars, vars, nvars) );
    351
    352 /* print solving statistics of subproblem if we are in SCIP's debug mode */
    354
    355 heurdata->usednodes += SCIPgetNNodes(subscip);
    356
    357 SCIP_CALL( SCIPtranslateSubSols(scip, subscip, heur, subvars, &success, NULL) );
    358 if( success )
    359 *result = SCIP_FOUNDSOL;
    360
    361 /* free subproblem */
    362 SCIPfreeBufferArray(scip, &subvars);
    363
    364 return SCIP_OKAY;
    365}
    366
    367/* ---------------- Callback methods of event handler ---------------- */
    368
    369/* exec the event handler
    370 *
    371 * we interrupt the solution process
    372 */
    373static
    374SCIP_DECL_EVENTEXEC(eventExecRins)
    375{
    376 SCIP_HEURDATA* heurdata;
    377
    378 assert(eventhdlr != NULL);
    379 assert(eventdata != NULL);
    380 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
    381 assert(event != NULL);
    383
    384 heurdata = (SCIP_HEURDATA*)eventdata;
    385 assert(heurdata != NULL);
    386
    387 /* interrupt solution process of sub-SCIP */
    388 if( SCIPgetNLPs(scip) > heurdata->lplimfac * heurdata->nodelimit )
    389 {
    390 SCIPdebugMsg(scip, "interrupt after %" SCIP_LONGINT_FORMAT " LPs\n",SCIPgetNLPs(scip));
    392 }
    393
    394 return SCIP_OKAY;
    395}
    396
    397
    398/*
    399 * Callback methods of primal heuristic
    400 */
    402/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
    403static
    404SCIP_DECL_HEURCOPY(heurCopyRins)
    405{ /*lint --e{715}*/
    406 assert(scip != NULL);
    407 assert(heur != NULL);
    408 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    409
    410 /* call inclusion method of primal heuristic */
    412
    413 return SCIP_OKAY;
    414}
    416/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
    417static
    418SCIP_DECL_HEURFREE(heurFreeRins)
    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 heuristic data */
    430 SCIPfreeBlockMemory(scip, &heurdata);
    431 SCIPheurSetData(heur, NULL);
    432
    433 return SCIP_OKAY;
    434}
    435
    437/** initialization method of primal heuristic (called after problem was transformed) */
    438static
    439SCIP_DECL_HEURINIT(heurInitRins)
    440{ /*lint --e{715}*/
    441 SCIP_HEURDATA* heurdata;
    442
    443 assert( heur != NULL );
    444 assert( scip != NULL );
    445
    446 /* get heuristic's data */
    447 heurdata = SCIPheurGetData(heur);
    448 assert( heurdata != NULL );
    449
    450 /* initialize data */
    451 heurdata->usednodes = 0;
    452
    453 return SCIP_OKAY;
    454}
    455
    457/** execution method of primal heuristic */
    458static
    459SCIP_DECL_HEUREXEC(heurExecRins)
    460{ /*lint --e{715}*/
    462
    463 SCIP_HEURDATA* heurdata; /* heuristic's data */
    464 SCIP* subscip; /* the subproblem created by RINS */
    465 SCIP_VAR** vars; /* original problem's variables */
    466 SCIP_VAR** fixedvars;
    467 SCIP_Real* fixedvals;
    468
    469 SCIP_RETCODE retcode; /* retcode needed for wrapper method */
    470
    471 int nvars;
    472 int nbinvars;
    473 int nintvars;
    474 int nfixedvars;
    475
    476 SCIP_Bool success;
    477
    478 assert( heur != NULL );
    479 assert( scip != NULL );
    480 assert( result != NULL );
    481 assert( SCIPhasCurrentNodeLP(scip) );
    482
    483 *result = SCIP_DELAYED;
    484
    485 /* do not call heuristic of node was already detected to be infeasible */
    486 if( nodeinfeasible )
    487 return SCIP_OKAY;
    488
    489 /* get heuristic's data */
    490 heurdata = SCIPheurGetData(heur);
    491 assert( heurdata != NULL );
    492
    493 /* only call heuristic, if an optimal LP solution and a feasible solution are at hand */
    495 return SCIP_OKAY;
    496
    497 /* only call heuristic, if the LP objective value is smaller than the cutoff bound */
    499 return SCIP_OKAY;
    500
    501 /* only call heuristic, if the best solution comes from transformed problem */
    502 assert( SCIPgetBestSol(scip) != NULL );
    504 return SCIP_OKAY;
    505
    506 /* only call heuristic, if enough nodes were processed since last incumbent */
    507 if( SCIPgetNNodes(scip) - SCIPgetSolNodenum(scip,SCIPgetBestSol(scip)) < heurdata->nwaitingnodes)
    508 return SCIP_OKAY;
    509
    510 *result = SCIP_DIDNOTRUN;
    511
    512 /* calculate the maximal number of branching nodes until heuristic is aborted */
    513 nnodes = (SCIP_Longint)(heurdata->nodesquot * SCIPgetNNodes(scip));
    514
    515 /* reward RINS if it succeeded often */
    517 nnodes -= (SCIP_Longint)(100.0 * SCIPheurGetNCalls(heur)); /* count the setup costs for the sub-MIP as 100 nodes */
    518 nnodes += heurdata->nodesofs;
    519
    520 /* determine the node limit for the current process */
    521 nnodes -= heurdata->usednodes;
    522 nnodes = MIN(nnodes, heurdata->maxnodes);
    523
    524 /* check whether we have enough nodes left to call subproblem solving */
    525 if( nnodes < heurdata->minnodes )
    526 return SCIP_OKAY;
    527
    528 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
    529
    530 /* check whether discrete variables are available */
    531 if( nbinvars == 0 && nintvars == 0 )
    532 return SCIP_OKAY;
    533
    534 if( SCIPisStopped(scip) )
    535 return SCIP_OKAY;
    536
    537 /* allocate buffer storage to hold the RINS fixings */
    538 SCIP_CALL( SCIPallocBufferArray(scip, &fixedvars, nbinvars + nintvars) );
    539 SCIP_CALL( SCIPallocBufferArray(scip, &fixedvals, nbinvars + nintvars) );
    540
    541 success = FALSE;
    542
    543 nfixedvars = 0;
    544 /* determine possible fixings for RINS: variables with same value in bestsol and LP relaxation */
    545 SCIP_CALL( determineFixings(scip, fixedvars, fixedvals, &nfixedvars, nbinvars + nintvars, heurdata->minfixingrate, &success) );
    546
    547 /* too few variables could be fixed by the RINS scheme */
    548 if( !success )
    549 goto TERMINATE;
    550
    551 /* check whether there is enough time and memory left */
    552 SCIP_CALL( SCIPcheckCopyLimits(scip, &success) );
    553
    554 /* abort if no time is left or not enough memory to create a copy of SCIP */
    555 if( !success )
    556 goto TERMINATE;
    557
    558 assert(nfixedvars > 0 && nfixedvars < nbinvars + nintvars);
    559
    560 *result = SCIP_DIDNOTFIND;
    561
    562 SCIPdebugMsg(scip, "RINS heuristic fixes %d out of %d binary+integer variables\n", nfixedvars, nbinvars + nintvars);
    563 SCIP_CALL( SCIPcreate(&subscip) );
    564
    565 retcode = wrapperRins(scip, subscip, heur, heurdata, vars, fixedvars, fixedvals, result, nvars, nfixedvars, nnodes);
    566
    567 SCIP_CALL( SCIPfree(&subscip) );
    568
    569 SCIP_CALL( retcode );
    570
    571TERMINATE:
    572 SCIPfreeBufferArray(scip, &fixedvals);
    573 SCIPfreeBufferArray(scip, &fixedvars);
    574
    575 return SCIP_OKAY;
    576}
    577
    578/*
    579 * primal heuristic specific interface methods
    580 */
    581
    582/** creates the RINS primal heuristic and includes it in SCIP */
    584 SCIP* scip /**< SCIP data structure */
    585 )
    586{
    587 SCIP_HEURDATA* heurdata;
    588 SCIP_HEUR* heur;
    589
    590 /* create Rins primal heuristic data */
    591 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    592
    593 /* include primal heuristic */
    596 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecRins, heurdata) );
    597
    598 assert(heur != NULL);
    599
    600 /* primal heuristic is safe to use in exact solving mode */
    601 SCIPheurMarkExact(heur);
    602
    603 /* set non-NULL pointers to callback methods */
    604 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyRins) );
    605 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeRins) );
    606 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitRins) );
    607
    608 /* add RINS primal heuristic parameters */
    609 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/nodesofs",
    610 "number of nodes added to the contingent of the total nodes",
    611 &heurdata->nodesofs, FALSE, DEFAULT_NODESOFS, 0, INT_MAX, NULL, NULL) );
    612
    613 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
    614 "maximum number of nodes to regard in the subproblem",
    615 &heurdata->maxnodes, TRUE, DEFAULT_MAXNODES, 0, INT_MAX, NULL, NULL) );
    616
    617 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/minnodes",
    618 "minimum number of nodes required to start the subproblem",
    619 &heurdata->minnodes, TRUE, DEFAULT_MINNODES, 0, INT_MAX, NULL, NULL) );
    620
    621 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesquot",
    622 "contingent of sub problem nodes in relation to the number of nodes of the original problem",
    623 &heurdata->nodesquot, FALSE, DEFAULT_NODESQUOT, 0.0, 1.0, NULL, NULL) );
    624
    625 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/nwaitingnodes",
    626 "number of nodes without incumbent change that heuristic should wait",
    627 &heurdata->nwaitingnodes, TRUE, DEFAULT_NWAITINGNODES, 0, INT_MAX, NULL, NULL) );
    628
    629 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprove",
    630 "factor by which " HEUR_NAME " should at least improve the incumbent",
    631 &heurdata->minimprove, TRUE, DEFAULT_MINIMPROVE, 0.0, 1.0, NULL, NULL) );
    632
    633 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minfixingrate",
    634 "minimum percentage of integer variables that have to be fixed",
    635 &heurdata->minfixingrate, FALSE, DEFAULT_MINFIXINGRATE, 0.0, 1.0, NULL, NULL) );
    636
    637 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/lplimfac",
    638 "factor by which the limit on the number of LP depends on the node limit",
    639 &heurdata->lplimfac, TRUE, DEFAULT_LPLIMFAC, 1.0, SCIP_REAL_MAX, NULL, NULL) );
    640
    641 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/uselprows",
    642 "should subproblem be created out of the rows in the LP rows?",
    643 &heurdata->uselprows, TRUE, DEFAULT_USELPROWS, NULL, NULL) );
    644
    645 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/copycuts",
    646 "if uselprows == FALSE, should all active cuts from cutpool be copied to constraints in subproblem?",
    647 &heurdata->copycuts, TRUE, DEFAULT_COPYCUTS, NULL, NULL) );
    648
    649 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/useuct",
    650 "should uct node selection be used at the beginning of the search?",
    651 &heurdata->useuct, TRUE, DEFAULT_USEUCT, NULL, NULL) );
    652
    653 return SCIP_OKAY;
    654}
    #define NULL
    Definition: def.h:248
    #define SCIP_Longint
    Definition: def.h:141
    #define SCIP_REAL_MAX
    Definition: def.h:158
    #define SCIP_Bool
    Definition: def.h:91
    #define MIN(x, y)
    Definition: def.h:224
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define SCIP_CALL_ABORT(x)
    Definition: def.h:334
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:148
    #define SCIP_CALL(x)
    Definition: def.h:355
    #define nnodes
    Definition: gastrans.c:74
    SCIP_RETCODE SCIPtranslateSubSols(SCIP *scip, SCIP *subscip, SCIP_HEUR *heur, SCIP_VAR **subvars, SCIP_Bool *success, int *solindex)
    Definition: scip_copy.c:1437
    SCIP_RETCODE SCIPcheckCopyLimits(SCIP *sourcescip, SCIP_Bool *success)
    Definition: scip_copy.c:3249
    SCIP_RETCODE SCIPmergeVariableStatistics(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR **sourcevars, SCIP_VAR **targetvars, int nvars)
    Definition: scip_copy.c:1254
    SCIP_RETCODE SCIPcopyLimits(SCIP *sourcescip, SCIP *targetscip)
    Definition: scip_copy.c:3292
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:759
    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
    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
    SCIP_RETCODE SCIPincludeHeurRins(SCIP *scip)
    Definition: heur_rins.c:580
    SCIP_BRANCHRULE * SCIPfindBranchrule(SCIP *scip, const char *name)
    Definition: scip_branch.c:304
    SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
    Definition: scip_event.c:111
    const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
    Definition: event.c:396
    SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
    Definition: event.c:1194
    SCIP_RETCODE SCIPcatchEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
    Definition: scip_event.c:293
    SCIP_RETCODE SCIPdropEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
    Definition: scip_event.c:333
    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_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
    SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
    Definition: scip_lp.c:87
    SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
    Definition: scip_lp.c:174
    SCIP_Real SCIPgetLPObjval(SCIP *scip)
    Definition: scip_lp.c:253
    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:2981
    int SCIPgetNSols(SCIP *scip)
    Definition: scip_sol.c:2882
    SCIP_Bool SCIPsolIsOriginal(SCIP_SOL *sol)
    Definition: sol.c:4140
    SCIP_Longint SCIPgetSolNodenum(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:2219
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1765
    SCIP_RETCODE SCIPtransformProb(SCIP *scip)
    Definition: scip_solve.c:232
    SCIP_RETCODE SCIPinterruptSolve(SCIP *scip)
    Definition: scip_solve.c:3548
    SCIP_RETCODE SCIPsolve(SCIP *scip)
    Definition: scip_solve.c:2635
    SCIP_Real SCIPgetUpperbound(SCIP *scip)
    SCIP_Longint SCIPgetNNodes(SCIP *scip)
    SCIP_RETCODE SCIPprintStatistics(SCIP *scip, FILE *file)
    SCIP_Real SCIPgetLowerbound(SCIP *scip)
    SCIP_Longint SCIPgetNLPs(SCIP *scip)
    SCIP_Real SCIPgetCutoffbound(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 SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPsumepsilon(SCIP *scip)
    SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
    Definition: var.c:24664
    #define DEFAULT_NODESQUOT
    Definition: heur_rins.c:75
    #define DEFAULT_NWAITINGNODES
    Definition: heur_rins.c:77
    static SCIP_DECL_HEUREXEC(heurExecRins)
    Definition: heur_rins.c:456
    #define DEFAULT_NODESOFS
    Definition: heur_rins.c:70
    #define DEFAULT_COPYCUTS
    Definition: heur_rins.c:79
    #define DEFAULT_MAXNODES
    Definition: heur_rins.c:71
    static SCIP_RETCODE determineFixings(SCIP *scip, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int *nfixedvars, int fixedvarssize, SCIP_Real minfixingrate, SCIP_Bool *success)
    Definition: heur_rins.c:123
    #define HEUR_TIMING
    Definition: heur_rins.c:67
    #define DEFAULT_MINNODES
    Definition: heur_rins.c:72
    #define HEUR_FREQOFS
    Definition: heur_rins.c:65
    #define HEUR_DESC
    Definition: heur_rins.c:61
    #define DEFAULT_LPLIMFAC
    Definition: heur_rins.c:76
    #define DEFAULT_MINFIXINGRATE
    Definition: heur_rins.c:74
    #define DEFAULT_USEUCT
    Definition: heur_rins.c:80
    static SCIP_RETCODE wrapperRins(SCIP *scip, SCIP *subscip, SCIP_HEUR *heur, SCIP_HEURDATA *heurdata, SCIP_VAR **vars, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, SCIP_RESULT *result, int nvars, int nfixedvars, SCIP_Longint nnodes)
    Definition: heur_rins.c:203
    #define HEUR_DISPCHAR
    Definition: heur_rins.c:62
    #define HEUR_MAXDEPTH
    Definition: heur_rins.c:66
    #define HEUR_PRIORITY
    Definition: heur_rins.c:63
    #define DEFAULT_MINIMPROVE
    Definition: heur_rins.c:73
    #define HEUR_NAME
    Definition: heur_rins.c:60
    #define DEFAULT_USELPROWS
    Definition: heur_rins.c:78
    static SCIP_DECL_HEURFREE(heurFreeRins)
    Definition: heur_rins.c:415
    static SCIP_DECL_EVENTEXEC(eventExecRins)
    Definition: heur_rins.c:371
    #define EVENTHDLR_DESC
    Definition: heur_rins.c:84
    #define HEUR_FREQ
    Definition: heur_rins.c:64
    #define HEUR_USESSUBSCIP
    Definition: heur_rins.c:68
    static SCIP_DECL_HEURCOPY(heurCopyRins)
    Definition: heur_rins.c:401
    #define EVENTHDLR_NAME
    Definition: heur_rins.c:83
    static SCIP_DECL_HEURINIT(heurInitRins)
    Definition: heur_rins.c:436
    LNS heuristic that combines the incumbent with the LP optimum.
    methods commonly used by primal heuristics
    memory allocation routines
    public methods for managing events
    public methods for primal heuristics
    public methods for message output
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    #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
    public methods for event handler plugins and event handlers
    general public methods
    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 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 solutions
    public solving methods
    public methods for querying solving statistics
    struct SCIP_EventData SCIP_EVENTDATA
    Definition: type_event.h:179
    #define SCIP_EVENTTYPE_LPSOLVED
    Definition: type_event.h:102
    struct SCIP_HeurData SCIP_HEURDATA
    Definition: type_heur.h:77
    @ SCIP_LPSOLSTAT_OPTIMAL
    Definition: type_lp.h:44
    @ SCIP_VERBLEVEL_NONE
    Definition: type_message.h:57
    @ SCIP_VERBLEVEL_FULL
    Definition: type_message.h:62
    @ 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_PLUGINNOTFOUND
    Definition: type_retcode.h:54
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63