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-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_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
    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(event != NULL);
    382
    384
    385 heurdata = (SCIP_HEURDATA*)eventdata;
    386 assert(heurdata != NULL);
    387
    388 /* interrupt solution process of sub-SCIP */
    389 if( SCIPgetNLPs(scip) > heurdata->lplimfac * heurdata->nodelimit )
    390 {
    391 SCIPdebugMsg(scip, "interrupt after %" SCIP_LONGINT_FORMAT " LPs\n",SCIPgetNLPs(scip));
    393 }
    394
    395 return SCIP_OKAY;
    396}
    397
    398
    399/*
    400 * Callback methods of primal heuristic
    401 */
    403/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
    404static
    405SCIP_DECL_HEURCOPY(heurCopyRins)
    406{ /*lint --e{715}*/
    407 assert(scip != NULL);
    408 assert(heur != NULL);
    409
    411
    412 /* call inclusion method of primal heuristic */
    414
    415 return SCIP_OKAY;
    416}
    418/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
    419static
    420SCIP_DECL_HEURFREE(heurFreeRins)
    421{ /*lint --e{715}*/
    422 SCIP_HEURDATA* heurdata;
    423
    424 assert( heur != NULL );
    425 assert( scip != NULL );
    426
    427 /* get heuristic data */
    428 heurdata = SCIPheurGetData(heur);
    429 assert( heurdata != NULL );
    430
    431 /* free heuristic data */
    432 SCIPfreeBlockMemory(scip, &heurdata);
    433 SCIPheurSetData(heur, NULL);
    434
    435 return SCIP_OKAY;
    436}
    437
    439/** initialization method of primal heuristic (called after problem was transformed) */
    440static
    441SCIP_DECL_HEURINIT(heurInitRins)
    442{ /*lint --e{715}*/
    443 SCIP_HEURDATA* heurdata;
    444
    445 assert( heur != NULL );
    446 assert( scip != NULL );
    447
    448 /* get heuristic's data */
    449 heurdata = SCIPheurGetData(heur);
    450 assert( heurdata != NULL );
    451
    452 /* initialize data */
    453 heurdata->usednodes = 0;
    454
    455 return SCIP_OKAY;
    456}
    457
    459/** execution method of primal heuristic */
    460static
    461SCIP_DECL_HEUREXEC(heurExecRins)
    462{ /*lint --e{715}*/
    464
    465 SCIP_HEURDATA* heurdata; /* heuristic's data */
    466 SCIP* subscip; /* the subproblem created by RINS */
    467 SCIP_VAR** vars; /* original problem's variables */
    468 SCIP_VAR** fixedvars;
    469 SCIP_Real* fixedvals;
    470
    471 SCIP_RETCODE retcode; /* retcode needed for wrapper method */
    472
    473 int nvars;
    474 int nbinvars;
    475 int nintvars;
    476 int nfixedvars;
    477
    478 SCIP_Bool success;
    479
    480 assert( heur != NULL );
    481 assert( scip != NULL );
    482 assert( result != NULL );
    483 assert( SCIPhasCurrentNodeLP(scip) );
    484
    485 *result = SCIP_DELAYED;
    486
    487 /* do not call heuristic of node was already detected to be infeasible */
    488 if( nodeinfeasible )
    489 return SCIP_OKAY;
    490
    491 /* get heuristic's data */
    492 heurdata = SCIPheurGetData(heur);
    493 assert( heurdata != NULL );
    494
    495 /* only call heuristic, if an optimal LP solution and a feasible solution are at hand */
    497 return SCIP_OKAY;
    498
    499 /* only call heuristic, if the LP objective value is smaller than the cutoff bound */
    501 return SCIP_OKAY;
    502
    503 /* only call heuristic, if the best solution comes from transformed problem */
    504 assert( SCIPgetBestSol(scip) != NULL );
    506 return SCIP_OKAY;
    507
    508 /* only call heuristic, if enough nodes were processed since last incumbent */
    509 if( SCIPgetNNodes(scip) - SCIPgetSolNodenum(scip,SCIPgetBestSol(scip)) < heurdata->nwaitingnodes)
    510 return SCIP_OKAY;
    511
    512 *result = SCIP_DIDNOTRUN;
    513
    514 /* calculate the maximal number of branching nodes until heuristic is aborted */
    515 nnodes = (SCIP_Longint)(heurdata->nodesquot * SCIPgetNNodes(scip));
    516
    517 /* reward RINS if it succeeded often */
    519 nnodes -= (SCIP_Longint)(100.0 * SCIPheurGetNCalls(heur)); /* count the setup costs for the sub-MIP as 100 nodes */
    520 nnodes += heurdata->nodesofs;
    521
    522 /* determine the node limit for the current process */
    523 nnodes -= heurdata->usednodes;
    524 nnodes = MIN(nnodes, heurdata->maxnodes);
    525
    526 /* check whether we have enough nodes left to call subproblem solving */
    527 if( nnodes < heurdata->minnodes )
    528 return SCIP_OKAY;
    529
    530 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
    531
    532 /* check whether discrete variables are available */
    533 if( nbinvars == 0 && nintvars == 0 )
    534 return SCIP_OKAY;
    535
    536 if( SCIPisStopped(scip) )
    537 return SCIP_OKAY;
    538
    539 /* allocate buffer storage to hold the RINS fixings */
    540 SCIP_CALL( SCIPallocBufferArray(scip, &fixedvars, nbinvars + nintvars) );
    541 SCIP_CALL( SCIPallocBufferArray(scip, &fixedvals, nbinvars + nintvars) );
    542
    543 success = FALSE;
    544
    545 nfixedvars = 0;
    546 /* determine possible fixings for RINS: variables with same value in bestsol and LP relaxation */
    547 SCIP_CALL( determineFixings(scip, fixedvars, fixedvals, &nfixedvars, nbinvars + nintvars, heurdata->minfixingrate, &success) );
    548
    549 /* too few variables could be fixed by the RINS scheme */
    550 if( !success )
    551 goto TERMINATE;
    552
    553 /* check whether there is enough time and memory left */
    554 SCIP_CALL( SCIPcheckCopyLimits(scip, &success) );
    555
    556 /* abort if no time is left or not enough memory to create a copy of SCIP */
    557 if( !success )
    558 goto TERMINATE;
    559
    560 assert(nfixedvars > 0 && nfixedvars < nbinvars + nintvars);
    561
    562 *result = SCIP_DIDNOTFIND;
    563
    564 SCIPdebugMsg(scip, "RINS heuristic fixes %d out of %d binary+integer variables\n", nfixedvars, nbinvars + nintvars);
    565 SCIP_CALL( SCIPcreate(&subscip) );
    566
    567 retcode = wrapperRins(scip, subscip, heur, heurdata, vars, fixedvars, fixedvals, result, nvars, nfixedvars, nnodes);
    568
    569 SCIP_CALL( SCIPfree(&subscip) );
    570
    571 SCIP_CALL( retcode );
    572
    573TERMINATE:
    574 SCIPfreeBufferArray(scip, &fixedvals);
    575 SCIPfreeBufferArray(scip, &fixedvars);
    576
    577 return SCIP_OKAY;
    578}
    579
    580/*
    581 * primal heuristic specific interface methods
    582 */
    583
    584/** creates the RINS primal heuristic and includes it in SCIP */
    586 SCIP* scip /**< SCIP data structure */
    587 )
    588{
    589 SCIP_HEURDATA* heurdata;
    590 SCIP_HEUR* heur;
    591
    592 /* create Rins primal heuristic data */
    593 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    594
    595 /* include primal heuristic */
    598 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecRins, heurdata) );
    599
    600 assert(heur != NULL);
    601
    602 /* primal heuristic is safe to use in exact solving mode */
    603 SCIPheurMarkExact(heur);
    604
    605 /* set non-NULL pointers to callback methods */
    606 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyRins) );
    607 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeRins) );
    608 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitRins) );
    609
    610 /* add RINS primal heuristic parameters */
    611 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/nodesofs",
    612 "number of nodes added to the contingent of the total nodes",
    613 &heurdata->nodesofs, FALSE, DEFAULT_NODESOFS, 0, INT_MAX, NULL, NULL) );
    614
    615 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
    616 "maximum number of nodes to regard in the subproblem",
    617 &heurdata->maxnodes, TRUE, DEFAULT_MAXNODES, 0, INT_MAX, NULL, NULL) );
    618
    619 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/minnodes",
    620 "minimum number of nodes required to start the subproblem",
    621 &heurdata->minnodes, TRUE, DEFAULT_MINNODES, 0, INT_MAX, NULL, NULL) );
    622
    623 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesquot",
    624 "contingent of sub problem nodes in relation to the number of nodes of the original problem",
    625 &heurdata->nodesquot, FALSE, DEFAULT_NODESQUOT, 0.0, 1.0, NULL, NULL) );
    626
    627 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/nwaitingnodes",
    628 "number of nodes without incumbent change that heuristic should wait",
    629 &heurdata->nwaitingnodes, TRUE, DEFAULT_NWAITINGNODES, 0, INT_MAX, NULL, NULL) );
    630
    631 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprove",
    632 "factor by which " HEUR_NAME " should at least improve the incumbent",
    633 &heurdata->minimprove, TRUE, DEFAULT_MINIMPROVE, 0.0, 1.0, NULL, NULL) );
    634
    635 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minfixingrate",
    636 "minimum percentage of integer variables that have to be fixed",
    637 &heurdata->minfixingrate, FALSE, DEFAULT_MINFIXINGRATE, 0.0, 1.0, NULL, NULL) );
    638
    639 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/lplimfac",
    640 "factor by which the limit on the number of LP depends on the node limit",
    641 &heurdata->lplimfac, TRUE, DEFAULT_LPLIMFAC, 1.0, SCIP_REAL_MAX, NULL, NULL) );
    642
    643 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/uselprows",
    644 "should subproblem be created out of the rows in the LP rows?",
    645 &heurdata->uselprows, TRUE, DEFAULT_USELPROWS, NULL, NULL) );
    646
    647 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/copycuts",
    648 "if uselprows == FALSE, should all active cuts from cutpool be copied to constraints in subproblem?",
    649 &heurdata->copycuts, TRUE, DEFAULT_COPYCUTS, NULL, NULL) );
    650
    651 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/useuct",
    652 "should uct node selection be used at the beginning of the search?",
    653 &heurdata->useuct, TRUE, DEFAULT_USEUCT, NULL, NULL) );
    654
    655 return SCIP_OKAY;
    656}
    #define NULL
    Definition: def.h:257
    #define SCIP_Longint
    Definition: def.h:150
    #define SCIP_REAL_MAX
    Definition: def.h:167
    #define SCIP_Bool
    Definition: def.h:100
    #define MIN(x, y)
    Definition: def.h:233
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define MAX(x, y)
    Definition: def.h:229
    #define SCIP_CALL_ABORT(x)
    Definition: def.h:343
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:157
    #define SCIP_CALL(x)
    Definition: def.h:364
    #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: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
    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:582
    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: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 SCIPtransformProb(SCIP *scip)
    Definition: scip_solve.c:232
    SCIP_RETCODE SCIPinterruptSolve(SCIP *scip)
    Definition: scip_solve.c:3561
    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_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:24696
    #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:458
    #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:417
    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:402
    #define EVENTHDLR_NAME
    Definition: heur_rins.c:83
    static SCIP_DECL_HEURINIT(heurInitRins)
    Definition: heur_rins.c:438
    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
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63