Scippy

    SCIP

    Solving Constraint Integer Programs

    heur_adaptivediving.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_adaptivediving.c
    26 * @ingroup DEFPLUGINS_HEUR
    27 * @brief diving heuristic that selects adaptively between the existing, public dive sets
    28 * @author Gregor Hendel
    29 */
    30
    31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    32
    33#include <assert.h>
    34#include <string.h>
    35
    37#include "scip/heuristics.h"
    38#include "scip/scipdefplugins.h"
    39
    40#define HEUR_NAME "adaptivediving"
    41#define HEUR_DESC "diving heuristic that selects adaptively between the existing, public divesets"
    42#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_DIVING
    43#define HEUR_PRIORITY -70000
    44#define HEUR_FREQ 5
    45#define HEUR_FREQOFS 3
    46#define HEUR_MAXDEPTH -1
    47#define HEUR_TIMING SCIP_HEURTIMING_AFTERLPPLUNGE
    48#define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
    49
    50#define DIVESETS_INITIALSIZE 10
    51#define DEFAULT_INITIALSEED 13
    52
    53/*
    54 * Default parameter settings
    55 */
    56#define DEFAULT_SELTYPE 'w'
    57#define DEFAULT_SCORETYPE 'c' /**< score parameter for selection: minimize either average 'n'odes, LP 'i'terations,
    58 * backtrack/'c'onflict ratio, 'd'epth, 1 / 's'olutions, or
    59 * 1 / solutions'u'ccess */
    60#define DEFAULT_USEADAPTIVECONTEXT FALSE
    61#define DEFAULT_SELCONFIDENCECOEFF 10.0 /**< coefficient c to decrease initial confidence (calls + 1.0) / (calls + c) in scores */
    62#define DEFAULT_EPSILON 1.0 /**< parameter that increases probability of exploration among divesets (only active if seltype is 'e') */
    63#define DEFAULT_MAXLPITERQUOT 0.15 /**< maximal fraction of diving LP iterations compared to node LP iterations */
    64#define DEFAULT_MAXLPITEROFS 1500L /**< additional number of allowed LP iterations */
    65#define DEFAULT_BESTSOLWEIGHT 10.0 /**< weight of incumbent solutions compared to other solutions in computation of LP iteration limit */
    66
    67/* locally defined heuristic data */
    68struct SCIP_HeurData
    69{
    70 /* data structures used internally */
    71 SCIP_SOL* sol; /**< working solution */
    72 SCIP_RANDNUMGEN* randnumgen; /**< random number generator for selection */
    73 SCIP_DIVESET** divesets; /**< publicly available divesets from diving heuristics */
    74 int ndivesets; /**< number of publicly available divesets from diving heuristics */
    75 int divesetssize; /**< array size for divesets array */
    76 int lastselection; /**< stores the last selected diveset when the heuristics was run */
    77 /* user parameters */
    78 SCIP_Real epsilon; /**< parameter that increases probability of exploration among divesets (only active if seltype is 'e') */
    79 SCIP_Real selconfidencecoeff; /**< coefficient c to decrease initial confidence (calls + 1.0) / (calls + c) in scores */
    80 SCIP_Real maxlpiterquot; /**< maximal fraction of diving LP iterations compared to node LP iterations */
    81 SCIP_Longint maxlpiterofs; /**< additional number of allowed LP iterations */
    82 SCIP_Real bestsolweight; /**< weight of incumbent solutions compared to other solutions in computation of LP iteration limit */
    83 char seltype; /**< selection strategy: (e)psilon-greedy, (w)eighted distribution, (n)ext diving */
    84 char scoretype; /**< score parameter for selection: minimize either average 'n'odes, LP 'i'terations,
    85 * backtrack/'c'onflict ratio, 'd'epth, 1 / 's'olutions, or
    86 * 1 / solutions'u'ccess */
    87 SCIP_Bool useadaptivecontext; /**< should the heuristic use its own statistics, or shared statistics? */
    88};
    89
    90/*
    91 * local methods
    92 */
    93
    94
    95/** get the selection score for this dive set */
    96static
    98 SCIP_DIVESET* diveset, /**< diving settings data structure */
    99 SCIP_HEURDATA* heurdata, /**< heuristic data */
    100 SCIP_DIVECONTEXT divecontext, /**< context for diving statistics */
    101 SCIP_Real* scoreptr /**< pointer to store the score */
    102 )
    103{
    104 SCIP_Real confidence;
    105
    106 assert(scoreptr != NULL);
    107
    108 /* compute confidence scalar (converges towards 1 with increasing number of calls) */
    109 confidence = (SCIPdivesetGetNCalls(diveset, divecontext) + 1.0) /
    110 (SCIPdivesetGetNCalls(diveset, divecontext) + heurdata->selconfidencecoeff);
    111
    112 switch (heurdata->scoretype) {
    113 case 'n': /* min average nodes */
    114 *scoreptr = confidence * SCIPdivesetGetNProbingNodes(diveset, divecontext) / (SCIPdivesetGetNCalls(diveset, divecontext) + 1.0);
    115 break;
    116 case 'i': /* min avg LP iterations */
    117 *scoreptr = confidence * SCIPdivesetGetNLPIterations(diveset, divecontext) / (SCIPdivesetGetNCalls(diveset, divecontext) + 1.0);
    118 break;
    119 case 'c': /* min backtrack / conflict ratio (the current default) */
    120 *scoreptr = confidence * (SCIPdivesetGetNBacktracks(diveset, divecontext)) / (SCIPdivesetGetNConflicts(diveset, divecontext) + 10.0);
    121 break;
    122 case 'd': /* minimum average depth */
    123 *scoreptr = SCIPdivesetGetAvgDepth(diveset, divecontext) * confidence;
    124 break;
    125 case 's': /* maximum number of solutions */
    126 *scoreptr = confidence / (SCIPdivesetGetNSols(diveset, divecontext) + 1.0);
    127 break;
    128 case 'u': /* maximum solution success (which weighs best solutions higher) */
    129 *scoreptr = confidence / (SCIPdivesetGetSolSuccess(diveset, divecontext) + 1.0);
    130 break;
    131 default:
    132 SCIPerrorMessage("Unsupported scoring parameter '%c'\n", heurdata->scoretype);
    133 SCIPABORT();
    134 *scoreptr = SCIP_INVALID;
    136 }
    137
    138 return SCIP_OKAY;
    139}
    140
    141/*
    142 * Callback methods
    143 */
    144
    145/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
    146static
    147SCIP_DECL_HEURCOPY(heurCopyAdaptivediving)
    148{ /*lint --e{715}*/
    149 assert(scip != NULL);
    150 assert(heur != NULL);
    151 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    152
    153 /* call inclusion method of primal heuristic */
    155
    156 return SCIP_OKAY;
    157}
    158
    159/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
    160static
    161SCIP_DECL_HEURFREE(heurFreeAdaptivediving) /*lint --e{715}*/
    162{ /*lint --e{715}*/
    163 SCIP_HEURDATA* heurdata;
    164
    165 assert(heur != NULL);
    166 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    167 assert(scip != NULL);
    168
    169 /* free heuristic data */
    170 heurdata = SCIPheurGetData(heur);
    171 assert(heurdata != NULL);
    172
    173 if( heurdata->divesets != NULL )
    174 {
    175 SCIPfreeBlockMemoryArray(scip, &heurdata->divesets, heurdata->divesetssize);
    176 }
    177
    178 SCIPfreeRandom(scip, &heurdata->randnumgen);
    179
    180 SCIPfreeMemory(scip, &heurdata);
    181 SCIPheurSetData(heur, NULL);
    182
    183 return SCIP_OKAY;
    184}
    185
    186/** find publicly available divesets and store them */
    187static
    189 SCIP* scip, /**< SCIP data structure */
    190 SCIP_HEUR* heur, /**< the heuristic */
    191 SCIP_HEURDATA* heurdata /**< heuristic data */
    192 )
    193{
    194 int h;
    195 SCIP_HEUR** heurs;
    196
    197 assert(scip != NULL);
    198 assert(heur != NULL);
    199 assert(heurdata != NULL);
    200
    201 heurs = SCIPgetHeurs(scip);
    202
    203 heurdata->divesetssize = DIVESETS_INITIALSIZE;
    204 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &heurdata->divesets, heurdata->divesetssize) );
    205 heurdata->ndivesets = 0;
    206
    207 for( h = 0; h < SCIPgetNHeurs(scip); ++h )
    208 {
    209 int d;
    210 assert(heurs[h] != NULL);
    211
    212 /* loop over divesets of this heuristic and check whether they are public */
    213 for( d = 0; d < SCIPheurGetNDivesets(heurs[h]); ++d )
    214 {
    215 SCIP_DIVESET* diveset = SCIPheurGetDivesets(heurs[h])[d];
    216 if( SCIPdivesetIsPublic(diveset) )
    217 {
    218 SCIPdebugMsg(scip, "Found publicly available diveset %s\n", SCIPdivesetGetName(diveset));
    219
    220 if( heurdata->ndivesets == heurdata->divesetssize )
    221 {
    222 int newsize = 2 * heurdata->divesetssize;
    223 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &heurdata->divesets, heurdata->divesetssize, newsize) );
    224 heurdata->divesetssize = newsize;
    225 }
    226 heurdata->divesets[heurdata->ndivesets++] = diveset;
    227 }
    228 else
    229 {
    230 SCIPdebugMsg(scip, "Skipping private diveset %s\n", SCIPdivesetGetName(diveset));
    231 }
    232 }
    233 }
    234 return SCIP_OKAY;
    235}
    236
    237/** initialization method of primal heuristic (called after problem was transformed) */
    238static
    239SCIP_DECL_HEURINIT(heurInitAdaptivediving) /*lint --e{715}*/
    240{ /*lint --e{715}*/
    241 SCIP_HEURDATA* heurdata;
    242
    243 assert(heur != NULL);
    244 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    245
    246 /* get and reset heuristic data */
    247 heurdata = SCIPheurGetData(heur);
    248 heurdata->lastselection = -1;
    249 if( heurdata->divesets != NULL )
    250 {
    251 /* we clear the list of collected divesets to ensure reproducability and consistent state across multiple runs
    252 * within the same SCIP data structure */
    253 SCIPfreeBlockMemoryArray(scip, &heurdata->divesets, heurdata->divesetssize);
    254 assert(heurdata->divesets == NULL);
    255 }
    256
    257 assert(heurdata != NULL);
    258
    259 /* create working solution */
    260 SCIP_CALL( SCIPcreateSol(scip, &heurdata->sol, heur) );
    261
    262 /* initialize random seed; use problem dimensions to vary initial order between different instances */
    263 SCIPsetRandomSeed(scip, heurdata->randnumgen,
    265
    266 return SCIP_OKAY;
    267}
    268
    269
    270/** deinitialization method of primal heuristic (called before transformed problem is freed) */
    271static
    272SCIP_DECL_HEUREXIT(heurExitAdaptivediving) /*lint --e{715}*/
    273{ /*lint --e{715}*/
    274 SCIP_HEURDATA* heurdata;
    275
    276 assert(heur != NULL);
    277 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    278
    279 /* get heuristic data */
    280 heurdata = SCIPheurGetData(heur);
    281 assert(heurdata != NULL);
    282
    283 /* free working solution */
    284 SCIP_CALL( SCIPfreeSol(scip, &heurdata->sol) );
    285
    286 return SCIP_OKAY;
    287}
    288
    289/*
    290 * heuristic specific interface methods
    291 */
    292
    293/** get LP iteration limit for diving */
    294static
    296 SCIP* scip, /**< SCIP data structure */
    297 SCIP_HEUR* heur, /**< the heuristic */
    298 SCIP_HEURDATA* heurdata /**< heuristic data */
    299 )
    300{
    301 SCIP_Real nsolsfound = SCIPheurGetNSolsFound(heur) + heurdata->bestsolweight * SCIPheurGetNBestSolsFound(heur);
    303 SCIP_Longint ncalls = SCIPheurGetNCalls(heur);
    304
    305 SCIP_Longint nlpiterationsdive = 0;
    306 SCIP_Longint lpiterlimit;
    307 int i;
    308
    309 assert(scip != NULL);
    310 assert(heur != NULL);
    311 assert(heurdata != NULL);
    312
    313 /* loop over the divesets and collect their individual iterations */
    314 for( i = 0; i < heurdata->ndivesets; ++i )
    315 {
    316 nlpiterationsdive += SCIPdivesetGetNLPIterations(heurdata->divesets[i], SCIP_DIVECONTEXT_ADAPTIVE);
    317 }
    318
    319 /* compute the iteration limit */
    320 lpiterlimit = (SCIP_Longint)(heurdata->maxlpiterquot * (nsolsfound+1.0)/(ncalls+1.0) * nlpiterations);
    321 lpiterlimit += heurdata->maxlpiterofs;
    322 lpiterlimit -= nlpiterationsdive;
    323
    324 return lpiterlimit;
    325}
    326
    327#ifdef SCIP_DEBUG
    328/** print array for debug purpose */
    329static
    330void printRealArray(
    331 char* strbuf, /**< string buffer array */
    332 SCIP_Real* elems, /**< array elements */
    333 int nelems /**< number of elements */
    334 )
    335{
    336 int c;
    337
    338 for( c = 0; c < nelems; ++c )
    339 strbuf += sprintf(strbuf, "%.4f ", elems[c]);
    340}
    341#endif
    342
    343/** sample from a distribution defined by weights */ /*lint -e715*/
    344static
    346 SCIP* scip, /**< SCIP data structure */
    347 SCIP_RANDNUMGEN* rng, /**< random number generator */
    348 SCIP_Real* weights, /**< weights of a ground set that define the sampling distribution */
    349 int nweights /**< number of elements in the ground set */
    350 )
    351{
    352 SCIP_Real weightsum;
    353 SCIP_Real randomnr;
    354 int w;
    355#ifdef SCIP_DEBUG
    356 char strbuf[SCIP_MAXSTRLEN];
    357 printRealArray(strbuf, weights, nweights);
    358 SCIPdebugMsg(scip, "Weights: %s\n", strbuf);
    359#endif
    360
    361 weightsum = 0.0;
    362 /* collect sum of weights */
    363 for( w = 0; w < nweights; ++w )
    364 {
    365 weightsum += weights[w];
    366 }
    367 assert(weightsum > 0);
    368
    369 randomnr = SCIPrandomGetReal(rng, 0.0, weightsum);
    370
    371 weightsum = 0.0;
    372 /* choose first element i such that the weight sum exceeds the random number */
    373 for( w = 0; w < nweights - 1; ++w )
    374 {
    375 weightsum += weights[w];
    376
    377 if( weightsum >= randomnr )
    378 break;
    379 }
    380 assert(w < nweights);
    381 assert(weights[w] > 0.0);
    382
    383 return w;
    384}
    385
    386/** select the diving method to apply */
    387static
    389 SCIP* scip, /**< SCIP data structure */
    390 SCIP_HEUR* heur, /**< the heuristic */
    391 SCIP_HEURDATA* heurdata, /**< heuristic data */
    392 int* selection /**< selection made */
    393 )
    394{
    395 SCIP_Bool* methodunavailable;
    396 SCIP_DIVESET** divesets;
    397 int ndivesets;
    398 int d;
    399 SCIP_RANDNUMGEN* rng;
    400 SCIP_DIVECONTEXT divecontext;
    401 SCIP_Real* weights;
    402 SCIP_Real epsilon_t;
    403
    404 divesets = heurdata->divesets;
    405 ndivesets = heurdata->ndivesets;
    406 assert(ndivesets > 0);
    407 assert(divesets != NULL);
    408
    409 SCIP_CALL( SCIPallocClearBufferArray(scip, &methodunavailable, ndivesets) );
    410
    411 divecontext = heurdata->useadaptivecontext ? SCIP_DIVECONTEXT_ADAPTIVE : SCIP_DIVECONTEXT_TOTAL;
    412
    413 /* check availability of divesets */
    414 for( d = 0; d < heurdata->ndivesets; ++d )
    415 {
    416 SCIP_Bool available;
    417 SCIP_CALL( SCIPisDivesetAvailable(scip, heurdata->divesets[d], &available) );
    418 methodunavailable[d] = ! available;
    419 }
    420
    421 *selection = -1;
    422
    423 rng = heurdata->randnumgen;
    424 assert(rng != NULL);
    425
    426 switch (heurdata->seltype) {
    427 case 'e':
    428 epsilon_t = heurdata->epsilon * sqrt(ndivesets / (SCIPheurGetNCalls(heur) + 1.0));
    429 epsilon_t = MAX(epsilon_t, 0.05);
    430
    431 /* select one of the available methods at random */
    432 if( epsilon_t >= 1.0 || SCIPrandomGetReal(rng, 0.0, 1.0) < epsilon_t )
    433 {
    434 do
    435 {
    436 *selection = SCIPrandomGetInt(rng, 0, ndivesets - 1);
    437 }
    438 while( methodunavailable[*selection] );
    439 }
    440 else
    441 {
    442 SCIP_Real bestscore = SCIP_REAL_MAX;
    443 for( d = 0; d < heurdata->ndivesets; ++d )
    444 {
    445 SCIP_Real score;
    446
    447 if( methodunavailable[d] )
    448 continue;
    449
    450 SCIP_CALL( divesetGetSelectionScore(divesets[d], heurdata, divecontext, &score) );
    451
    452 if( score < bestscore )
    453 {
    454 bestscore = score;
    455 *selection = d;
    456 }
    457 }
    458 }
    459 break;
    460 case 'w':
    461 SCIP_CALL( SCIPallocBufferArray(scip, &weights, ndivesets) );
    462
    463 /* initialize weights as inverse of the score + a small positive epsilon */
    464 for( d = 0; d < ndivesets; ++d )
    465 {
    466 SCIP_Real score;
    467
    468 SCIP_CALL( divesetGetSelectionScore(divesets[d], heurdata, divecontext, &score) );
    469
    470 weights[d] = methodunavailable[d] ? 0.0 : 1 / (score + 1e-4);
    471 }
    472
    473 *selection = sampleWeighted(scip, rng, weights, ndivesets);
    474
    475 SCIPfreeBufferArray(scip, &weights);
    476 break;
    477 case 'n':
    478 /* continue from last selection and stop at the next available method */
    479 *selection = heurdata->lastselection;
    480
    481 do
    482 {
    483 *selection = (*selection + 1) % ndivesets;
    484 }
    485 while( methodunavailable[*selection] );
    486 heurdata->lastselection = *selection;
    487 break;
    488 default:
    489 SCIPerrorMessage("Error: Unknown selection method %c\n", heurdata->seltype);
    490
    491 return SCIP_INVALIDDATA;
    492 }
    493
    494 assert(*selection >= 0 && *selection < ndivesets);
    495 SCIPfreeBufferArray(scip, &methodunavailable);
    496
    497 return SCIP_OKAY;
    498}
    499
    500/** execution method of primal heuristic */
    501static
    502SCIP_DECL_HEUREXEC(heurExecAdaptivediving) /*lint --e{715}*/
    503{ /*lint --e{715}*/
    504 SCIP_HEURDATA* heurdata;
    505 SCIP_DIVESET* diveset;
    506 SCIP_DIVESET** divesets;
    507 SCIP_Longint lpiterlimit;
    508 int selection;
    509
    510 assert(heur != NULL);
    511 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    512 assert(scip != NULL);
    513 assert(result != NULL);
    514 assert(SCIPhasCurrentNodeLP(scip));
    515
    516 heurdata = SCIPheurGetData(heur);
    517 if( heurdata->divesets == NULL )
    518 {
    519 SCIP_CALL( findAndStoreDivesets(scip, heur, heurdata) );
    520 }
    521
    522 divesets = heurdata->divesets;
    523 assert(divesets != NULL);
    524 assert(heurdata->ndivesets > 0);
    525
    526 SCIPdebugMsg(scip, "heurExecAdaptivediving: depth %d sols %d inf %u node %lld (last dive at %lld)\n",
    529 nodeinfeasible,
    532 );
    533
    534 *result = SCIP_DELAYED;
    535
    536 /* do not call heuristic in node that was already detected to be infeasible */
    537 if( nodeinfeasible )
    538 return SCIP_OKAY;
    539
    540 /* only call heuristic, if an optimal LP solution is at hand */
    542 return SCIP_OKAY;
    543
    544 /* only call heuristic, if the LP objective value is smaller than the cutoff bound */
    546 return SCIP_OKAY;
    547
    548 /* only call heuristic, if the LP solution is basic (which allows fast resolve in diving) */
    549 if( !SCIPisLPSolBasic(scip) )
    550 return SCIP_OKAY;
    551
    552 /* don't dive two times at the same node */
    554 {
    555 SCIPdebugMsg(scip, "already dived at node here\n");
    556
    557 return SCIP_OKAY;
    558 }
    559
    560 *result = SCIP_DIDNOTRUN;
    561
    562 lpiterlimit = getLPIterlimit(scip, heur, heurdata);
    563
    564 if( lpiterlimit <= 0 )
    565 return SCIP_OKAY;
    566
    567 /* select the next diving strategy based on previous success */
    568 SCIP_CALL( selectDiving(scip, heur, heurdata, &selection) );
    569 assert(selection >= 0 && selection < heurdata->ndivesets);
    570
    571 diveset = divesets[selection];
    572 assert(diveset != NULL);
    573
    574 SCIPdebugMsg(scip, "Selected diveset %s\n", SCIPdivesetGetName(diveset));
    575
    576 SCIP_CALL( SCIPperformGenericDivingAlgorithm(scip, diveset, heurdata->sol, heur, result, nodeinfeasible,
    577 lpiterlimit, -1, -1.0, SCIP_DIVECONTEXT_ADAPTIVE) );
    578
    579 if( *result == SCIP_FOUNDSOL )
    580 {
    581 SCIPdebugMsg(scip, "Solution found by diveset %s\n", SCIPdivesetGetName(diveset));
    582 }
    583
    584 return SCIP_OKAY;
    585}
    586
    587/** creates the adaptivediving heuristic and includes it in SCIP */
    589 SCIP* scip /**< SCIP data structure */
    590 )
    591{
    592 SCIP_RETCODE retcode;
    593 SCIP_HEURDATA* heurdata;
    594 SCIP_HEUR* heur;
    595
    596 /* create adaptivediving data */
    597 heurdata = NULL;
    598 SCIP_CALL( SCIPallocMemory(scip, &heurdata) );
    599
    600 heurdata->divesets = NULL;
    601 heurdata->ndivesets = 0;
    602 heurdata->divesetssize = -1;
    603
    604 SCIP_CALL_TERMINATE( retcode, SCIPcreateRandom(scip, &heurdata->randnumgen, DEFAULT_INITIALSEED, TRUE), TERMINATE );
    605
    606 /* include adaptive diving primal heuristic */
    609 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecAdaptivediving, heurdata) );
    610
    611 assert(heur != NULL);
    612
    613 /* primal heuristic is safe to use in exact solving mode */
    614 SCIPheurMarkExact(heur);
    615
    616 /* set non-NULL pointers to callback methods */
    617 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyAdaptivediving) );
    618 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeAdaptivediving) );
    619 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitAdaptivediving) );
    620 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitAdaptivediving) );
    621
    622 /* add parameters */
    623 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/epsilon",
    624 "parameter that increases probability of exploration among divesets (only active if seltype is 'e')",
    625 &heurdata->epsilon, FALSE, DEFAULT_EPSILON, 0.0, SCIP_REAL_MAX, NULL, NULL) );
    626
    627 SCIP_CALL( SCIPaddCharParam(scip, "heuristics/" HEUR_NAME "/scoretype",
    628 "score parameter for selection: minimize either average 'n'odes, LP 'i'terations,"
    629 "backtrack/'c'onflict ratio, 'd'epth, 1 / 's'olutions, or 1 / solutions'u'ccess",
    630 &heurdata->scoretype, FALSE, DEFAULT_SCORETYPE, "cdinsu", NULL, NULL) );
    631
    632 SCIP_CALL( SCIPaddCharParam(scip, "heuristics/" HEUR_NAME "/seltype",
    633 "selection strategy: (e)psilon-greedy, (w)eighted distribution, (n)ext diving",
    634 &heurdata->seltype, FALSE, DEFAULT_SELTYPE, "enw", NULL, NULL) );
    635
    636 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/useadaptivecontext",
    637 "should the heuristic use its own statistics, or shared statistics?", &heurdata->useadaptivecontext, TRUE,
    639
    640 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/selconfidencecoeff",
    641 "coefficient c to decrease initial confidence (calls + 1.0) / (calls + c) in scores",
    642 &heurdata->selconfidencecoeff, FALSE, DEFAULT_SELCONFIDENCECOEFF, 1.0, (SCIP_Real)INT_MAX, NULL, NULL) );
    643
    644 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/maxlpiterquot",
    645 "maximal fraction of diving LP iterations compared to node LP iterations",
    646 &heurdata->maxlpiterquot, FALSE, DEFAULT_MAXLPITERQUOT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
    647
    648 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/maxlpiterofs",
    649 "additional number of allowed LP iterations",
    650 &heurdata->maxlpiterofs, FALSE, DEFAULT_MAXLPITEROFS, 0L, (SCIP_Longint)INT_MAX, NULL, NULL) );
    651
    652 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/bestsolweight",
    653 "weight of incumbent solutions compared to other solutions in computation of LP iteration limit",
    654 &heurdata->bestsolweight, FALSE, DEFAULT_BESTSOLWEIGHT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
    655
    656TERMINATE:
    657 if( retcode != SCIP_OKAY )
    658 {
    659 SCIPfreeMemory(scip, &heurdata);
    660 return retcode;
    661 }
    662
    663 return SCIP_OKAY;
    664}
    SCIP_VAR * h
    Definition: circlepacking.c:68
    SCIP_VAR * w
    Definition: circlepacking.c:67
    #define NULL
    Definition: def.h:248
    #define SCIP_MAXSTRLEN
    Definition: def.h:269
    #define SCIP_Longint
    Definition: def.h:141
    #define SCIP_REAL_MAX
    Definition: def.h:158
    #define SCIP_INVALID
    Definition: def.h:178
    #define SCIP_Bool
    Definition: def.h:91
    #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_TERMINATE(retcode, x, TERM)
    Definition: def.h:376
    #define SCIPABORT()
    Definition: def.h:327
    #define SCIP_CALL(x)
    Definition: def.h:355
    int SCIPgetNOrigConss(SCIP *scip)
    Definition: scip_prob.c:3712
    int SCIPgetNOrigVars(SCIP *scip)
    Definition: scip_prob.c:2838
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_RETCODE SCIPaddLongintParam(SCIP *scip, const char *name, const char *desc, SCIP_Longint *valueptr, SCIP_Bool isadvanced, SCIP_Longint defaultvalue, SCIP_Longint minvalue, SCIP_Longint maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:111
    SCIP_RETCODE SCIPaddCharParam(SCIP *scip, const char *name, const char *desc, char *valueptr, SCIP_Bool isadvanced, char defaultvalue, const char *allowedvalues, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:167
    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 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_Bool SCIPdivesetIsPublic(SCIP_DIVESET *diveset)
    Definition: heur.c:764
    SCIP_Longint SCIPdivesetGetNBacktracks(SCIP_DIVESET *diveset, SCIP_DIVECONTEXT divecontext)
    Definition: heur.c:615
    SCIP_Longint SCIPdivesetGetNSols(SCIP_DIVESET *diveset, SCIP_DIVECONTEXT divecontext)
    Definition: heur.c:641
    SCIP_Longint SCIPdivesetGetNConflicts(SCIP_DIVESET *diveset, SCIP_DIVECONTEXT divecontext)
    Definition: heur.c:628
    SCIP_Real SCIPdivesetGetAvgDepth(SCIP_DIVESET *diveset, SCIP_DIVECONTEXT divecontext)
    Definition: heur.c:537
    SCIP_Longint SCIPdivesetGetNLPIterations(SCIP_DIVESET *diveset, SCIP_DIVECONTEXT divecontext)
    Definition: heur.c:589
    SCIP_Longint SCIPdivesetGetSolSuccess(SCIP_DIVESET *diveset, SCIP_DIVECONTEXT divecontext)
    Definition: heur.c:471
    const char * SCIPdivesetGetName(SCIP_DIVESET *diveset)
    Definition: heur.c:445
    SCIP_RETCODE SCIPisDivesetAvailable(SCIP *scip, SCIP_DIVESET *diveset, SCIP_Bool *available)
    Definition: scip_heur.c:368
    int SCIPdivesetGetNCalls(SCIP_DIVESET *diveset, SCIP_DIVECONTEXT divecontext)
    Definition: heur.c:485
    SCIP_Longint SCIPdivesetGetNProbingNodes(SCIP_DIVESET *diveset, SCIP_DIVECONTEXT divecontext)
    Definition: heur.c:602
    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_HEUR ** SCIPgetHeurs(SCIP *scip)
    Definition: scip_heur.c:276
    SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
    Definition: scip_heur.c:183
    SCIP_Longint SCIPheurGetNSolsFound(SCIP_HEUR *heur)
    Definition: heur.c:1603
    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
    int SCIPgetNHeurs(SCIP *scip)
    Definition: scip_heur.c:287
    SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
    Definition: heur.c:1593
    int SCIPheurGetNDivesets(SCIP_HEUR *heur)
    Definition: heur.c:1675
    void SCIPheurMarkExact(SCIP_HEUR *heur)
    Definition: heur.c:1457
    SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
    Definition: scip_heur.c:199
    const char * SCIPheurGetName(SCIP_HEUR *heur)
    Definition: heur.c:1467
    SCIP_DIVESET ** SCIPheurGetDivesets(SCIP_HEUR *heur)
    Definition: heur.c:1665
    void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
    Definition: heur.c:1378
    SCIP_Longint SCIPgetLastDivenode(SCIP *scip)
    Definition: scip_lp.c:2710
    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
    SCIP_Bool SCIPisLPSolBasic(SCIP *scip)
    Definition: scip_lp.c:673
    #define SCIPfreeBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:110
    #define SCIPallocClearBufferArray(scip, ptr, num)
    Definition: scip_mem.h:126
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPallocMemory(scip, ptr)
    Definition: scip_mem.h:60
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPfreeMemory(scip, ptr)
    Definition: scip_mem.h:78
    #define SCIPallocBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:93
    #define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
    Definition: scip_mem.h:99
    SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:516
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1252
    int SCIPgetNSols(SCIP *scip)
    Definition: scip_sol.c:2882
    SCIP_Longint SCIPgetNNodes(SCIP *scip)
    SCIP_Longint SCIPgetNNodeLPIterations(SCIP *scip)
    SCIP_Real SCIPgetCutoffbound(SCIP *scip)
    SCIP_RETCODE SCIPperformGenericDivingAlgorithm(SCIP *scip, SCIP_DIVESET *diveset, SCIP_SOL *worksol, SCIP_HEUR *heur, SCIP_RESULT *result, SCIP_Bool nodeinfeasible, SCIP_Longint iterlim, int nodelimit, SCIP_Real lpresolvedomchgquot, SCIP_DIVECONTEXT divecontext)
    Definition: heuristics.c:221
    SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    int SCIPgetDepth(SCIP *scip)
    Definition: scip_tree.c:672
    void SCIPfreeRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen)
    void SCIPsetRandomSeed(SCIP *scip, SCIP_RANDNUMGEN *randnumgen, unsigned int seed)
    SCIP_Real SCIPrandomGetReal(SCIP_RANDNUMGEN *randnumgen, SCIP_Real minrandval, SCIP_Real maxrandval)
    Definition: misc.c:10245
    SCIP_RETCODE SCIPcreateRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen, unsigned int initialseed, SCIP_Bool useglobalseed)
    int SCIPrandomGetInt(SCIP_RANDNUMGEN *randnumgen, int minrandval, int maxrandval)
    Definition: misc.c:10223
    static SCIP_Longint getLPIterlimit(SCIP *scip, SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
    static SCIP_RETCODE divesetGetSelectionScore(SCIP_DIVESET *diveset, SCIP_HEURDATA *heurdata, SCIP_DIVECONTEXT divecontext, SCIP_Real *scoreptr)
    #define DEFAULT_INITIALSEED
    static SCIP_DECL_HEURFREE(heurFreeAdaptivediving)
    static SCIP_DECL_HEUREXIT(heurExitAdaptivediving)
    #define HEUR_TIMING
    static SCIP_DECL_HEURCOPY(heurCopyAdaptivediving)
    static int sampleWeighted(SCIP *scip, SCIP_RANDNUMGEN *rng, SCIP_Real *weights, int nweights)
    static SCIP_RETCODE findAndStoreDivesets(SCIP *scip, SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
    #define DEFAULT_MAXLPITERQUOT
    #define HEUR_FREQOFS
    #define HEUR_DESC
    #define DEFAULT_USEADAPTIVECONTEXT
    SCIP_RETCODE SCIPincludeHeurAdaptivediving(SCIP *scip)
    #define DEFAULT_SCORETYPE
    #define DEFAULT_SELCONFIDENCECOEFF
    static SCIP_DECL_HEURINIT(heurInitAdaptivediving)
    #define DIVESETS_INITIALSIZE
    #define HEUR_DISPCHAR
    #define DEFAULT_EPSILON
    #define HEUR_MAXDEPTH
    #define HEUR_PRIORITY
    #define DEFAULT_MAXLPITEROFS
    #define DEFAULT_SELTYPE
    #define HEUR_NAME
    static SCIP_DECL_HEUREXEC(heurExecAdaptivediving)
    #define HEUR_FREQ
    #define HEUR_USESSUBSCIP
    static SCIP_RETCODE selectDiving(SCIP *scip, SCIP_HEUR *heur, SCIP_HEURDATA *heurdata, int *selection)
    #define DEFAULT_BESTSOLWEIGHT
    diving heuristic that selects adaptively between the existing, public dive sets
    methods commonly used by primal heuristics
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    default SCIP plugins
    SCIP_SOL * sol
    Definition: struct_heur.h:71
    enum SCIP_DiveContext SCIP_DIVECONTEXT
    Definition: type_heur.h:73
    struct SCIP_HeurData SCIP_HEURDATA
    Definition: type_heur.h:77
    @ SCIP_DIVECONTEXT_TOTAL
    Definition: type_heur.h:68
    @ SCIP_DIVECONTEXT_ADAPTIVE
    Definition: type_heur.h:70
    @ SCIP_LPSOLSTAT_OPTIMAL
    Definition: type_lp.h:44
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_DELAYED
    Definition: type_result.h:43
    @ SCIP_FOUNDSOL
    Definition: type_result.h:56
    @ SCIP_INVALIDDATA
    Definition: type_retcode.h:52
    @ SCIP_PARAMETERWRONGVAL
    Definition: type_retcode.h:57
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63