Scippy

    SCIP

    Solving Constraint Integer Programs

    heur_rootsoldiving.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_rootsoldiving.c
    26 * @ingroup DEFPLUGINS_HEUR
    27 * @brief LP diving heuristic that changes variable's objective values using root LP solution as guide
    28 * @author Kati Wolter
    29 */
    30
    31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    32
    35#include "scip/pub_heur.h"
    36#include "scip/pub_message.h"
    37#include "scip/pub_var.h"
    38#include "scip/scip_branch.h"
    39#include "scip/scip_exact.h"
    40#include "scip/scip_general.h"
    41#include "scip/scip_heur.h"
    42#include "scip/scip_lp.h"
    43#include "scip/scip_mem.h"
    44#include "scip/scip_message.h"
    45#include "scip/scip_numerics.h"
    46#include "scip/scip_param.h"
    47#include "scip/scip_prob.h"
    48#include "scip/scip_sol.h"
    50#include "scip/scip_tree.h"
    51#include <string.h>
    52
    53#define HEUR_NAME "rootsoldiving"
    54#define HEUR_DESC "LP diving heuristic that changes variable's objective values using root LP solution as guide"
    55#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_OBJDIVING
    56#define HEUR_PRIORITY -1005000
    57#define HEUR_FREQ 20
    58#define HEUR_FREQOFS 5
    59#define HEUR_MAXDEPTH -1
    60#define HEUR_TIMING SCIP_HEURTIMING_AFTERLPPLUNGE
    61#define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
    62
    63
    64/*
    65 * Default parameter settings
    66 */
    67
    68#define DEFAULT_MINRELDEPTH 0.0 /**< minimal relative depth to start diving */
    69#define DEFAULT_MAXRELDEPTH 1.0 /**< maximal relative depth to start diving */
    70#define DEFAULT_MAXLPITERQUOT 0.01 /**< maximal fraction of diving LP iterations compared to node LP iterations */
    71#define DEFAULT_MAXLPITEROFS 1000 /**< additional number of allowed LP iterations */
    72#define DEFAULT_MAXSOLS -1 /**< total number of feasible solutions found up to which heuristic is called
    73 * (-1: no limit) */
    74#define DEFAULT_DEPTHFAC 0.5 /**< maximal diving depth: number of binary/integer variables times depthfac */
    75#define DEFAULT_DEPTHFACNOSOL 2.0 /**< maximal diving depth factor if no feasible solution was found yet */
    76
    77#define MINLPITER 10000 /**< minimal number of LP iterations allowed in each LP solving call */
    78#define DEFAULT_ALPHA 0.9 /**< soft rounding factor to fade out objective coefficients */
    79
    80
    81/* locally defined heuristic data */
    82struct SCIP_HeurData
    83{
    84 SCIP_SOL* sol; /**< working solution */
    85 SCIP_Real minreldepth; /**< minimal relative depth to start diving */
    86 SCIP_Real maxreldepth; /**< maximal relative depth to start diving */
    87 SCIP_Real maxlpiterquot; /**< maximal fraction of diving LP iterations compared to node LP iterations */
    88 int maxlpiterofs; /**< additional number of allowed LP iterations */
    89 int maxsols; /**< total number of feasible solutions found up to which heuristic is called
    90 * (-1: no limit) */
    91 SCIP_Real depthfac; /**< maximal diving depth: number of binary/integer variables times depthfac */
    92 SCIP_Real depthfacnosol; /**< maximal diving depth factor if no feasible solution was found yet */
    93 SCIP_Real alpha; /**< soft rounding factor to fade out objective coefficients */
    94 SCIP_Longint nlpiterations; /**< LP iterations used in this heuristic */
    95 int nsuccess; /**< number of runs that produced at least one feasible solution */
    96};
    97
    98
    99/*
    100 * Callback methods
    101 */
    102
    103/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
    104static
    105SCIP_DECL_HEURCOPY(heurCopyRootsoldiving)
    106{ /*lint --e{715}*/
    107 assert(scip != NULL);
    108 assert(heur != NULL);
    109 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    110
    111 /* call inclusion method of primal heuristic */
    113
    114 return SCIP_OKAY;
    115}
    116
    117/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
    118static
    119SCIP_DECL_HEURFREE(heurFreeRootsoldiving) /*lint --e{715}*/
    120{ /*lint --e{715}*/
    121 SCIP_HEURDATA* heurdata;
    122
    123 assert(heur != NULL);
    124 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    125 assert(scip != NULL);
    126
    127 /* free heuristic data */
    128 heurdata = SCIPheurGetData(heur);
    129 assert(heurdata != NULL);
    130 SCIPfreeBlockMemory(scip, &heurdata);
    131 SCIPheurSetData(heur, NULL);
    132
    133 return SCIP_OKAY;
    134}
    135
    136
    137/** initialization method of primal heuristic (called after problem was transformed) */
    138static
    139SCIP_DECL_HEURINIT(heurInitRootsoldiving) /*lint --e{715}*/
    140{ /*lint --e{715}*/
    141 SCIP_HEURDATA* heurdata;
    142
    143 assert(heur != NULL);
    144 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    145
    146 /* get heuristic data */
    147 heurdata = SCIPheurGetData(heur);
    148 assert(heurdata != NULL);
    149
    150 /* create working solution */
    151 SCIP_CALL( SCIPcreateSol(scip, &heurdata->sol, heur) );
    152
    153 /* initialize data */
    154 heurdata->nlpiterations = 0;
    155 heurdata->nsuccess = 0;
    156
    157 return SCIP_OKAY;
    158}
    159
    160
    161/** deinitialization method of primal heuristic (called before transformed problem is freed) */
    162static
    163SCIP_DECL_HEUREXIT(heurExitRootsoldiving) /*lint --e{715}*/
    164{ /*lint --e{715}*/
    165 SCIP_HEURDATA* heurdata;
    166
    167 assert(heur != NULL);
    168 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    169
    170 /* get heuristic data */
    171 heurdata = SCIPheurGetData(heur);
    172 assert(heurdata != NULL);
    173
    174 /* free working solution */
    175 SCIP_CALL( SCIPfreeSol(scip, &heurdata->sol) );
    176
    177 return SCIP_OKAY;
    178}
    179
    180
    181/** execution method of primal heuristic */
    182static
    183SCIP_DECL_HEUREXEC(heurExecRootsoldiving) /*lint --e{715}*/
    184{ /*lint --e{715}*/
    185 SCIP_HEURDATA* heurdata;
    186 SCIP_VAR** vars;
    187 SCIP_Real* rootsol;
    188 SCIP_Real* objchgvals;
    189 int* softroundings;
    190 int* intvalrounds;
    191 SCIP_LPSOLSTAT lpsolstat;
    192 SCIP_Real absstartobjval;
    193 SCIP_Real objstep;
    194 SCIP_Real alpha;
    195 SCIP_Real oldobj;
    196 SCIP_Real newobj;
    197 SCIP_Bool lperror;
    198 SCIP_Bool lpsolchanged;
    199 SCIP_Longint nsolsfound;
    200 SCIP_Longint ncalls;
    201 SCIP_Longint nlpiterations;
    202 SCIP_Longint maxnlpiterations;
    203 int nvars;
    204 int nenfovars;
    205 int nlpcands;
    206 int depth;
    207 int maxdepth;
    208 int maxdivedepth;
    209 int divedepth;
    210 int startnlpcands;
    211 int ncycles;
    212 int i;
    213
    214 assert(heur != NULL);
    215 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    216 assert(scip != NULL);
    217 assert(result != NULL);
    218 assert(SCIPhasCurrentNodeLP(scip));
    219
    220 *result = SCIP_DELAYED;
    221
    222 /* do not call heuristic of node was already detected to be infeasible */
    223 if( nodeinfeasible )
    224 return SCIP_OKAY;
    225
    226 /* only call heuristic, if an optimal LP solution is at hand */
    228 return SCIP_OKAY;
    229
    230 /* only call heuristic, if the LP objective value is smaller than the cutoff bound */
    232 return SCIP_OKAY;
    233
    234 /* only call heuristic, if the LP solution is basic (which allows fast resolve in diving) */
    235 if( !SCIPisLPSolBasic(scip) )
    236 return SCIP_OKAY;
    237
    238 /* don't dive two times at the same node */
    240 return SCIP_OKAY;
    241
    242 *result = SCIP_DIDNOTRUN;
    243
    244 /* get heuristic's data */
    245 heurdata = SCIPheurGetData(heur);
    246 assert(heurdata != NULL);
    247
    248 /* only apply heuristic, if only a few solutions have been found */
    249 if( heurdata->maxsols >= 0 && SCIPgetNSolsFound(scip) >= heurdata->maxsols )
    250 return SCIP_OKAY;
    251
    252 /* only try to dive, if we are in the correct part of the tree, given by minreldepth and maxreldepth */
    253 depth = SCIPgetDepth(scip);
    254 maxdepth = SCIPgetMaxDepth(scip);
    255 maxdepth = MAX(maxdepth, 30);
    256 if( depth < heurdata->minreldepth*maxdepth || depth > heurdata->maxreldepth*maxdepth )
    257 return SCIP_OKAY;
    258
    259 /* calculate the maximal number of LP iterations until heuristic is aborted */
    260 nlpiterations = SCIPgetNNodeLPIterations(scip);
    261 ncalls = SCIPheurGetNCalls(heur);
    262 nsolsfound = 10*SCIPheurGetNBestSolsFound(heur) + heurdata->nsuccess;
    263 maxnlpiterations = (SCIP_Longint)(((nsolsfound+1.0)/(ncalls+1.0)) * heurdata->maxlpiterquot * nlpiterations);
    264 maxnlpiterations += heurdata->maxlpiterofs;
    265
    266 /* don't try to dive, if we took too many LP iterations during diving */
    267 if( heurdata->nlpiterations >= maxnlpiterations )
    268 return SCIP_OKAY;
    269
    270 /* allow at least a certain number of LP iterations in this dive */
    271 maxnlpiterations = MAX(maxnlpiterations, heurdata->nlpiterations + MINLPITER);
    272
    273 /* get number of fractional variables, that should be integral */
    274 nlpcands = SCIPgetNLPBranchCands(scip);
    275
    276 /* don't try to dive, if there are no fractional variables */
    277 if( nlpcands == 0 )
    278 return SCIP_OKAY;
    279
    280 /* get all variables of LP */
    281 vars = SCIPgetVars(scip);
    282 nvars = SCIPgetNVars(scip);
    283 nenfovars = nvars - SCIPgetNContVars(scip) - SCIPgetNContImplVars(scip);
    284 assert(nenfovars >= 0);
    285
    286 /* calculate the maximal diving depth */
    287 if( SCIPgetNSolsFound(scip) == 0 )
    288 maxdivedepth = (int)(heurdata->depthfacnosol * nenfovars);
    289 else
    290 maxdivedepth = (int)(heurdata->depthfac * nenfovars);
    291 maxdivedepth = MAX(maxdivedepth, 10);
    292
    293 *result = SCIP_DIDNOTFIND;
    294
    295 /* get root solution value of all binary and integer variables */
    296 SCIP_CALL( SCIPallocBufferArray(scip, &rootsol, nenfovars) );
    297 for( i = 0; i < nenfovars; i++ )
    298 rootsol[i] = SCIPvarGetRootSol(vars[i]);
    299
    300 /* get current LP objective value, and calculate length of a single step in an objective coefficient */
    301 absstartobjval = SCIPgetLPObjval(scip);
    302 absstartobjval = ABS(absstartobjval);
    303 absstartobjval = MAX(absstartobjval, 1.0);
    304 objstep = absstartobjval / 10.0;
    305
    306 /* initialize array storing the preferred soft rounding directions and counting the integral value rounds */
    307 SCIP_CALL( SCIPallocBufferArray(scip, &softroundings, nenfovars) );
    308 BMSclearMemoryArray(softroundings, nenfovars);
    309 SCIP_CALL( SCIPallocBufferArray(scip, &intvalrounds, nenfovars) );
    310 BMSclearMemoryArray(intvalrounds, nenfovars);
    311
    312 /* allocate temporary memory for buffering objective changes */
    313 SCIP_CALL( SCIPallocBufferArray(scip, &objchgvals, nenfovars) );
    314
    315 /* start diving */
    317
    318 SCIPdebugMsg(scip, "(node %" SCIP_LONGINT_FORMAT ") executing rootsoldiving heuristic: depth=%d, %d fractionals, dualbound=%g, maxnlpiterations=%" SCIP_LONGINT_FORMAT ", maxdivedepth=%d, LPobj=%g, objstep=%g\n",
    319 SCIPgetNNodes(scip), SCIPgetDepth(scip), nlpcands, SCIPgetDualbound(scip), maxnlpiterations, maxdivedepth,
    320 SCIPgetLPObjval(scip), objstep);
    321
    322 lperror = FALSE;
    323 divedepth = 0;
    324 lpsolstat = SCIP_LPSOLSTAT_OPTIMAL;
    325 alpha = heurdata->alpha;
    326 ncycles = 0;
    327 lpsolchanged = TRUE;
    328 startnlpcands = nlpcands;
    329 while( !lperror && lpsolstat == SCIP_LPSOLSTAT_OPTIMAL && nlpcands > 0 && ncycles < 10
    330 && (divedepth < 10
    331 || nlpcands <= startnlpcands - divedepth/2
    332 || (divedepth < maxdivedepth && heurdata->nlpiterations < maxnlpiterations))
    333 && !SCIPisStopped(scip) )
    334 {
    335 SCIP_Bool success;
    336 int hardroundingidx;
    337 int hardroundingdir;
    338 SCIP_Real hardroundingoldbd;
    339 SCIP_Real hardroundingnewbd;
    340 SCIP_Bool boundschanged;
    341
    342 SCIP_RETCODE retcode;
    343
    344 /* create solution from diving LP and try to round it */
    345 SCIP_CALL( SCIPlinkLPSol(scip, heurdata->sol) );
    346 SCIP_CALL( SCIProundSol(scip, heurdata->sol, &success) );
    347
    348 if( success && !SCIPisExact(scip) )
    349 {
    350 SCIPdebugMsg(scip, "rootsoldiving found roundable primal solution: obj=%g\n", SCIPgetSolOrigObj(scip, heurdata->sol));
    351
    352 /* try to add solution to SCIP */
    353 SCIP_CALL( SCIPtrySol(scip, heurdata->sol, FALSE, FALSE, FALSE, FALSE, FALSE, &success) );
    354
    355 /* check, if solution was feasible and good enough */
    356 if( success )
    357 {
    358 SCIPdebugMsg(scip, " -> solution was feasible and good enough\n");
    359 *result = SCIP_FOUNDSOL;
    360 }
    361 }
    362
    363 divedepth++;
    364 hardroundingidx = -1;
    365 hardroundingdir = 0;
    366 hardroundingoldbd = 0.0;
    367 hardroundingnewbd = 0.0;
    368 boundschanged = FALSE;
    369
    370 SCIPdebugMsg(scip, "dive %d/%d, LP iter %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ":\n", divedepth, maxdivedepth, heurdata->nlpiterations, maxnlpiterations);
    371
    372 /* round solution x* from diving LP:
    373 * - x~_j = down(x*_j) if x*_j is integer or binary variable and x*_j <= root solution_j
    374 * - x~_j = up(x*_j) if x*_j is integer or binary variable and x*_j > root solution_j
    375 * - x~_j = x*_j if x*_j is continuous variable
    376 * change objective function in diving LP:
    377 * - if x*_j is integral, or j is a continuous variable, set obj'_j = alpha * obj_j
    378 * - otherwise, set obj'_j = alpha * obj_j + sign(x*_j - x~_j)
    379 */
    380 for( i = 0; i < nenfovars; i++ )
    381 {
    382 SCIP_VAR* var;
    383 SCIP_Real solval;
    384
    385 var = vars[i];
    386 oldobj = SCIPgetVarObjDive(scip, var);
    387 newobj = oldobj;
    388
    389 solval = SCIPvarGetLPSol(var);
    390 if( SCIPisFeasIntegral(scip, solval) )
    391 {
    392 /* if the variable became integral after a soft rounding, count the rounds; after a while, fix it to its
    393 * current integral value;
    394 * otherwise, fade out the objective value
    395 */
    396 if( softroundings[i] != 0 && lpsolchanged )
    397 {
    398 intvalrounds[i]++;
    399 if( intvalrounds[i] == 5 && SCIPgetVarLbDive(scip, var) < SCIPgetVarUbDive(scip, var) - 0.5 )
    400 {
    401 /* use exact integral value, if the variable is only integral within numerical tolerances */
    402 solval = SCIPfloor(scip, solval+0.5);
    403 SCIPdebugMsg(scip, " -> fixing <%s> = %g\n", SCIPvarGetName(var), solval);
    404 SCIP_CALL( SCIPchgVarLbDive(scip, var, solval) );
    405 SCIP_CALL( SCIPchgVarUbDive(scip, var, solval) );
    406 boundschanged = TRUE;
    407 }
    408 }
    409 else
    410 newobj = alpha * oldobj;
    411 }
    412 else if( solval <= rootsol[i] )
    413 {
    414 /* if the variable was soft rounded most of the time downwards, round it downwards by changing the bounds;
    415 * otherwise, apply soft rounding by changing the objective value
    416 */
    417 softroundings[i]--;
    418 if( softroundings[i] <= -10 && hardroundingidx == -1 )
    419 {
    420 SCIPdebugMsg(scip, " -> hard rounding <%s>[%g] <= %g\n",
    421 SCIPvarGetName(var), solval, SCIPfeasFloor(scip, solval));
    422 hardroundingidx = i;
    423 hardroundingdir = -1;
    424 hardroundingoldbd = SCIPgetVarUbDive(scip, var);
    425 hardroundingnewbd = SCIPfeasFloor(scip, solval);
    426 SCIP_CALL( SCIPchgVarUbDive(scip, var, hardroundingnewbd) );
    427 boundschanged = TRUE;
    428 }
    429 else
    430 newobj = alpha * oldobj + objstep;
    431 }
    432 else
    433 {
    434 /* if the variable was soft rounded most of the time upwards, round it upwards by changing the bounds;
    435 * otherwise, apply soft rounding by changing the objective value
    436 */
    437 softroundings[i]++;
    438 if( softroundings[i] >= +10 && hardroundingidx == -1 )
    439 {
    440 SCIPdebugMsg(scip, " -> hard rounding <%s>[%g] >= %g\n",
    441 SCIPvarGetName(var), solval, SCIPfeasCeil(scip, solval));
    442 hardroundingidx = i;
    443 hardroundingdir = +1;
    444 hardroundingoldbd = SCIPgetVarLbDive(scip, var);
    445 hardroundingnewbd = SCIPfeasCeil(scip, solval);
    446 SCIP_CALL( SCIPchgVarLbDive(scip, var, hardroundingnewbd) );
    447 boundschanged = TRUE;
    448 }
    449 else
    450 newobj = alpha * oldobj - objstep;
    451 }
    452
    453 /* remember the objective change */
    454 objchgvals[i] = newobj;
    455 }
    456
    457 /* apply objective changes if there was no bound change */
    458 if( !boundschanged )
    459 {
    460 /* apply cached changes on integer variables */
    461 for( i = 0; i < nenfovars; ++i )
    462 {
    463 SCIP_VAR* var;
    464
    465 var = vars[i];
    466 SCIPdebugMsg(scip, " -> i=%d var <%s>, solval=%g, rootsol=%g, oldobj=%g, newobj=%g\n",
    467 i, SCIPvarGetName(var), SCIPvarGetLPSol(var), rootsol[i], SCIPgetVarObjDive(scip, var), objchgvals[i]);
    468
    469 SCIP_CALL( SCIPchgVarObjDive(scip, var, objchgvals[i]) );
    470 }
    471
    472 /* fade out the objective values of the continuous variables */
    473 for( i = nenfovars; i < nvars; i++ )
    474 {
    475 SCIP_VAR* var;
    476
    477 var = vars[i];
    478 oldobj = SCIPgetVarObjDive(scip, var);
    479 newobj = alpha * oldobj;
    480
    481 SCIPdebugMsg(scip, " -> i=%d var <%s>, solval=%g, oldobj=%g, newobj=%g\n",
    482 i, SCIPvarGetName(var), SCIPvarGetLPSol(var), oldobj, newobj);
    483
    484 SCIP_CALL( SCIPchgVarObjDive(scip, var, newobj) );
    485 }
    486 }
    487
    488 SOLVEAGAIN:
    489 /* resolve the diving LP */
    490 nlpiterations = SCIPgetNLPIterations(scip);
    491
    492 retcode = SCIPsolveDiveLP(scip, MAX((int)(maxnlpiterations - heurdata->nlpiterations), MINLPITER), &lperror, NULL);
    493 lpsolstat = SCIPgetLPSolstat(scip);
    494
    495 /* Errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
    496 * Hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
    497 */
    498 if( retcode != SCIP_OKAY )
    499 {
    500#ifndef NDEBUG
    501 if( lpsolstat != SCIP_LPSOLSTAT_UNBOUNDEDRAY )
    502 {
    503 SCIP_CALL( retcode );
    504 }
    505#endif
    506 SCIPwarningMessage(scip, "Error while solving LP in Rootsoldiving heuristic; LP solve terminated with code <%d>\n", retcode);
    507 SCIPwarningMessage(scip, "This does not affect the remaining solution procedure --> continue\n");
    508 }
    509
    510 if( lperror )
    511 break;
    512
    513 /* update iteration count */
    514 heurdata->nlpiterations += SCIPgetNLPIterations(scip) - nlpiterations;
    515
    516 /* if no LP iterations were performed, we stayed at the same solution -> count this cycling */
    517 lpsolchanged = (SCIPgetNLPIterations(scip) != nlpiterations);
    518 if( lpsolchanged )
    519 ncycles = 0;
    520 else if( !boundschanged ) /* do not count if integral variables have been fixed */
    521 ncycles++;
    522
    523 /* get LP solution status and number of fractional variables, that should be integral */
    524 if( lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE && hardroundingidx != -1 )
    525 {
    526 SCIP_VAR* var;
    527
    528 var = vars[hardroundingidx];
    529
    530 /* round the hard rounded variable to the opposite direction and resolve the LP */
    531 if( hardroundingdir == -1 )
    532 {
    533 SCIPdebugMsg(scip, " -> opposite hard rounding <%s> >= %g\n", SCIPvarGetName(var), hardroundingnewbd + 1.0);
    534 SCIP_CALL( SCIPchgVarUbDive(scip, var, hardroundingoldbd) );
    535 SCIP_CALL( SCIPchgVarLbDive(scip, var, hardroundingnewbd + 1.0) );
    536 }
    537 else
    538 {
    539 SCIPdebugMsg(scip, " -> opposite hard rounding <%s> <= %g\n", SCIPvarGetName(var), hardroundingnewbd - 1.0);
    540 SCIP_CALL( SCIPchgVarLbDive(scip, var, hardroundingoldbd) );
    541 SCIP_CALL( SCIPchgVarUbDive(scip, var, hardroundingnewbd - 1.0) );
    542 }
    543 hardroundingidx = -1;
    544 goto SOLVEAGAIN;
    545 }
    546 if( lpsolstat == SCIP_LPSOLSTAT_OPTIMAL )
    547 nlpcands = SCIPgetNLPBranchCands(scip);
    548 SCIPdebugMsg(scip, " -> lpsolstat=%d, nfrac=%d\n", lpsolstat, nlpcands);
    549 }
    550
    551 SCIPdebugMsg(scip, "---> diving finished: lpsolstat = %d, depth %d/%d, LP iter %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT "\n",
    552 lpsolstat, divedepth, maxdivedepth, heurdata->nlpiterations, maxnlpiterations);
    553
    554 /* check if a solution has been found */
    555 if( nlpcands == 0 && !lperror && lpsolstat == SCIP_LPSOLSTAT_OPTIMAL )
    556 {
    557 SCIP_Bool success;
    558
    559 /* create solution from diving LP */
    560 SCIP_CALL( SCIPlinkLPSol(scip, heurdata->sol) );
    561 SCIPdebugMsg(scip, "rootsoldiving found primal solution: obj=%g\n", SCIPgetSolOrigObj(scip, heurdata->sol));
    562
    563 /* in exact mode we have to end diving prior to trying the solution */
    564 if( SCIPisExact(scip) )
    565 {
    566 SCIP_CALL( SCIPunlinkSol(scip, heurdata->sol) );
    568 }
    569
    570 /* try to add solution to SCIP */
    571 SCIP_CALL( SCIPtrySol(scip, heurdata->sol, FALSE, FALSE, FALSE, FALSE, FALSE, &success) );
    572
    573 /* check, if solution was feasible and good enough */
    574 if( success )
    575 {
    576 SCIPdebugMsg(scip, " -> solution was feasible and good enough\n");
    577 *result = SCIP_FOUNDSOL;
    578 }
    579 }
    580
    581 /* end diving */
    582 if( SCIPinDive(scip) )
    583 {
    585 }
    586
    587 if( *result == SCIP_FOUNDSOL )
    588 heurdata->nsuccess++;
    589
    590 /* free temporary memory */
    591 SCIPfreeBufferArray(scip, &objchgvals);
    592 SCIPfreeBufferArray(scip, &intvalrounds);
    593 SCIPfreeBufferArray(scip, &softroundings);
    594 SCIPfreeBufferArray(scip, &rootsol);
    595
    596 SCIPdebugMsg(scip, "rootsoldiving heuristic finished\n");
    597
    598 return SCIP_OKAY;
    599}
    600
    601
    602/*
    603 * heuristic specific interface methods
    604 */
    605
    606/** creates the rootsoldiving heuristic and includes it in SCIP */
    608 SCIP* scip /**< SCIP data structure */
    609 )
    610{
    611 SCIP_HEURDATA* heurdata;
    612 SCIP_HEUR* heur;
    613
    614 /* create Rootsoldiving primal heuristic data */
    615 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    616
    617 /* include primal heuristic */
    620 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecRootsoldiving, heurdata) );
    621
    622 assert(heur != NULL);
    623
    624 /* primal heuristic is safe to use in exact solving mode */
    625 SCIPheurMarkExact(heur);
    626
    627 /* set non-NULL pointers to callback methods */
    628 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyRootsoldiving) );
    629 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeRootsoldiving) );
    630 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitRootsoldiving) );
    631 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitRootsoldiving) );
    632
    633 /* rootsoldiving heuristic parameters */
    635 "heuristics/rootsoldiving/minreldepth",
    636 "minimal relative depth to start diving",
    637 &heurdata->minreldepth, TRUE, DEFAULT_MINRELDEPTH, 0.0, 1.0, NULL, NULL) );
    639 "heuristics/rootsoldiving/maxreldepth",
    640 "maximal relative depth to start diving",
    641 &heurdata->maxreldepth, TRUE, DEFAULT_MAXRELDEPTH, 0.0, 1.0, NULL, NULL) );
    643 "heuristics/rootsoldiving/maxlpiterquot",
    644 "maximal fraction of diving LP iterations compared to node LP iterations",
    645 &heurdata->maxlpiterquot, FALSE, DEFAULT_MAXLPITERQUOT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
    647 "heuristics/rootsoldiving/maxlpiterofs",
    648 "additional number of allowed LP iterations",
    649 &heurdata->maxlpiterofs, FALSE, DEFAULT_MAXLPITEROFS, 0, INT_MAX, NULL, NULL) );
    651 "heuristics/rootsoldiving/maxsols",
    652 "total number of feasible solutions found up to which heuristic is called (-1: no limit)",
    653 &heurdata->maxsols, TRUE, DEFAULT_MAXSOLS, -1, INT_MAX, NULL, NULL) );
    655 "heuristics/rootsoldiving/depthfac",
    656 "maximal diving depth: number of binary/integer variables times depthfac",
    657 &heurdata->depthfac, TRUE, DEFAULT_DEPTHFAC, 0.0, SCIP_REAL_MAX, NULL, NULL) );
    659 "heuristics/rootsoldiving/depthfacnosol",
    660 "maximal diving depth factor if no feasible solution was found yet",
    661 &heurdata->depthfacnosol, TRUE, DEFAULT_DEPTHFACNOSOL, 0.0, SCIP_REAL_MAX, NULL, NULL) );
    663 "heuristics/rootsoldiving/alpha",
    664 "soft rounding factor to fade out objective coefficients",
    665 &heurdata->alpha, TRUE, DEFAULT_ALPHA, 0.0, 1.0, NULL, NULL) );
    666
    667 return SCIP_OKAY;
    668}
    669
    #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 SCIP_Real
    Definition: def.h:156
    #define ABS(x)
    Definition: def.h:216
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:148
    #define SCIP_CALL(x)
    Definition: def.h:355
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:759
    int SCIPgetNContVars(SCIP *scip)
    Definition: scip_prob.c:2569
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    SCIP_VAR ** SCIPgetVars(SCIP *scip)
    Definition: scip_prob.c:2201
    int SCIPgetNContImplVars(SCIP *scip)
    Definition: scip_prob.c:2522
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
    Definition: scip_message.c:120
    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 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 SCIPincludeHeurRootsoldiving(SCIP *scip)
    int SCIPgetNLPBranchCands(SCIP *scip)
    Definition: scip_branch.c:436
    SCIP_Bool SCIPisExact(SCIP *scip)
    Definition: scip_exact.c:193
    SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
    Definition: scip_heur.c:167
    SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
    Definition: heur.c:1368
    SCIP_RETCODE SCIPincludeHeurBasic(SCIP *scip, SCIP_HEUR **heur, const char *name, const char *desc, char dispchar, int priority, int freq, int freqofs, int maxdepth, SCIP_HEURTIMING timingmask, SCIP_Bool usessubscip, SCIP_DECL_HEUREXEC((*heurexec)), SCIP_HEURDATA *heurdata)
    Definition: scip_heur.c:122
    SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
    Definition: scip_heur.c:183
    SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
    Definition: scip_heur.c:215
    SCIP_Longint SCIPheurGetNBestSolsFound(SCIP_HEUR *heur)
    Definition: heur.c:1613
    SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
    Definition: heur.c:1593
    void SCIPheurMarkExact(SCIP_HEUR *heur)
    Definition: heur.c:1457
    SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
    Definition: scip_heur.c:199
    const char * SCIPheurGetName(SCIP_HEUR *heur)
    Definition: heur.c:1467
    void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
    Definition: heur.c:1378
    SCIP_RETCODE SCIPchgVarLbDive(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
    Definition: scip_lp.c:2384
    SCIP_RETCODE SCIPchgVarUbDive(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
    Definition: scip_lp.c:2416
    SCIP_Real SCIPgetVarLbDive(SCIP *scip, SCIP_VAR *var)
    Definition: scip_lp.c:2581
    SCIP_Real SCIPgetVarUbDive(SCIP *scip, SCIP_VAR *var)
    Definition: scip_lp.c:2610
    SCIP_Real SCIPgetVarObjDive(SCIP *scip, SCIP_VAR *var)
    Definition: scip_lp.c:2552
    SCIP_RETCODE SCIPstartDive(SCIP *scip)
    Definition: scip_lp.c:2206
    SCIP_RETCODE SCIPchgVarObjDive(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
    Definition: scip_lp.c:2343
    SCIP_RETCODE SCIPsolveDiveLP(SCIP *scip, int itlim, SCIP_Bool *lperror, SCIP_Bool *cutoff)
    Definition: scip_lp.c:2643
    SCIP_RETCODE SCIPendDive(SCIP *scip)
    Definition: scip_lp.c:2255
    SCIP_Bool SCIPinDive(SCIP *scip)
    Definition: scip_lp.c:2740
    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 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_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
    SCIP_RETCODE SCIPunlinkSol(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1506
    SCIP_RETCODE SCIProundSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool *success)
    Definition: scip_sol.c:3123
    SCIP_RETCODE SCIPtrySol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
    Definition: scip_sol.c:4012
    SCIP_RETCODE SCIPlinkLPSol(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1295
    SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1892
    SCIP_Longint SCIPgetNSolsFound(SCIP *scip)
    int SCIPgetMaxDepth(SCIP *scip)
    SCIP_Longint SCIPgetNNodes(SCIP *scip)
    SCIP_Real SCIPgetDualbound(SCIP *scip)
    SCIP_Longint SCIPgetNNodeLPIterations(SCIP *scip)
    SCIP_Real SCIPgetCutoffbound(SCIP *scip)
    SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
    SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
    int SCIPgetDepth(SCIP *scip)
    Definition: scip_tree.c:672
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
    Definition: var.c:19115
    SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
    Definition: var.c:24664
    static SCIP_DECL_HEURCOPY(heurCopyRootsoldiving)
    #define DEFAULT_DEPTHFAC
    #define HEUR_TIMING
    static SCIP_DECL_HEURFREE(heurFreeRootsoldiving)
    #define DEFAULT_MAXLPITERQUOT
    #define HEUR_FREQOFS
    #define HEUR_DESC
    #define MINLPITER
    static SCIP_DECL_HEUREXIT(heurExitRootsoldiving)
    #define HEUR_DISPCHAR
    #define HEUR_MAXDEPTH
    #define HEUR_PRIORITY
    #define DEFAULT_MAXRELDEPTH
    #define DEFAULT_MAXLPITEROFS
    #define HEUR_NAME
    #define DEFAULT_DEPTHFACNOSOL
    static SCIP_DECL_HEUREXEC(heurExecRootsoldiving)
    #define DEFAULT_ALPHA
    #define HEUR_FREQ
    #define DEFAULT_MINRELDEPTH
    #define DEFAULT_MAXSOLS
    #define HEUR_USESSUBSCIP
    static SCIP_DECL_HEURINIT(heurInitRootsoldiving)
    LP diving heuristic that changes variables' objective values using root LP solution as guide.
    memory allocation routines
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    public methods for primal heuristics
    public methods for message output
    public methods for problem variables
    public methods for branching rule plugins and branching
    public methods for exact solving
    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 numerical tolerances
    public methods for SCIP parameter handling
    public methods for global and local (sub)problems
    public methods for solutions
    public methods for querying solving statistics
    public methods for the branch-and-bound tree
    struct SCIP_HeurData SCIP_HEURDATA
    Definition: type_heur.h:77
    enum SCIP_LPSolStat SCIP_LPSOLSTAT
    Definition: type_lp.h:52
    @ SCIP_LPSOLSTAT_OPTIMAL
    Definition: type_lp.h:44
    @ SCIP_LPSOLSTAT_UNBOUNDEDRAY
    Definition: type_lp.h:46
    @ SCIP_LPSOLSTAT_INFEASIBLE
    Definition: type_lp.h:45
    @ 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
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63