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-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_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
    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
    111
    112 /* call inclusion method of primal heuristic */
    114
    115 return SCIP_OKAY;
    116}
    117
    118/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
    119static
    120SCIP_DECL_HEURFREE(heurFreeRootsoldiving) /*lint --e{715}*/
    121{ /*lint --e{715}*/
    122 SCIP_HEURDATA* heurdata;
    123
    124 assert(heur != NULL);
    125 assert(scip != NULL);
    126
    128
    129 /* free heuristic data */
    130 heurdata = SCIPheurGetData(heur);
    131 assert(heurdata != NULL);
    132 SCIPfreeBlockMemory(scip, &heurdata);
    133 SCIPheurSetData(heur, NULL);
    134
    135 return SCIP_OKAY;
    136}
    137
    138
    139/** initialization method of primal heuristic (called after problem was transformed) */
    140static
    141SCIP_DECL_HEURINIT(heurInitRootsoldiving) /*lint --e{715}*/
    142{ /*lint --e{715}*/
    143 SCIP_HEURDATA* heurdata;
    144
    145 assert(heur != NULL);
    146
    148
    149 /* get heuristic data */
    150 heurdata = SCIPheurGetData(heur);
    151 assert(heurdata != NULL);
    152
    153 /* create working solution */
    154 SCIP_CALL( SCIPcreateSol(scip, &heurdata->sol, heur) );
    155
    156 /* initialize data */
    157 heurdata->nlpiterations = 0;
    158 heurdata->nsuccess = 0;
    159
    160 return SCIP_OKAY;
    161}
    162
    163
    164/** deinitialization method of primal heuristic (called before transformed problem is freed) */
    165static
    166SCIP_DECL_HEUREXIT(heurExitRootsoldiving) /*lint --e{715}*/
    167{ /*lint --e{715}*/
    168 SCIP_HEURDATA* heurdata;
    169
    170 assert(heur != NULL);
    171
    173
    174 /* get heuristic data */
    175 heurdata = SCIPheurGetData(heur);
    176 assert(heurdata != NULL);
    177
    178 /* free working solution */
    179 SCIP_CALL( SCIPfreeSol(scip, &heurdata->sol) );
    180
    181 return SCIP_OKAY;
    182}
    183
    184
    185/** execution method of primal heuristic */
    186static
    187SCIP_DECL_HEUREXEC(heurExecRootsoldiving) /*lint --e{715}*/
    188{ /*lint --e{715}*/
    189 SCIP_HEURDATA* heurdata;
    190 SCIP_VAR** vars;
    191 SCIP_Real* rootsol;
    192 SCIP_Real* objchgvals;
    193 int* softroundings;
    194 int* intvalrounds;
    195 SCIP_LPSOLSTAT lpsolstat;
    196 SCIP_Real absstartobjval;
    197 SCIP_Real objstep;
    198 SCIP_Real alpha;
    199 SCIP_Real oldobj;
    200 SCIP_Real newobj;
    201 SCIP_Bool lperror;
    202 SCIP_Bool lpsolchanged;
    203 SCIP_Longint nsolsfound;
    204 SCIP_Longint ncalls;
    205 SCIP_Longint nlpiterations;
    206 SCIP_Longint maxnlpiterations;
    207 int nvars;
    208 int nenfovars;
    209 int nlpcands;
    210 int depth;
    211 int maxdepth;
    212 int maxdivedepth;
    213 int divedepth;
    214 int startnlpcands;
    215 int ncycles;
    216 int i;
    217
    218 assert(heur != NULL);
    219 assert(scip != NULL);
    220 assert(result != NULL);
    221 assert(SCIPhasCurrentNodeLP(scip));
    222
    224
    225 *result = SCIP_DELAYED;
    226
    227 /* do not call heuristic of node was already detected to be infeasible */
    228 if( nodeinfeasible )
    229 return SCIP_OKAY;
    230
    231 /* only call heuristic, if an optimal LP solution is at hand */
    233 return SCIP_OKAY;
    234
    235 /* only call heuristic, if the LP objective value is smaller than the cutoff bound */
    237 return SCIP_OKAY;
    238
    239 /* only call heuristic, if the LP solution is basic (which allows fast resolve in diving) */
    240 if( !SCIPisLPSolBasic(scip) )
    241 return SCIP_OKAY;
    242
    243 /* don't dive two times at the same node */
    245 return SCIP_OKAY;
    246
    247 *result = SCIP_DIDNOTRUN;
    248
    249 /* get heuristic's data */
    250 heurdata = SCIPheurGetData(heur);
    251 assert(heurdata != NULL);
    252
    253 /* only apply heuristic, if only a few solutions have been found */
    254 if( heurdata->maxsols >= 0 && SCIPgetNSolsFound(scip) >= heurdata->maxsols )
    255 return SCIP_OKAY;
    256
    257 /* only try to dive, if we are in the correct part of the tree, given by minreldepth and maxreldepth */
    258 depth = SCIPgetDepth(scip);
    259 maxdepth = SCIPgetMaxDepth(scip);
    260 maxdepth = MAX(maxdepth, 30);
    261 if( depth < heurdata->minreldepth*maxdepth || depth > heurdata->maxreldepth*maxdepth )
    262 return SCIP_OKAY;
    263
    264 /* calculate the maximal number of LP iterations until heuristic is aborted */
    265 nlpiterations = SCIPgetNNodeLPIterations(scip);
    266 ncalls = SCIPheurGetNCalls(heur);
    267 nsolsfound = 10*SCIPheurGetNBestSolsFound(heur) + heurdata->nsuccess;
    268 maxnlpiterations = (SCIP_Longint)(((nsolsfound+1.0)/(ncalls+1.0)) * heurdata->maxlpiterquot * nlpiterations);
    269 maxnlpiterations += heurdata->maxlpiterofs;
    270
    271 /* don't try to dive, if we took too many LP iterations during diving */
    272 if( heurdata->nlpiterations >= maxnlpiterations )
    273 return SCIP_OKAY;
    274
    275 /* allow at least a certain number of LP iterations in this dive */
    276 maxnlpiterations = MAX(maxnlpiterations, heurdata->nlpiterations + MINLPITER);
    277
    278 /* get number of fractional variables, that should be integral */
    279 nlpcands = SCIPgetNLPBranchCands(scip);
    280
    281 /* don't try to dive, if there are no fractional variables */
    282 if( nlpcands == 0 )
    283 return SCIP_OKAY;
    284
    285 /* get all variables of LP */
    286 vars = SCIPgetVars(scip);
    287 nvars = SCIPgetNVars(scip);
    288 nenfovars = nvars - SCIPgetNContVars(scip) - SCIPgetNContImplVars(scip);
    289 assert(nenfovars >= 0);
    290
    291 /* calculate the maximal diving depth */
    292 if( SCIPgetNSolsFound(scip) == 0 )
    293 maxdivedepth = (int)(heurdata->depthfacnosol * nenfovars);
    294 else
    295 maxdivedepth = (int)(heurdata->depthfac * nenfovars);
    296 maxdivedepth = MAX(maxdivedepth, 10);
    297
    298 *result = SCIP_DIDNOTFIND;
    299
    300 /* get root solution value of all binary and integer variables */
    301 SCIP_CALL( SCIPallocBufferArray(scip, &rootsol, nenfovars) );
    302 for( i = 0; i < nenfovars; i++ )
    303 rootsol[i] = SCIPvarGetRootSol(vars[i]);
    304
    305 /* get current LP objective value, and calculate length of a single step in an objective coefficient */
    306 absstartobjval = SCIPgetLPObjval(scip);
    307 absstartobjval = ABS(absstartobjval);
    308 absstartobjval = MAX(absstartobjval, 1.0);
    309 objstep = absstartobjval / 10.0;
    310
    311 /* initialize array storing the preferred soft rounding directions and counting the integral value rounds */
    312 SCIP_CALL( SCIPallocBufferArray(scip, &softroundings, nenfovars) );
    313 BMSclearMemoryArray(softroundings, nenfovars);
    314 SCIP_CALL( SCIPallocBufferArray(scip, &intvalrounds, nenfovars) );
    315 BMSclearMemoryArray(intvalrounds, nenfovars);
    316
    317 /* allocate temporary memory for buffering objective changes */
    318 SCIP_CALL( SCIPallocBufferArray(scip, &objchgvals, nenfovars) );
    319
    320 /* start diving */
    322
    323 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",
    324 SCIPgetNNodes(scip), SCIPgetDepth(scip), nlpcands, SCIPgetDualbound(scip), maxnlpiterations, maxdivedepth,
    325 SCIPgetLPObjval(scip), objstep);
    326
    327 lperror = FALSE;
    328 divedepth = 0;
    329 lpsolstat = SCIP_LPSOLSTAT_OPTIMAL;
    330 alpha = heurdata->alpha;
    331 ncycles = 0;
    332 lpsolchanged = TRUE;
    333 startnlpcands = nlpcands;
    334 while( !lperror && lpsolstat == SCIP_LPSOLSTAT_OPTIMAL && nlpcands > 0 && ncycles < 10
    335 && (divedepth < 10
    336 || nlpcands <= startnlpcands - divedepth/2
    337 || (divedepth < maxdivedepth && heurdata->nlpiterations < maxnlpiterations))
    338 && !SCIPisStopped(scip) )
    339 {
    340 SCIP_Bool success;
    341 int hardroundingidx;
    342 int hardroundingdir;
    343 SCIP_Real hardroundingoldbd;
    344 SCIP_Real hardroundingnewbd;
    345 SCIP_Bool boundschanged;
    346
    347 SCIP_RETCODE retcode;
    348
    349 /* create solution from diving LP and try to round it */
    350 SCIP_CALL( SCIPlinkLPSol(scip, heurdata->sol) );
    351 SCIP_CALL( SCIProundSol(scip, heurdata->sol, &success) );
    352
    353 if( success && !SCIPisExact(scip) )
    354 {
    355 SCIPdebugMsg(scip, "rootsoldiving found roundable primal solution: obj=%g\n", SCIPgetSolOrigObj(scip, heurdata->sol));
    356
    357 /* try to add solution to SCIP */
    358 SCIP_CALL( SCIPtrySol(scip, heurdata->sol, FALSE, FALSE, FALSE, FALSE, FALSE, &success) );
    359
    360 /* check, if solution was feasible and good enough */
    361 if( success )
    362 {
    363 SCIPdebugMsg(scip, " -> solution was feasible and good enough\n");
    364 *result = SCIP_FOUNDSOL;
    365 }
    366 }
    367
    368 divedepth++;
    369 hardroundingidx = -1;
    370 hardroundingdir = 0;
    371 hardroundingoldbd = 0.0;
    372 hardroundingnewbd = 0.0;
    373 boundschanged = FALSE;
    374
    375 SCIPdebugMsg(scip, "dive %d/%d, LP iter %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ":\n", divedepth, maxdivedepth, heurdata->nlpiterations, maxnlpiterations);
    376
    377 /* round solution x* from diving LP:
    378 * - x~_j = down(x*_j) if x*_j is integer or binary variable and x*_j <= root solution_j
    379 * - x~_j = up(x*_j) if x*_j is integer or binary variable and x*_j > root solution_j
    380 * - x~_j = x*_j if x*_j is continuous variable
    381 * change objective function in diving LP:
    382 * - if x*_j is integral, or j is a continuous variable, set obj'_j = alpha * obj_j
    383 * - otherwise, set obj'_j = alpha * obj_j + sign(x*_j - x~_j)
    384 */
    385 for( i = 0; i < nenfovars; i++ )
    386 {
    387 SCIP_VAR* var;
    388 SCIP_Real solval;
    389
    390 var = vars[i];
    391 oldobj = SCIPgetVarObjDive(scip, var);
    392 newobj = oldobj;
    393
    394 solval = SCIPvarGetLPSol(var);
    395 if( SCIPisFeasIntegral(scip, solval) )
    396 {
    397 /* if the variable became integral after a soft rounding, count the rounds; after a while, fix it to its
    398 * current integral value;
    399 * otherwise, fade out the objective value
    400 */
    401 if( softroundings[i] != 0 && lpsolchanged )
    402 {
    403 intvalrounds[i]++;
    404 if( intvalrounds[i] == 5 && SCIPgetVarLbDive(scip, var) < SCIPgetVarUbDive(scip, var) - 0.5 )
    405 {
    406 /* use exact integral value, if the variable is only integral within numerical tolerances */
    407 solval = SCIPfloor(scip, solval+0.5);
    408 SCIPdebugMsg(scip, " -> fixing <%s> = %g\n", SCIPvarGetName(var), solval);
    409 SCIP_CALL( SCIPchgVarLbDive(scip, var, solval) );
    410 SCIP_CALL( SCIPchgVarUbDive(scip, var, solval) );
    411 boundschanged = TRUE;
    412 }
    413 }
    414 else
    415 newobj = alpha * oldobj;
    416 }
    417 else if( solval <= rootsol[i] )
    418 {
    419 /* if the variable was soft rounded most of the time downwards, round it downwards by changing the bounds;
    420 * otherwise, apply soft rounding by changing the objective value
    421 */
    422 softroundings[i]--;
    423 if( softroundings[i] <= -10 && hardroundingidx == -1 )
    424 {
    425 SCIPdebugMsg(scip, " -> hard rounding <%s>[%g] <= %g\n",
    426 SCIPvarGetName(var), solval, SCIPfeasFloor(scip, solval));
    427 hardroundingidx = i;
    428 hardroundingdir = -1;
    429 hardroundingoldbd = SCIPgetVarUbDive(scip, var);
    430 hardroundingnewbd = SCIPfeasFloor(scip, solval);
    431 SCIP_CALL( SCIPchgVarUbDive(scip, var, hardroundingnewbd) );
    432 boundschanged = TRUE;
    433 }
    434 else
    435 newobj = alpha * oldobj + objstep;
    436 }
    437 else
    438 {
    439 /* if the variable was soft rounded most of the time upwards, round it upwards by changing the bounds;
    440 * otherwise, apply soft rounding by changing the objective value
    441 */
    442 softroundings[i]++;
    443 if( softroundings[i] >= +10 && hardroundingidx == -1 )
    444 {
    445 SCIPdebugMsg(scip, " -> hard rounding <%s>[%g] >= %g\n",
    446 SCIPvarGetName(var), solval, SCIPfeasCeil(scip, solval));
    447 hardroundingidx = i;
    448 hardroundingdir = +1;
    449 hardroundingoldbd = SCIPgetVarLbDive(scip, var);
    450 hardroundingnewbd = SCIPfeasCeil(scip, solval);
    451 SCIP_CALL( SCIPchgVarLbDive(scip, var, hardroundingnewbd) );
    452 boundschanged = TRUE;
    453 }
    454 else
    455 newobj = alpha * oldobj - objstep;
    456 }
    457
    458 /* remember the objective change */
    459 objchgvals[i] = newobj;
    460 }
    461
    462 /* apply objective changes if there was no bound change */
    463 if( !boundschanged )
    464 {
    465 /* apply cached changes on integer variables */
    466 for( i = 0; i < nenfovars; ++i )
    467 {
    468 SCIP_VAR* var;
    469
    470 var = vars[i];
    471 SCIPdebugMsg(scip, " -> i=%d var <%s>, solval=%g, rootsol=%g, oldobj=%g, newobj=%g\n",
    472 i, SCIPvarGetName(var), SCIPvarGetLPSol(var), rootsol[i], SCIPgetVarObjDive(scip, var), objchgvals[i]);
    473
    474 SCIP_CALL( SCIPchgVarObjDive(scip, var, objchgvals[i]) );
    475 }
    476
    477 /* fade out the objective values of the continuous variables */
    478 for( i = nenfovars; i < nvars; i++ )
    479 {
    480 SCIP_VAR* var;
    481
    482 var = vars[i];
    483 oldobj = SCIPgetVarObjDive(scip, var);
    484 newobj = alpha * oldobj;
    485
    486 SCIPdebugMsg(scip, " -> i=%d var <%s>, solval=%g, oldobj=%g, newobj=%g\n",
    487 i, SCIPvarGetName(var), SCIPvarGetLPSol(var), oldobj, newobj);
    488
    489 SCIP_CALL( SCIPchgVarObjDive(scip, var, newobj) );
    490 }
    491 }
    492
    493 SOLVEAGAIN:
    494 /* resolve the diving LP */
    495 nlpiterations = SCIPgetNLPIterations(scip);
    496
    497 retcode = SCIPsolveDiveLP(scip, MAX((int)(maxnlpiterations - heurdata->nlpiterations), MINLPITER), &lperror, NULL);
    498 lpsolstat = SCIPgetLPSolstat(scip);
    499
    500 /* Errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
    501 * Hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
    502 */
    503 if( retcode != SCIP_OKAY )
    504 {
    505#ifndef NDEBUG
    506 if( lpsolstat != SCIP_LPSOLSTAT_UNBOUNDEDRAY )
    507 {
    508 SCIP_CALL( retcode );
    509 }
    510#endif
    511 SCIPwarningMessage(scip, "Error while solving LP in Rootsoldiving heuristic; LP solve terminated with code <%d>\n", retcode);
    512 SCIPwarningMessage(scip, "This does not affect the remaining solution procedure --> continue\n");
    513 }
    514
    515 if( lperror )
    516 break;
    517
    518 /* update iteration count */
    519 heurdata->nlpiterations += SCIPgetNLPIterations(scip) - nlpiterations;
    520
    521 /* if no LP iterations were performed, we stayed at the same solution -> count this cycling */
    522 lpsolchanged = (SCIPgetNLPIterations(scip) != nlpiterations);
    523 if( lpsolchanged )
    524 ncycles = 0;
    525 else if( !boundschanged ) /* do not count if integral variables have been fixed */
    526 ncycles++;
    527
    528 /* get LP solution status and number of fractional variables, that should be integral */
    529 if( lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE && hardroundingidx != -1 )
    530 {
    531 SCIP_VAR* var;
    532
    533 var = vars[hardroundingidx];
    534
    535 /* round the hard rounded variable to the opposite direction and resolve the LP */
    536 if( hardroundingdir == -1 )
    537 {
    538 SCIPdebugMsg(scip, " -> opposite hard rounding <%s> >= %g\n", SCIPvarGetName(var), hardroundingnewbd + 1.0);
    539 SCIP_CALL( SCIPchgVarUbDive(scip, var, hardroundingoldbd) );
    540 SCIP_CALL( SCIPchgVarLbDive(scip, var, hardroundingnewbd + 1.0) );
    541 }
    542 else
    543 {
    544 SCIPdebugMsg(scip, " -> opposite hard rounding <%s> <= %g\n", SCIPvarGetName(var), hardroundingnewbd - 1.0);
    545 SCIP_CALL( SCIPchgVarLbDive(scip, var, hardroundingoldbd) );
    546 SCIP_CALL( SCIPchgVarUbDive(scip, var, hardroundingnewbd - 1.0) );
    547 }
    548 hardroundingidx = -1;
    549 goto SOLVEAGAIN;
    550 }
    551 if( lpsolstat == SCIP_LPSOLSTAT_OPTIMAL )
    552 nlpcands = SCIPgetNLPBranchCands(scip);
    553 SCIPdebugMsg(scip, " -> lpsolstat=%d, nfrac=%d\n", lpsolstat, nlpcands);
    554 }
    555
    556 SCIPdebugMsg(scip, "---> diving finished: lpsolstat = %d, depth %d/%d, LP iter %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT "\n",
    557 lpsolstat, divedepth, maxdivedepth, heurdata->nlpiterations, maxnlpiterations);
    558
    559 /* check if a solution has been found */
    560 if( nlpcands == 0 && !lperror && lpsolstat == SCIP_LPSOLSTAT_OPTIMAL )
    561 {
    562 SCIP_Bool success;
    563
    564 /* create solution from diving LP */
    565 SCIP_CALL( SCIPlinkLPSol(scip, heurdata->sol) );
    566 SCIPdebugMsg(scip, "rootsoldiving found primal solution: obj=%g\n", SCIPgetSolOrigObj(scip, heurdata->sol));
    567
    568 /* in exact mode we have to end diving prior to trying the solution */
    569 if( SCIPisExact(scip) )
    570 {
    571 SCIP_CALL( SCIPunlinkSol(scip, heurdata->sol) );
    573 }
    574
    575 /* try to add solution to SCIP */
    576 SCIP_CALL( SCIPtrySol(scip, heurdata->sol, FALSE, FALSE, FALSE, FALSE, FALSE, &success) );
    577
    578 /* check, if solution was feasible and good enough */
    579 if( success )
    580 {
    581 SCIPdebugMsg(scip, " -> solution was feasible and good enough\n");
    582 *result = SCIP_FOUNDSOL;
    583 }
    584 }
    585
    586 /* end diving */
    587 if( SCIPinDive(scip) )
    588 {
    590 }
    591
    592 if( *result == SCIP_FOUNDSOL )
    593 heurdata->nsuccess++;
    594
    595 /* free temporary memory */
    596 SCIPfreeBufferArray(scip, &objchgvals);
    597 SCIPfreeBufferArray(scip, &intvalrounds);
    598 SCIPfreeBufferArray(scip, &softroundings);
    599 SCIPfreeBufferArray(scip, &rootsol);
    600
    601 SCIPdebugMsg(scip, "rootsoldiving heuristic finished\n");
    602
    603 return SCIP_OKAY;
    604}
    605
    606
    607/*
    608 * heuristic specific interface methods
    609 */
    610
    611/** creates the rootsoldiving heuristic and includes it in SCIP */
    613 SCIP* scip /**< SCIP data structure */
    614 )
    615{
    616 SCIP_HEURDATA* heurdata;
    617 SCIP_HEUR* heur;
    618
    619 /* create Rootsoldiving primal heuristic data */
    620 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    621
    622 /* include primal heuristic */
    625 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecRootsoldiving, heurdata) );
    626
    627 assert(heur != NULL);
    628
    629 /* primal heuristic is safe to use in exact solving mode */
    630 SCIPheurMarkExact(heur);
    631
    632 /* set non-NULL pointers to callback methods */
    633 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyRootsoldiving) );
    634 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeRootsoldiving) );
    635 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitRootsoldiving) );
    636 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitRootsoldiving) );
    637
    638 /* rootsoldiving heuristic parameters */
    640 "heuristics/rootsoldiving/minreldepth",
    641 "minimal relative depth to start diving",
    642 &heurdata->minreldepth, TRUE, DEFAULT_MINRELDEPTH, 0.0, 1.0, NULL, NULL) );
    644 "heuristics/rootsoldiving/maxreldepth",
    645 "maximal relative depth to start diving",
    646 &heurdata->maxreldepth, TRUE, DEFAULT_MAXRELDEPTH, 0.0, 1.0, NULL, NULL) );
    648 "heuristics/rootsoldiving/maxlpiterquot",
    649 "maximal fraction of diving LP iterations compared to node LP iterations",
    650 &heurdata->maxlpiterquot, FALSE, DEFAULT_MAXLPITERQUOT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
    652 "heuristics/rootsoldiving/maxlpiterofs",
    653 "additional number of allowed LP iterations",
    654 &heurdata->maxlpiterofs, FALSE, DEFAULT_MAXLPITEROFS, 0, INT_MAX, NULL, NULL) );
    656 "heuristics/rootsoldiving/maxsols",
    657 "total number of feasible solutions found up to which heuristic is called (-1: no limit)",
    658 &heurdata->maxsols, TRUE, DEFAULT_MAXSOLS, -1, INT_MAX, NULL, NULL) );
    660 "heuristics/rootsoldiving/depthfac",
    661 "maximal diving depth: number of binary/integer variables times depthfac",
    662 &heurdata->depthfac, TRUE, DEFAULT_DEPTHFAC, 0.0, SCIP_REAL_MAX, NULL, NULL) );
    664 "heuristics/rootsoldiving/depthfacnosol",
    665 "maximal diving depth factor if no feasible solution was found yet",
    666 &heurdata->depthfacnosol, TRUE, DEFAULT_DEPTHFACNOSOL, 0.0, SCIP_REAL_MAX, NULL, NULL) );
    668 "heuristics/rootsoldiving/alpha",
    669 "soft rounding factor to fade out objective coefficients",
    670 &heurdata->alpha, TRUE, DEFAULT_ALPHA, 0.0, 1.0, NULL, NULL) );
    671
    672 return SCIP_OKAY;
    673}
    674
    #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 SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define ABS(x)
    Definition: def.h:225
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define MAX(x, y)
    Definition: def.h:229
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:157
    #define SCIP_CALL(x)
    Definition: def.h:364
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:767
    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:514
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1250
    SCIP_RETCODE SCIPunlinkSol(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1504
    SCIP_RETCODE SCIProundSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool *success)
    Definition: scip_sol.c:3128
    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:4017
    SCIP_RETCODE SCIPlinkLPSol(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1293
    SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1890
    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:23299
    SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
    Definition: var.c:19144
    SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
    Definition: var.c:24696
    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
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63