SCIP

    Solving Constraint Integer Programs

    heur_lpface.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_lpface.c
    26 * @ingroup DEFPLUGINS_HEUR
    27 * @brief lpface primal heuristic that searches the optimal LP face inside a sub-MIP
    28 * @author Gregor Hendel
    29 */
    30
    31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    32
    34#include "scip/cons_linear.h"
    35#include "scip/scipdefplugins.h"
    36#include "scip/heur_lpface.h"
    37#include "scip/pub_event.h"
    38#include "scip/pub_heur.h"
    39#include "scip/pub_lp.h"
    40#include "scip/pub_message.h"
    41#include "scip/pub_misc.h"
    42#include "scip/pub_sol.h"
    43#include "scip/pub_tree.h"
    44#include "scip/pub_var.h"
    45#include "scip/scip_branch.h"
    46#include "scip/scip_cons.h"
    47#include "scip/scip_copy.h"
    48#include "scip/scip_event.h"
    49#include "scip/scip_exact.h"
    50#include "scip/scip_general.h"
    51#include "scip/scip_heur.h"
    52#include "scip/scip_lp.h"
    53#include "scip/scip_mem.h"
    54#include "scip/scip_message.h"
    55#include "scip/scip_nodesel.h"
    56#include "scip/scip_numerics.h"
    57#include "scip/scip_param.h"
    58#include "scip/scip_prob.h"
    59#include "scip/scip_sol.h"
    60#include "scip/scip_solve.h"
    62#include "scip/scip_timing.h"
    63#include "scip/scip_tree.h"
    64#include "scip/scip_var.h"
    65
    66
    67#define HEUR_NAME "lpface"
    68#define HEUR_DESC "LNS heuristic that searches the optimal LP face inside a sub-MIP"
    69#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_LNS
    70#define HEUR_PRIORITY -1104010
    71#define HEUR_FREQ 15
    72#define HEUR_FREQOFS 0
    73#define HEUR_MAXDEPTH -1
    74#define HEUR_TIMING SCIP_HEURTIMING_AFTERLPNODE
    75#define HEUR_USESSUBSCIP TRUE /**< does the heuristic use a secondary SCIP instance? */
    76
    77#define DEFAULT_MAXNODES 5000LL /**< maximum number of nodes to regard in the subproblem */
    78#define DEFAULT_MINNODES 50LL /**< minimum number of nodes to regard in the subproblem */
    79#define DEFAULT_MINFIXINGRATE 0.1 /**< required percentage of fixed integer variables in sub-MIP to run */
    80#define DEFAULT_NODESOFS 200LL /**< number of nodes added to the contingent of the total nodes */
    81#define DEFAULT_NODESQUOT 0.1 /**< subproblem nodes in relation to nodes of the original problem */
    82#define DEFAULT_LPLIMFAC 2.0 /**< factor by which the limit on the number of LP depends on the node limit */
    83#define DEFAULT_USELPROWS TRUE /**< should subproblem be created out of the rows in the LP rows,
    84 * otherwise, the copy constructors of the constraints handlers are used */
    85#define DEFAULT_COPYCUTS TRUE /**< if uselprows == FALSE, should all active cuts from cutpool be copied
    86 * to constraints in subproblem? */
    87#define DEFAULT_DUALBASISEQUATIONS FALSE /**< should the dually nonbasic rows be turned into equations? */
    88#define DEFAULT_KEEPSUBSCIP FALSE /**< should the heuristic continue solving the same sub-SCIP? */
    89#define DEFAULT_MINPATHLEN 5 /**< the minimum active search tree path length along which the lower bound
    90 * hasn't changed before heuristic becomes active */
    91/* event handler properties */
    92#define EVENTHDLR_NAME "Lpface"
    93#define EVENTHDLR_DESC "LP event handler for " HEUR_NAME " heuristic"
    94
    95/*
    96 * Data structures
    97 */
    98
    99/** data structure to keep sub-SCIP across runs */
    101{
    102 SCIP* subscip; /**< pointer to store sub-SCIP data structure */
    103 SCIP_VAR** subvars; /**< array of variables of the sub-problem */
    104 int nsubvars; /**< number of sub-problem variables */
    105 SCIP_Real objbound; /**< lower bound on objective for when sub SCIP was created */
    106};
    108
    109/** primal heuristic data */
    110struct SCIP_HeurData
    111{
    112 SCIP_Longint maxnodes; /**< maximum number of nodes to regard in the subproblem */
    113 SCIP_Longint minnodes; /**< minimum number of nodes to regard in the subproblem */
    114 SCIP_Longint nodesofs; /**< number of nodes added to the contingent of the total nodes */
    115 SCIP_Longint usednodes; /**< nodes already used by lpface in earlier calls */
    116 SCIP_Real nodesquot; /**< subproblem nodes in relation to nodes of the original problem */
    117
    118 unsigned int nfailures; /**< number of failures since last successful call */
    119 SCIP_Longint nextnodenumber; /**< number of nodes at which lpface should be called the next time */
    120 SCIP_Real lastlpobjinfeas; /**< last LP objective where the sub-MIP was run to proven infeasibility */
    121 SCIP_Real minfixingrate; /**< required percentage of fixed integer variables in sub-MIP to run */
    122 SCIP_Real nodelimit; /**< the nodelimit employed in the current sub-SCIP, for the event handler*/
    123 SCIP_Real lplimfac; /**< factor by which the limit on the number of LP depends on the node limit */
    124 SCIP_Bool uselprows; /**< should subproblem be created out of the rows in the LP rows? */
    125 SCIP_Bool copycuts; /**< if uselprows == FALSE, should all active cuts from cutpool be copied
    126 * to constraints in subproblem? */
    127 SCIP_Bool dualbasisequations; /**< should the dually nonbasic rows be turned into equations? */
    128 SCIP_Bool keepsubscip; /**< should the heuristic continue solving the same sub-SCIP? */
    129 char subscipobjective; /**< objective function in the sub-SCIP: (z)ero, (r)oot-LP-difference,
    130 * (i)nference, LP (f)ractionality, (o)riginal */
    131
    132 SCIP_STATUS submipstatus; /**< return status of the sub-MIP */
    133 SCIP_Longint submipnlpiters; /**< number of LP iterations of the sub-MIP */
    134 SCIP_Real submippresoltime; /**< time required to presolve the sub-MIP */
    135 int nvarsfixed; /**< the number of fixed variables by the heuristic */
    136 int minpathlen; /**< the minimum active search tree path length along which the lower bound
    137 * hasn't changed before heuristic becomes active */
    138 SUBSCIPDATA* subscipdata; /**< sub-SCIP data structure */
    139};
    140
    141/*
    142 * Local methods
    143 */
    144
    145/** determine variable fixings for sub-SCIP based on reduced costs */
    146static
    148 SCIP* scip, /**< SCIP data structure */
    149 SCIP_HEURDATA* heurdata, /**< primal heuristic data */
    150 SCIP_VAR** fixvars, /**< buffer to store variables that should be fixed */
    151 SCIP_Real* fixvals, /**< buffer to store corresponding fixing values */
    152 int* nfixvars, /**< pointer to store number of variables that should be fixed */
    153 SCIP_Bool* success /**< pointer to store whether enough integer variables were fixed */
    154 )
    155{
    156 SCIP_VAR** vars; /* original scip variables */
    157 SCIP_Real fixingrate; /* percentage of variables that are fixed */
    158 int nvars;
    159 int nbinvars;
    160 int nintvars;
    161 int i;
    162 int fixingcounter;
    163
    164 /* get required data of the main scip problem */
    165 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
    166
    167 fixingcounter = 0;
    168
    169 assert(nvars >= nbinvars + nintvars);
    170
    171 *nfixvars = 0;
    172 /* loop over problem variables and fix all with nonzero reduced costs to their solution value */
    173 for( i = 0; i < nvars; i++ )
    174 {
    175 SCIP_Real solval;
    176 SCIP_COL* col;
    177 SCIP_Real redcost;
    178 SCIP_Real lbglobal;
    179 SCIP_Real ubglobal;
    180 SCIP_VAR* var;
    181
    182 var = vars[i];
    183
    184 /* skip non-column variables */
    186 continue;
    187
    188 /* skip relaxation only variables */
    189 if( SCIPvarIsRelaxationOnly(var) )
    190 continue;
    191
    192 solval = SCIPgetSolVal(scip, NULL, var);
    193 col = SCIPvarGetCol(vars[i]);
    194 assert(col != NULL);
    195 redcost = SCIPgetColRedcost(scip, col);
    196 lbglobal = SCIPvarGetLbGlobal(var);
    197 ubglobal = SCIPvarGetUbGlobal(var);
    198
    199 /* fix the variable to its solution value if variable is nonbasic (i.e., at one of its bounds)
    200 * with nonzero reduced costs
    201 */
    202 if( ! SCIPisDualfeasZero(scip, redcost) )
    203 {
    204 /* fix variable based on reduced cost information, respecting global bounds */
    205 if( (redcost > 0 && SCIPisFeasEQ(scip, solval, lbglobal)) ||
    206 (redcost < 0 && SCIPisFeasEQ(scip, solval, ubglobal)) )
    207 {
    208 assert(! SCIPisInfinity(scip, REALABS(solval)));
    209
    210 fixvars[*nfixvars] = var;
    211 fixvals[*nfixvars] = solval;
    212
    213 if( SCIPvarIsIntegral(var) )
    214 ++fixingcounter;
    215
    216 ++(*nfixvars);
    217 }
    218 }
    219 }
    220
    221 fixingrate = (SCIP_Real)fixingcounter / (SCIP_Real)(MAX(nbinvars + nintvars, 1));
    222 heurdata->nvarsfixed = fixingcounter;
    223
    224 /* if all variables were fixed or amount of fixed variables is insufficient, skip residual part of
    225 * subproblem creation and abort immediately
    226 */
    227 *success = (fixingcounter < nvars && fixingrate >= heurdata->minfixingrate);
    228
    229 SCIPdebugMsg(scip, " LP face heuristic fixed %senough variables (%d out of %d)\n",
    230 *success ? "": "not ", fixingcounter, nvars);
    231
    232 return SCIP_OKAY;
    233}
    234
    235/** creates the rows of the subproblem */
    236static
    238 SCIP* scip, /**< original SCIP data structure */
    239 SCIP* subscip, /**< SCIP data structure for the subproblem */
    240 SCIP_VAR** subvars, /**< the variables of the subproblem */
    241 SCIP_Bool dualbasisequations /**< should the dually nonbasic rows be turned into equations? */
    242 )
    243{
    244 SCIP_ROW** rows; /* original scip rows */
    245
    246 int nrows;
    247 int i;
    248
    249 /* get the rows and their number */
    250 SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );
    251
    252 /* copy all global rows to linear constraints, unless they contain relaxation-only variables */
    253 for( i = 0; i < nrows; i++ )
    254 {
    255 SCIP_VAR** consvars; /* new constraint's variables */
    256 SCIP_COL** cols; /* original row's columns */
    257 SCIP_CONS* cons; /* new constraint */
    258
    259 SCIP_Real* vals; /* variables' coefficient values of the row */
    260 SCIP_Real constant; /* constant added to the row */
    261 SCIP_Real lhs; /* left hand side of the row */
    262 SCIP_Real rhs; /* left right side of the row */
    263 SCIP_Real dualsol;
    264 SCIP_Real rowsolactivity;
    265 int j;
    266 int nnonz;
    267
    268 /* ignore rows that are only locally valid */
    269 if( SCIProwIsLocal(rows[i]) )
    270 continue;
    271
    272 /* get the row's data */
    273 constant = SCIProwGetConstant(rows[i]);
    274 vals = SCIProwGetVals(rows[i]);
    275 nnonz = SCIProwGetNNonz(rows[i]);
    276 cols = SCIProwGetCols(rows[i]);
    277
    278 /* only subtract constant if left hand side is not infinite */
    279 lhs = SCIProwGetLhs(rows[i]);
    280 if( ! SCIPisInfinity(scip, -lhs) )
    281 lhs -= constant;
    282
    283 /* only subtract constant if right hand side is not infinite */
    284 rhs = SCIProwGetRhs(rows[i]);
    285 if( ! SCIPisInfinity(scip, rhs) )
    286 rhs -= constant;
    287
    288 assert(lhs <= rhs);
    289
    290 /* allocate memory array to be filled with the corresponding subproblem variables */
    291 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nnonz) );
    292 for( j = 0; j < nnonz; j++ )
    293 {
    294 consvars[j] = subvars[SCIPvarGetProbindex(SCIPcolGetVar(cols[j]))];
    295 if( consvars[j] == NULL )
    296 break;
    297 }
    298 /* skip row if not all variables are in sub-SCIP, i.e., relaxation-only variables */
    299 if( j < nnonz )
    300 {
    301 SCIPfreeBufferArray(scip, &consvars);
    302 continue;
    303 }
    304
    305 dualsol = SCIProwGetDualsol(rows[i]);
    306 rowsolactivity = SCIPgetRowActivity(scip, rows[i]);
    307
    308 /* transform into equation if the row is sharp and has a nonzero dual solution */
    309 if( dualbasisequations && ! SCIPisDualfeasZero(scip, dualsol) )
    310 {
    311 if( dualsol > 0.0 && SCIPisFeasEQ(scip, rowsolactivity, lhs) )
    312 rhs = lhs;
    313 else if( dualsol < 0.0 && SCIPisFeasEQ(scip, rowsolactivity, rhs) )
    314 lhs = rhs;
    315 }
    316
    317 /* create a new linear constraint and add it to the subproblem */
    318 SCIP_CALL( SCIPcreateConsLinear(subscip, &cons, SCIProwGetName(rows[i]), nnonz, consvars, vals, lhs, rhs,
    320 SCIP_CALL( SCIPaddCons(subscip, cons) );
    321 SCIP_CALL( SCIPreleaseCons(subscip, &cons) );
    322
    323 /* free temporary memory */
    324 SCIPfreeBufferArray(scip, &consvars);
    325 }
    326
    327 return SCIP_OKAY;
    328}
    329
    330/** create the LP face subproblem constraints */
    331static
    333 SCIP* scip, /**< original SCIP data structure */
    334 SCIP* subscip, /**< SCIP data structure for the subproblem */
    335 SCIP_VAR** subvars, /**< the variables of the subproblem */
    336 SCIP_HEURDATA* heurdata /**< primal heuristic data */
    337 )
    338{
    339 SCIP_VAR** vars = SCIPgetVars(scip);
    340 int nvars = SCIPgetNVars(scip);
    341 SCIP_Real lowerbound;
    342 SCIP_CONS* origobjcons;
    343 int i;
    344#ifndef NDEBUG
    345 int nobjvars = 0;
    346#endif
    347
    348 /* we copy the rows of the LP, if enough variables could be fixed and we work on the MIP relaxation of the problem */
    349 if( heurdata->uselprows )
    350 {
    351 SCIP_CALL( createRows(scip, subscip, subvars, heurdata->dualbasisequations) );
    352 }
    353
    354 /* add an equation that the objective function must be equal to the lower bound */
    355 lowerbound = SCIPgetLowerbound(scip);
    356
    357 SCIP_CALL( SCIPcreateConsLinear(subscip, &origobjcons, "objbound_of_origscip", 0, NULL, NULL, lowerbound, lowerbound,
    359
    360 for( i = 0; i < nvars; ++i)
    361 {
    362 if( ! SCIPisZero(subscip, SCIPvarGetObj(vars[i])) )
    363 {
    364 assert(subvars[i] != NULL); /* a relaxation-only variable cannot have an objective coefficient */
    365 SCIP_CALL( SCIPaddCoefLinear(subscip, origobjcons, subvars[i], SCIPvarGetObj(vars[i])) );
    366#ifndef NDEBUG
    367 nobjvars++;
    368#endif
    369 }
    370 }
    371 assert(nobjvars == SCIPgetNObjVars(scip));
    372
    373 SCIP_CALL( SCIPaddCons(subscip, origobjcons) );
    374 SCIP_CALL( SCIPreleaseCons(subscip, &origobjcons) );
    375
    376 return SCIP_OKAY;
    377}
    378
    379/** updates heurdata after an unsuccessful run of lpface */
    380static
    382 SCIP* scip, /**< original SCIP data structure */
    383 SCIP_HEURDATA* heurdata /**< primal heuristic data */
    384 )
    385{
    386 /* increase number of failures, calculate next node at which lpface should be called and update actual solutions */
    387 heurdata->nfailures++;
    388 heurdata->nextnodenumber = (heurdata->nfailures <= 25
    389 ? SCIPgetNNodes(scip) + 100*(2LL << heurdata->nfailures) /*lint !e703*/
    391}
    392
    393/** calculate a node limit based on node limiting parameters of the heuristic */
    394static
    396 SCIP* scip, /**< (original) SCIP data structure */
    397 SCIP_HEUR* heur, /**< LP face heuristic */
    398 SCIP_HEURDATA* heurdata /**< primal heuristic data */
    399 )
    400{
    401 SCIP_Longint nodelimit;
    402
    403 /* calculate the maximal number of branching nodes until heuristic is aborted */
    404 nodelimit = (SCIP_Longint)(heurdata->nodesquot * SCIPgetNNodes(scip));
    405
    406 /* count the setup costs for the sub-MIP as 100 nodes */
    407 nodelimit -= 100 * SCIPheurGetNCalls(heur);
    408
    409 /* add the offset */
    410 nodelimit += heurdata->nodesofs;
    411
    412 /* subtract previously used nodes */
    413 nodelimit -= heurdata->usednodes;
    414
    415 /* do not use more than the maximum number of allowed nodes in one run */
    416 nodelimit = MIN(nodelimit, heurdata->maxnodes);
    417
    418 /* if the subscip has been kept from a previous run, add the number of already processed nodes */
    419 if( heurdata->subscipdata->subscip != NULL )
    420 nodelimit += SCIPgetNNodes(heurdata->subscipdata->subscip);
    421
    422 return nodelimit;
    423}
    424
    425/** sets node, time, and memory limit according to the parameter settings of the heuristic */
    426static
    428 SCIP* scip, /**< original SCIP data structure */
    429 SCIP* subscip, /**< data structure of the sub-problem */
    430 SCIP_HEUR* heur, /**< LP face heuristic */
    431 SCIP_HEURDATA* heurdata, /**< heuristic data structure */
    432 SCIP_Bool* success /**< did we successfully set all parameters up? */
    433 )
    434{
    435 SCIP_Real timelimit;
    436 SCIP_Real memorylimit;
    437 SCIP_Longint nodelimit;
    438 SCIP_Bool avoidmemout;
    439
    440 *success = TRUE;
    441
    442 /* check whether there is enough time and memory left */
    443 SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
    444 SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memorylimit) );
    445 SCIP_CALL( SCIPgetBoolParam(scip, "misc/avoidmemout", &avoidmemout) );
    446
    447 if( ! SCIPisInfinity(scip, timelimit) )
    448 timelimit -= SCIPgetSolvingTime(scip);
    449
    450 /* substract the memory already used by the main SCIP and the estimated memory usage of external software */
    451 if( ! SCIPisInfinity(scip, memorylimit) )
    452 {
    453 memorylimit -= SCIPgetMemUsed(scip)/1048576.0;
    454 memorylimit -= SCIPgetMemExternEstim(scip)/1048576.0;
    455 }
    456
    457 /* abort if no time is left or not enough memory (we don't abort in this case if misc_avoidmemout == FALSE)
    458 * to create a copy of SCIP, including external memory usage */
    459 if( timelimit <= 0.0 || (avoidmemout && memorylimit <= 2.0 * SCIPgetMemExternEstim(scip) / 1048576.0) )
    460 {
    461 *success = FALSE;
    462 return SCIP_OKAY;
    463 }
    464
    465 /* calculate node limit for the subproblem */
    466 nodelimit = calcNodeLimit(scip, heur, heurdata);
    467
    468 /* we should have aborted the sub-SCIP procedure earlier if no additional nodes are allowed
    469 * with the current parameter settings
    470 */
    471 assert(nodelimit > SCIPgetNNodes(subscip));
    472
    473 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", nodelimit) );
    474 heurdata->nodelimit = nodelimit;
    475
    476 /* set also the other two limits */
    477 SCIP_CALL( SCIPsetRealParam(subscip, "limits/time", timelimit) );
    478 SCIP_CALL( SCIPsetRealParam(subscip, "limits/memory", memorylimit) );
    479
    480 /* disable bound limits */
    481 SCIP_CALL( SCIPsetRealParam(subscip, "limits/primal", SCIP_INVALID) );
    482 SCIP_CALL( SCIPsetRealParam(subscip, "limits/dual", SCIP_INVALID) );
    483
    484 return SCIP_OKAY;
    485}
    486
    487/** sets all one-time parameter settings like search strategy, but no limits */
    488static
    490 SCIP* subscip /**< data structure of the sub-problem */
    491 )
    492{
    493 /* do not abort subproblem on CTRL-C */
    494 SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
    495
    496 /* for debugging lpface, enable MIP output */
    497#ifdef SCIP_DEBUG
    498 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) );
    499 SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 1) );
    500#endif
    501
    502 /* disable statistic timing inside sub SCIP */
    503 SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
    504
    505 /* forbid recursive call of heuristics and separators solving subMIPs */
    506 SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );
    507
    508 /* disable expensive cutting plane separation */
    510
    511 /* disable expensive presolving */
    513
    514 /* use restart depth first node selection */
    515 if( SCIPfindNodesel(subscip, "restartdfs") != NULL && ! SCIPisParamFixed(subscip, "nodeselection/restartdfs/stdpriority") )
    516 {
    517 SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/restartdfs/stdpriority", INT_MAX/4) );
    518 }
    519
    520 /* use inference branching */
    521 if( SCIPfindBranchrule(subscip, "inference") != NULL && ! SCIPisParamFixed(subscip, "branching/inference/priority") )
    522 {
    523 SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
    524 }
    525
    526 /* enable conflict analysis, disable analysis of boundexceeding LPs, and restrict conflict pool */
    527 if( !SCIPisParamFixed(subscip, "conflict/enable") )
    528 {
    529 SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/enable", TRUE) );
    530 }
    531 if( !SCIPisParamFixed(subscip, "conflict/useboundlp") )
    532 {
    533 SCIP_CALL( SCIPsetCharParam(subscip, "conflict/useboundlp", 'o') );
    534 }
    535 if( !SCIPisParamFixed(subscip, "conflict/maxstoresize") )
    536 {
    537 SCIP_CALL( SCIPsetIntParam(subscip, "conflict/maxstoresize", 100) );
    538 }
    539
    540 return SCIP_OKAY;
    541}
    542
    543/** reset the sub-SCIP data to its default values */
    544static
    546 SUBSCIPDATA* subscipdata /**< data structure of the sub-problem */
    547 )
    548{
    549 subscipdata->subscip = NULL;
    550 subscipdata->subvars = NULL;
    551 subscipdata->nsubvars = 0;
    552 subscipdata->objbound = SCIP_INVALID;
    553}
    554
    555/** free the stored sub-SCIP information */
    556static
    558 SCIP* scip, /**< original SCIP data structure */
    559 SUBSCIPDATA* subscipdata /**< data structure of the sub-problem */
    560 )
    561{
    562 assert(subscipdata != NULL);
    563
    564 /* free the subscipdata's scip */
    565 if( subscipdata->subscip != NULL )
    566 {
    567 SCIP_CALL( SCIPfree(&subscipdata->subscip) );
    568 }
    569
    570 subscipdata->subscip = NULL;
    571
    572 /* free the subscip variables */
    573 if( subscipdata->subvars != NULL )
    574 {
    575 assert(subscipdata->nsubvars > 0);
    576 SCIPfreeBlockMemoryArray(scip, &subscipdata->subvars, subscipdata->nsubvars);
    577 }
    578
    579 subscipdataReset(subscipdata);
    580
    581 return SCIP_OKAY;
    582}
    583
    584/** store the sub-SCIP to the data structure */
    585static
    587 SCIP* scip, /**< original SCIP data structure */
    588 SUBSCIPDATA* subscipdata, /**< data structure of the sub-problem */
    589 SCIP* subscip, /**< sub scip data structure to keep */
    590 SCIP_VAR** subvars, /**< sub scip variable array in the order of the main SCIP variables */
    591 int nvars /**< number of sub SCIP variables */
    592 )
    593{
    594 assert(scip != NULL);
    595 assert(subscipdata != NULL);
    596 assert(subscip != NULL);
    597 assert(subvars != NULL);
    598 assert(nvars == SCIPgetNVars(scip));
    599
    600 assert(subscipdata->subscip == NULL);
    601 assert(subscipdata->subvars == NULL);
    602
    603 subscipdata->subscip = subscip;
    604 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &subscipdata->subvars, subvars, nvars) );
    605 subscipdata->nsubvars = nvars;
    606
    608
    609 return SCIP_OKAY;
    610}
    611
    612#ifdef SCIP_DEBUG
    613/** print debug message listing solving time, nodes, and status of sub-SCIP */
    614static
    615SCIP_RETCODE subscipGetInfo(
    616 SCIP* scip, /**< SCIP data structure */
    617 SCIP* subscip /**< sub SCIP data */
    618 )
    619{
    620 SCIP_Real timelimit;
    621 SCIP_Real memorylimit;
    622 SCIP_Longint nodelimit;
    623 SCIP_Real time;
    624 SCIP_Longint nodes;
    625 SCIP_STATUS status;
    626
    627 SCIP_CALL( SCIPgetRealParam(subscip, "limits/time", &timelimit) );
    628 SCIP_CALL( SCIPgetRealParam(subscip, "limits/memory", &memorylimit) );
    629 SCIP_CALL( SCIPgetLongintParam(subscip, "limits/nodes", &nodelimit) );
    630
    631 time = SCIPgetSolvingTime(subscip);
    632 nodes = SCIPgetNNodes(subscip);
    633 status = SCIPgetStatus(subscip);
    634
    635 SCIPdebugMsg(scip, "SCIP info: Time: %.1f (Limit: %.1f) Nodes: %"SCIP_LONGINT_FORMAT" (Limit: %"SCIP_LONGINT_FORMAT") Status: %d\n",
    636 time, timelimit, nodes, nodelimit, status);
    637
    638 return SCIP_OKAY;
    639}
    640#endif
    641
    642/** create the objective function based on the user selection */
    643static
    645 SCIP* scip, /**< SCIP data structure */
    646 SCIP* subscip, /**< sub-SCIP data structure */
    647 SCIP_VAR* var, /**< SCIP variable */
    648 SCIP_VAR* subvar, /**< sub-SCIP variable whose objective coefficient is changed */
    649 SCIP_HEURDATA* heurdata /**< heuristic data structure to control how the objective is changed */
    650 )
    651{
    652 SCIP_Real objcoeff;
    653 SCIP_Real upfrac;
    654 SCIP_Real downfrac;
    655 SCIP_Real lpsolval;
    656 SCIP_Real rootlpsolval;
    657
    658 /* create the objective value based on the choice of the sub-SCIP objective */
    659 switch( heurdata->subscipobjective )
    660 {
    661 /* use zero as objective function */
    662 case 'z':
    663 objcoeff = 0.0;
    664 break;
    665
    666 /* use current LP fractionality as objective */
    667 case 'f':
    668 lpsolval = SCIPvarGetLPSol(var);
    669 downfrac = SCIPfrac(scip, lpsolval);
    670 upfrac = 1.0 - downfrac;
    671
    672 objcoeff = downfrac - upfrac;
    673 break;
    674
    675 /* use root LP solution difference */
    676 case 'r':
    677 lpsolval = SCIPvarGetLPSol(var);
    678 rootlpsolval = SCIPvarGetRootSol(var);
    679 objcoeff = rootlpsolval - lpsolval;
    680 break;
    681
    682 /* use average inferences */
    683 case 'i':
    686 break;
    687
    688 /* use original objective function */
    689 case 'o':
    690 objcoeff = SCIPvarGetObj(var);
    691 break;
    692 default:
    693 objcoeff = 0.0;
    694 break;
    695 }
    696
    697 SCIP_CALL( SCIPchgVarObj(subscip, subvar, objcoeff) );
    698
    699 return SCIP_OKAY;
    700}
    701
    702/* ---------------- Callback methods of event handler ---------------- */
    703
    704/** execution callback of the event handler for Lpface sub-SCIP
    705 *
    706 * we interrupt the solution process if we hit the LP iteration limit per node
    707 */
    708static
    709SCIP_DECL_EVENTEXEC(eventExecLpface)
    710{
    711 SCIP_HEURDATA* heurdata;
    712
    713 assert(eventhdlr != NULL);
    714 assert(eventdata != NULL);
    715 assert(event != NULL);
    717
    719
    720 heurdata = (SCIP_HEURDATA*)eventdata;
    721 assert(heurdata != NULL);
    722
    723 /* interrupt solution process of sub-SCIP */
    724 if( SCIPgetNLPs(scip) > heurdata->lplimfac * heurdata->nodelimit )
    725 {
    726 SCIPdebugMsg(scip, "interrupt after %" SCIP_LONGINT_FORMAT " LPs\n",SCIPgetNLPs(scip));
    728 }
    729
    730 return SCIP_OKAY;
    731}
    732
    733/** setup and solve the subproblem and catch the return code */
    734static
    736 SCIP* scip, /**< SCIP data structure */
    737 SCIP* subscip, /**< sub-SCIP data structure */
    738 SCIP_HEURDATA* heurdata, /**< heuristics data */
    739 SCIP_VAR** subvars, /**< subproblem's variables */
    740 SCIP_VAR** vars, /**< original problem's variables */
    741 SCIP_VAR** fixvars, /**< variables that should be fixed */
    742 SCIP_Real* fixvals, /**< corresponding fixing values */
    743 int nfixvars, /**< number of variables that should be fixed */
    744 int nvars /**< number of original problem's variables */
    745 )
    746{
    747 SCIP_HASHMAP* varmapfw = NULL; /* mapping of SCIP variables to sub-SCIP variables */
    748 SCIP_Bool success;
    749 int i;
    750
    751 assert( subscip != NULL );
    752 assert( heurdata != NULL );
    753 assert( vars != NULL );
    754
    755 /* create the variable hash map */
    756 SCIP_CALL( SCIPhashmapCreate(&varmapfw, SCIPblkmem(subscip), nvars) );
    757 success = FALSE;
    758
    759 if( heurdata->uselprows )
    760 {
    761 SCIP_Bool valid;
    762 char probname[SCIP_MAXSTRLEN];
    763
    764 /* copy all plugins */
    766 TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, &valid) );
    767
    768 /* copy parameter settings */
    770
    771 /* even when solving exactly, sub-SCIP heuristics should be run in floating-point mode, since the exactsol constraint
    772 * handler is in place to perform a final repair step
    773 */
    775
    776 /* get name of the original problem and add the string "_lpfacesub" */
    777 (void) SCIPsnprintf(probname, SCIP_MAXSTRLEN, "%s_lpfacesub", SCIPgetProbName(scip));
    778
    779 /* create the subproblem */
    780 SCIP_CALL( SCIPcreateProbBasic(subscip, probname) );
    782
    783 /* copy all variables */
    784 SCIP_CALL( SCIPcopyVars(scip, subscip, varmapfw, NULL, fixvars, fixvals, nfixvars, TRUE) );
    785 }
    786 else
    787 {
    788 SCIP_CALL( SCIPcopyConsCompression(scip, subscip, varmapfw, NULL, "lpface", fixvars, fixvals, nfixvars, TRUE, FALSE, FALSE, TRUE, &success) );
    789
    790 if( heurdata->copycuts )
    791 {
    792 /* copies all active cuts from cutpool of sourcescip to linear constraints in targetscip */
    793 SCIP_CALL( SCIPcopyCuts(scip, subscip, varmapfw, NULL, TRUE, NULL) );
    794 }
    795 }
    796 assert(!SCIPisExact(subscip));
    797
    798 /* fill subvars array with mapping from original variables and set the objective coefficient to the desired value */
    799 for( i = 0; i < nvars; i++ )
    800 {
    801 subvars[i] = (SCIP_VAR*) SCIPhashmapGetImage(varmapfw, vars[i]);
    802
    803 if( subvars[i] != NULL )
    804 {
    805 SCIP_CALL( changeSubvariableObjective(scip, subscip, vars[i], subvars[i], heurdata) );
    806 }
    807 }
    808
    809 /* free hash map */
    810 SCIPhashmapFree(&varmapfw);
    811
    812 /* disable output to console */
    813 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
    814
    815 /* fix variables that are at their bounds and have nonzero reduced costs */
    816 SCIP_CALL( setupSubproblem(scip, subscip, subvars, heurdata) );
    817
    818 /* set up sub-SCIP parameters */
    820
    821 return SCIP_OKAY;
    822}
    823
    824/** setup and solve the subproblem and catch the return code */
    825static
    827 SCIP* scip, /**< SCIP data structure */
    828 SCIP* subscip, /**< sub-SCIP data structure */
    829 SCIP_HEUR* heur, /**< mutation heuristic */
    830 SCIP_HEURDATA* heurdata, /**< heuristics data */
    831 SCIP_VAR** subvars, /**< subproblem's variables */
    832 SCIP_RESULT* result, /**< pointer to store the result */
    833 SCIP_Real focusnodelb, /**< lower bound of the focus node */
    834 SCIP_Bool* keepthisscip /**< should the subscip be kept or deleted? */
    835 )
    836{
    837 SCIP_EVENTHDLR* eventhdlr;
    838 SCIP_Bool success;
    839
    840 assert( scip != NULL );
    841 assert( subscip != NULL );
    842 assert( heur != NULL );
    843 assert( heurdata != NULL );
    844 assert( subvars != NULL );
    845
    846 /* create event handler for LP events */
    847 SCIP_CALL( SCIPincludeEventhdlrBasic(subscip, &eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC, eventExecLpface, NULL) );
    848 if( eventhdlr == NULL )
    849 {
    850 SCIPerrorMessage("event handler for " HEUR_NAME " heuristic not found.\n");
    851 return SCIP_PLUGINNOTFOUND;
    852 }
    853
    854 /* determine node, memory, and time limits for the sub-SCIP. Both node and time limit change with every call to
    855 * the heuristic
    856 */
    857 SCIP_CALL( setSubscipLimits(scip, subscip, heur, heurdata, &success) );
    858
    859 /* if we did not succeed to set the limits of the subscip to let it run, we won't keep it any longer */
    860 if( !success )
    861 {
    862 *keepthisscip = FALSE;
    863
    864 return SCIP_OKAY;
    865 }
    866
    867 /* catch LP events of sub-SCIP */
    868 SCIP_CALL( SCIPtransformProb(subscip) );
    869 SCIP_CALL( SCIPcatchEvent(subscip, SCIP_EVENTTYPE_LPSOLVED, eventhdlr, (SCIP_EVENTDATA*) heurdata, NULL) );
    870
    871#ifdef WRITELPFACEPROB
    872 {
    873 char probfilename[] = "./lpface_prob.mps";
    874 char paramfilename[] = "./lpface_prob.set";
    875 SCIPinfoMessage(scip, NULL, "Writing problem and parameters to file: <%s> <%s>\n", probfilename, paramfilename);
    876 SCIP_CALL( SCIPwriteOrigProblem(subscip, probfilename, NULL, FALSE) );
    877 SCIP_CALL( SCIPwriteParams(subscip, paramfilename, TRUE, TRUE) );
    878 }
    879#endif
    880
    881 /* we must not be infeasible at this stage */
    882 assert(SCIPgetStatus(subscip) != SCIP_STATUS_INFEASIBLE);
    883
    884 /* solve the subproblem */
    885 SCIPdebugMsg(scip, "Solve Lpface subMIP\n");
    886 SCIPdebug(
    887 SCIP_CALL( subscipGetInfo(scip, subscip) );
    888 )
    889
    890 /* Errors in solving the subproblem should not kill the overall solving process.
    891 * Hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
    892 */
    893 SCIP_CALL_ABORT( SCIPsolve(subscip) );
    894
    895 /* print solving statistics of subproblem if we are in SCIP's debug mode */
    897
    898 /* save useful information regarding the subscip runs */
    899 heurdata->usednodes += SCIPgetNNodes(subscip);
    900 heurdata->submipnlpiters += SCIPgetNLPIterations(subscip);
    901 heurdata->submippresoltime += SCIPgetPresolvingTime(subscip);
    902 heurdata->submipstatus = SCIPgetStatus(subscip);
    903
    904 /* store the focus node lower bound as infeasible to avoid running on this face again */
    905 if( heurdata->submipstatus == SCIP_STATUS_INFEASIBLE )
    906 {
    907 heurdata->lastlpobjinfeas = focusnodelb;
    908 *keepthisscip = FALSE;
    909 }
    910 else if( SCIPgetNSols(subscip) > 0 )
    911 {
    912 int solindex;
    913
    914 /* check, whether a solution was found;
    915 * due to numerics, it might happen that not all solutions are feasible -> try all solutions until one is accepted
    916 */
    917 SCIP_CALL( SCIPtranslateSubSols(scip, subscip, heur, subvars, &success, &solindex) );
    918 SCIPdebugMsg(scip, "Transfer was %s successful\n", success ? "" : "not");
    919
    920 /* we found an optimal solution and are done. Thus, we free the subscip immediately */
    921 if( success )
    922 {
    923 *keepthisscip = FALSE;
    924 *result = SCIP_FOUNDSOL;
    925 }
    926
    927 /* if solution could not be added to problem => run is counted as a failure */
    928 if( ! success || solindex != SCIPsolGetIndex(SCIPgetBestSol(scip)) )
    929 updateFailureStatistic(scip, heurdata);
    930 }
    931 else
    932 {
    933 /* if no new solution was found, run was a failure */
    934 updateFailureStatistic(scip, heurdata);
    935 }
    936
    937 return SCIP_OKAY;
    938}
    939
    940/*
    941 * Callback methods of primal heuristic
    942 */
    943
    944/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
    945static
    946SCIP_DECL_HEURCOPY(heurCopyLpface)
    947{ /*lint --e{715}*/
    948 assert(scip != NULL);
    949 assert(heur != NULL);
    950
    952
    953 /* call inclusion method of primal heuristic */
    955
    956 return SCIP_OKAY;
    957}
    958
    959/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
    960static
    961SCIP_DECL_HEURFREE(heurFreeLpface)
    962{ /*lint --e{715}*/
    963 SCIP_HEURDATA* heurdata;
    964
    965 assert(heur != NULL);
    966 assert(scip != NULL);
    967
    968 /* get heuristic data */
    969 heurdata = SCIPheurGetData(heur);
    970 assert(heurdata != NULL);
    971
    972 /* free heuristic data */
    973 SCIPfreeBlockMemory(scip, &heurdata);
    974 SCIPheurSetData(heur, NULL);
    975
    976 return SCIP_OKAY;
    977}
    978
    979/** initialization method of primal heuristic (called after problem was transformed) */
    980static
    981SCIP_DECL_HEURINIT(heurInitLpface)
    982{ /*lint --e{715}*/
    983 SCIP_HEURDATA* heurdata;
    984
    985 assert(heur != NULL);
    986 assert(scip != NULL);
    987
    988 /* get heuristic's data */
    989 heurdata = SCIPheurGetData(heur);
    990 assert(heurdata != NULL);
    991
    992 /* initialize data */
    993 heurdata->usednodes = 0;
    994 heurdata->nfailures = 0;
    995 heurdata->nextnodenumber = 0;
    996
    997 heurdata->submipstatus = SCIP_STATUS_UNKNOWN;
    998 heurdata->submipnlpiters = -1;
    999 heurdata->submippresoltime = 0.0;
    1000 heurdata->nvarsfixed = -1;
    1001
    1002 return SCIP_OKAY;
    1003}
    1004
    1005/** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
    1006static
    1007SCIP_DECL_HEURINITSOL(heurInitsolLpface)
    1008{ /*lint --e{715}*/
    1009 SCIP_HEURDATA* heurdata;
    1010
    1011 assert(heur != NULL);
    1012 assert(scip != NULL);
    1013
    1014 /* get heuristic's data */
    1015 heurdata = SCIPheurGetData(heur);
    1016 assert(heurdata != NULL);
    1017
    1018 /* reset the last infeasible objective because it lives in transformed space and must be invalidated at every restart */
    1019 heurdata->lastlpobjinfeas = -SCIPinfinity(scip);
    1020
    1021 assert(heurdata->subscipdata == NULL);
    1022
    1023 /* variable order might have changed since the last run, reinitialize sub-SCIP data */
    1024 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata->subscipdata) );
    1025 subscipdataReset(heurdata->subscipdata);
    1026
    1027 return SCIP_OKAY;
    1028}
    1029
    1030/** solving process deinitialization method of primal heuristic (called before branch and bound process is exiting) */
    1031static
    1032SCIP_DECL_HEUREXITSOL(heurExitsolLpface)
    1033{ /*lint --e{715}*/
    1034 SCIP_HEURDATA* heurdata;
    1035
    1036 assert(heur != NULL);
    1037 assert(scip != NULL);
    1038
    1039 /* get heuristic's data */
    1040 heurdata = SCIPheurGetData(heur);
    1041 assert(heurdata != NULL);
    1042
    1043 /* variable order might change after restart, free the heuristic subscipdata */
    1044 assert(heurdata->keepsubscip || heurdata->subscipdata->subscip == NULL);
    1045 if( heurdata->subscipdata->subscip != NULL )
    1046 {
    1047 /* free kept data structures first */
    1048 SCIP_CALL( subscipdataFreeSubscip(scip, heurdata->subscipdata) );
    1049 }
    1050
    1051 /* free the sub-SCIP data structure */
    1052 SCIPfreeBlockMemory(scip, &heurdata->subscipdata);
    1053
    1054 return SCIP_OKAY;
    1055}
    1056
    1057#ifdef SCIP_STATISTIC
    1058/** deinitialization method of primal heuristic (called before transformed problem is freed) */
    1059static
    1061{ /*lint --e{715}*/
    1062 SCIP_HEURDATA* heurdata;
    1063
    1064 assert(heur != NULL);
    1065 assert(scip != NULL);
    1066
    1067 /* get heuristic's data */
    1068 heurdata = SCIPheurGetData(heur);
    1069 assert(heurdata != NULL);
    1070
    1072 "LP Face heuristic stats: Status: %d Nodes: %d LP iters: %d Fixed: %d Presolving time: %.2f\n",
    1073 heurdata->submipstatus, heurdata->usednodes, heurdata->submipnlpiters, heurdata->nvarsfixed, heurdata->submippresoltime);
    1074
    1075 return SCIP_OKAY;
    1076}
    1077#else
    1078#define heurExitLpface NULL
    1079#endif
    1080
    1081/** execution method of primal heuristic */
    1082static
    1083SCIP_DECL_HEUREXEC(heurExecLpface)
    1084{ /*lint --e{715}*/
    1085 SCIP* subscip; /* the subproblem created by lpface */
    1086 SCIP_HEURDATA* heurdata; /* primal heuristic data */
    1087 SCIP_VAR** vars; /* original problem's variables */
    1088 SCIP_VAR** subvars; /* subproblem's variables */
    1089 SCIP_RETCODE retcode;
    1090 SCIP_Bool keepthisscip;
    1091 SCIP_Real focusnodelb;
    1092 SCIP_Real rootlb;
    1093 SCIP_Longint nodelimit; /* node limit for the subproblem */
    1094 int nvars; /* number of original problem's variables */
    1095 int nbinvars;
    1096 int nintvars;
    1097
    1098 assert(scip != NULL);
    1099 assert(heur != NULL);
    1100 assert(result != NULL);
    1101
    1102 *result = SCIP_DELAYED;
    1103
    1104 /* we skip infeasible nodes */
    1105 if( nodeinfeasible )
    1106 return SCIP_OKAY;
    1107
    1108 /* do not run heuristic on nodes that were not solved to optimality */
    1110 return SCIP_OKAY;
    1111
    1112 /* LP face requires that the LP defines a valid lower bound for the current node */
    1114 return SCIP_OKAY;
    1115
    1116 assert(SCIPgetCurrentNode(scip) != NULL);
    1118 assert(!SCIPisInfinity(scip, focusnodelb));
    1119
    1120 /* do not run if the current focus node already has a lower bound higher than the LP value at the node,
    1121 * for example, due to strong branching
    1122 */
    1123 if( SCIPisGT(scip, focusnodelb, SCIPgetLPObjval(scip)) )
    1124 return SCIP_OKAY;
    1125
    1126 /* from the checked conditions, the LP objective should be the lower bound for the current node */
    1127 assert(SCIPisEQ(scip, focusnodelb, SCIPgetLPObjval(scip)));
    1128
    1129 /* only run at lower bound defining nodes */
    1130 if( SCIPisGT(scip, focusnodelb, SCIPgetLowerbound(scip)) )
    1131 return SCIP_OKAY;
    1132
    1133 /* get heuristic's data */
    1134 heurdata = SCIPheurGetData(heur);
    1135 assert(heurdata != NULL);
    1136
    1137 /* delay heuristic if the active search tree path is not deep enough */
    1138 if( SCIPgetDepth(scip) < heurdata->minpathlen - 1 )
    1139 return SCIP_OKAY;
    1140
    1141 /* the node number to run the heuristic again was not yet reached */
    1142 if( SCIPgetNNodes(scip) < heurdata->nextnodenumber )
    1143 return SCIP_OKAY;
    1144
    1145 /* only run if lower bound has increased since last LP objective where the sub-MIP was solved to infeasibility */
    1146 if( SCIPisEQ(scip, heurdata->lastlpobjinfeas, focusnodelb) )
    1147 return SCIP_OKAY;
    1148
    1149 /* make the reasoning stronger if the objective value must be integral */
    1151 && (! SCIPisIntegral(scip, focusnodelb) || SCIPisLT(scip, focusnodelb, heurdata->lastlpobjinfeas + 1.0)) )
    1152 return SCIP_OKAY;
    1153
    1154 rootlb = SCIPgetLowerboundRoot(scip);
    1155 assert(SCIPisLE(scip, rootlb, focusnodelb));
    1156
    1157 /* if the lower bound hasn't changed since the root node, we want to run anyway, otherwise we base our decision on the
    1158 * total path length of the active search tree along which the lower bound did not change anymore.
    1159 */
    1160 if( SCIPisLT(scip, rootlb, focusnodelb) )
    1161 {
    1162 SCIP_NODE* parent;
    1163 int nonimprovingpathlen = 0; /* the length of the current path (in edges) along which the lower bound stayed the same */
    1164
    1166
    1167 /* count the path length along which the dual bound has not changed */
    1168 while( SCIPisEQ(scip, SCIPnodeGetLowerbound(parent), focusnodelb) && nonimprovingpathlen < heurdata->minpathlen )
    1169 {
    1170 ++nonimprovingpathlen;
    1171
    1172 /* we cannot hit the root node because the root lower bound is strictly smaller */
    1173 assert(SCIPnodeGetParent(parent) != NULL);
    1174 parent = SCIPnodeGetParent(parent);
    1175 }
    1176
    1177 /* we return if the nonimproving path is too short measured by the heuristic frequency */
    1178 if( nonimprovingpathlen < heurdata->minpathlen )
    1179 {
    1180 /* we do not delay the heuristic if the path has length zero, otherwise it may be called at children so that
    1181 * the path length is sufficient
    1182 */
    1183 if( nonimprovingpathlen == 0 )
    1184 *result = SCIP_DIDNOTRUN;
    1185
    1186 return SCIP_OKAY;
    1187 }
    1188 }
    1189
    1190 *result = SCIP_DIDNOTRUN;
    1191
    1192 /* calculate the maximal number of branching nodes until heuristic is aborted */
    1193 nodelimit = calcNodeLimit(scip, heur, heurdata);
    1194
    1195 /* check whether we have enough nodes left to call subproblem solving */
    1196 if( nodelimit < heurdata->minnodes )
    1197 return SCIP_OKAY;
    1198
    1199 if( SCIPisStopped(scip) )
    1200 return SCIP_OKAY;
    1201
    1202 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
    1203 assert(nvars > 0);
    1204
    1205 /* check whether discrete variables are present */
    1206 if( nbinvars == 0 && nintvars == 0 )
    1207 return SCIP_OKAY;
    1208
    1209 *result = SCIP_DIDNOTFIND;
    1210
    1211 keepthisscip = heurdata->keepsubscip;
    1212
    1213 /* check if variable number increased since last call to the sub-SCIP */
    1214 if( heurdata->subscipdata->subscip != NULL && heurdata->subscipdata->nsubvars != nvars )
    1215 {
    1216 SCIPdebugMsg(scip, "Free subscip of LP face heuristic because variable number %d changed since last call (was %d)\n",
    1217 nvars, heurdata->subscipdata->nsubvars);
    1218
    1219 SCIP_CALL( subscipdataFreeSubscip(scip, heurdata->subscipdata) );
    1220 }
    1221 else if( heurdata->subscipdata->subscip != NULL && SCIPisGT(scip, focusnodelb, heurdata->subscipdata->objbound) )
    1222 {
    1223 SCIPdebugMsg(scip, "Free subscip of LP face heuristic because of different dual bound: %16.9g > %16.9g\n",
    1224 SCIPretransformObj(scip, focusnodelb), SCIPretransformObj(scip, heurdata->subscipdata->objbound));
    1225
    1226 SCIP_CALL( subscipdataFreeSubscip(scip, heurdata->subscipdata) );
    1227 }
    1228
    1229 /* retrieve the sub-SCIP from the heuristic data structure */
    1230 if( heurdata->subscipdata->subscip != NULL )
    1231 {
    1232 subscip = heurdata->subscipdata->subscip;
    1233 subvars = heurdata->subscipdata->subvars;
    1234 nvars = heurdata->subscipdata->nsubvars;
    1235
    1236 SCIPdebug(
    1237 SCIPdebugMsg(scip, "Loaded sub-SCIP from previous run:\n");
    1238 SCIP_CALL( subscipGetInfo(scip, subscip) );
    1239 )
    1240 }
    1241 else
    1242 {
    1243 SCIP_VAR** fixvars;
    1244 SCIP_Real* fixvals;
    1245 int nfixvars;
    1246 SCIP_Bool success;
    1247
    1248 assert(heurdata->subscipdata->subscip == NULL);
    1249
    1250 /* allocate memory to hold sub-SCIP variables */
    1251 SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
    1252
    1253 SCIP_CALL( SCIPallocBufferArray(scip, &fixvars, nvars) );
    1254 SCIP_CALL( SCIPallocBufferArray(scip, &fixvals, nvars) );
    1255
    1256 SCIP_CALL( determineVariableFixings(scip, heurdata, fixvars, fixvals, &nfixvars, &success) );
    1257
    1258 if( ! success )
    1259 {
    1260 SCIPfreeBufferArray(scip, &fixvals);
    1261 SCIPfreeBufferArray(scip, &fixvars);
    1262 SCIPfreeBufferArray(scip, &subvars);
    1263
    1264 *result = SCIP_DIDNOTRUN;
    1265 return SCIP_OKAY;
    1266 }
    1267
    1268 SCIPdebugMsg(scip, "Creating new sub-Problem for LP face heuristic\n");
    1269
    1270 /* initialize the subproblem */
    1271 SCIP_CALL( SCIPcreate(&subscip) );
    1272
    1273 SCIP_CALL( setupSubscipLpface(scip, subscip, heurdata, subvars, vars, fixvars, fixvals, nfixvars, nvars) );
    1274
    1275 SCIPfreeBufferArray(scip, &fixvals);
    1276 SCIPfreeBufferArray(scip, &fixvars);
    1277 }
    1278
    1279 retcode = solveSubscipLpface(scip, subscip, heur, heurdata, subvars, result, focusnodelb, &keepthisscip);
    1280
    1281 SCIP_CALL( retcode );
    1282
    1283 /* free subproblem or store it for the next run of the heuristic */
    1284 if( ! keepthisscip )
    1285 {
    1286 /* we only allocated buffer memory if no previous subscip was reinstalled */
    1287 if( heurdata->subscipdata->subscip == NULL )
    1288 {
    1289 SCIPfreeBufferArray(scip, &subvars);
    1290 SCIP_CALL( SCIPfree(&subscip) );
    1291 }
    1292 else
    1293 SCIP_CALL( subscipdataFreeSubscip(scip, heurdata->subscipdata) );
    1294
    1295 subscipdataReset(heurdata->subscipdata);
    1296 }
    1297 else
    1298 {
    1299 /* if the subscip has not yet been stored, we copy the subscip into the heuristic data to keep it for the next run */
    1300 if( heurdata->subscipdata->subscip == NULL )
    1301 {
    1302 SCIP_CALL( subscipdataCopySubscip(scip, heurdata->subscipdata, subscip, subvars, nvars) );
    1303 SCIPfreeBufferArray(scip, &subvars);
    1304 }
    1305 else
    1306 {
    1307 assert(heurdata->subscipdata->subscip == subscip);
    1308 assert(heurdata->subscipdata->subvars == subvars);
    1309 assert(heurdata->subscipdata->nsubvars == nvars);
    1310 }
    1311 }
    1312
    1313 return SCIP_OKAY;
    1314}
    1315
    1316/*
    1317 * primal heuristic specific interface methods
    1318 */
    1319
    1320/** creates the lpface primal heuristic and includes it in SCIP */
    1322 SCIP* scip /**< SCIP data structure */
    1323 )
    1324{
    1325 SCIP_HEURDATA* heurdata;
    1326 SCIP_HEUR* heur;
    1327
    1328 /* create Lpface primal heuristic data */
    1329 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    1330
    1331 heurdata->subscipdata = NULL;
    1332
    1333 /* include primal heuristic */
    1336 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecLpface, heurdata) );
    1337
    1338 assert(heur != NULL);
    1339
    1340 /* primal heuristic is safe to use in exact solving mode */
    1341 SCIPheurMarkExact(heur);
    1342
    1343 /* set non-NULL pointers to callback methods */
    1344 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyLpface) );
    1345 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeLpface) );
    1346 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitLpface) );
    1347 SCIP_CALL( SCIPsetHeurInitsol(scip, heur, heurInitsolLpface) );
    1348 SCIP_CALL( SCIPsetHeurExitsol(scip, heur, heurExitsolLpface) );
    1350
    1351 /* add lpface primal heuristic parameters */
    1352 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/nodesofs",
    1353 "number of nodes added to the contingent of the total nodes",
    1354 &heurdata->nodesofs, FALSE, DEFAULT_NODESOFS, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
    1355
    1356 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
    1357 "maximum number of nodes to regard in the subproblem",
    1358 &heurdata->maxnodes, TRUE, DEFAULT_MAXNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
    1359
    1360 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/minnodes",
    1361 "minimum number of nodes required to start the subproblem",
    1362 &heurdata->minnodes, TRUE, DEFAULT_MINNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
    1363
    1364 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesquot",
    1365 "contingent of sub problem nodes in relation to the number of nodes of the original problem",
    1366 &heurdata->nodesquot, FALSE, DEFAULT_NODESQUOT, 0.0, 1.0, NULL, NULL) );
    1367
    1368 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minfixingrate",
    1369 "required percentage of fixed integer variables in sub-MIP to run",
    1370 &heurdata->minfixingrate, FALSE, DEFAULT_MINFIXINGRATE, 0.0, 1.0, NULL, NULL) );
    1371
    1372 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/lplimfac",
    1373 "factor by which the limit on the number of LP depends on the node limit",
    1374 &heurdata->lplimfac, TRUE, DEFAULT_LPLIMFAC, 1.0, SCIP_REAL_MAX, NULL, NULL) );
    1375
    1376 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/uselprows",
    1377 "should subproblem be created out of the rows in the LP rows?",
    1378 &heurdata->uselprows, TRUE, DEFAULT_USELPROWS, NULL, NULL) );
    1379
    1380 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/dualbasisequations",
    1381 "should dually nonbasic rows be turned into equations?",
    1382 &heurdata->dualbasisequations, TRUE, DEFAULT_DUALBASISEQUATIONS, NULL, NULL) );
    1383
    1384 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/keepsubscip",
    1385 "should the heuristic continue solving the same sub-SCIP?",
    1386 &heurdata->keepsubscip, TRUE, DEFAULT_KEEPSUBSCIP, NULL, NULL) );
    1387
    1388 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/copycuts",
    1389 "if uselprows == FALSE, should all active cuts from cutpool be copied to constraints in subproblem?",
    1390 &heurdata->copycuts, TRUE, DEFAULT_COPYCUTS, NULL, NULL) );
    1391
    1392 SCIP_CALL( SCIPaddCharParam(scip, "heuristics/" HEUR_NAME "/subscipobjective",
    1393 "objective function in the sub-SCIP: (z)ero, (r)oot-LP-difference, (i)nference, LP (f)ractionality, (o)riginal",
    1394 &heurdata->subscipobjective, TRUE, 'z', "forzi", NULL, NULL) );
    1395
    1396 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/minpathlen",
    1397 "the minimum active search tree path length along which lower bound hasn't changed before heuristic becomes active",
    1398 &heurdata->minpathlen, TRUE, DEFAULT_MINPATHLEN, 0, 65531, NULL, NULL) );
    1399
    1400 return SCIP_OKAY;
    1401}
    Constraint handler for linear constraints in their most general form, .
    #define NULL
    Definition: def.h:257
    #define SCIP_MAXSTRLEN
    Definition: def.h:278
    #define SCIP_Longint
    Definition: def.h:150
    #define SCIP_REAL_MAX
    Definition: def.h:167
    #define SCIP_INVALID
    Definition: def.h:187
    #define SCIP_Bool
    Definition: def.h:100
    #define MIN(x, y)
    Definition: def.h:233
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define MAX(x, y)
    Definition: def.h:229
    #define SCIP_CALL_ABORT(x)
    Definition: def.h:343
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:157
    #define REALABS(x)
    Definition: def.h:191
    #define SCIP_LONGINT_MAX
    Definition: def.h:151
    #define SCIP_CALL(x)
    Definition: def.h:364
    SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
    SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    SCIP_RETCODE SCIPcopyPlugins(SCIP *sourcescip, SCIP *targetscip, SCIP_Bool copyreaders, SCIP_Bool copypricers, SCIP_Bool copyconshdlrs, SCIP_Bool copyconflicthdlrs, SCIP_Bool copypresolvers, SCIP_Bool copyrelaxators, SCIP_Bool copyseparators, SCIP_Bool copycutselectors, SCIP_Bool copypropagators, SCIP_Bool copyheuristics, SCIP_Bool copyeventhdlrs, SCIP_Bool copynodeselectors, SCIP_Bool copybranchrules, SCIP_Bool copyiisfinders, SCIP_Bool copydisplays, SCIP_Bool copydialogs, SCIP_Bool copytables, SCIP_Bool copyexprhdlrs, SCIP_Bool copynlpis, SCIP_Bool passmessagehdlr, SCIP_Bool *valid)
    Definition: scip_copy.c:276
    void SCIPsetSubscipDepth(SCIP *scip, int newdepth)
    Definition: scip_copy.c:2610
    SCIP_RETCODE SCIPtranslateSubSols(SCIP *scip, SCIP *subscip, SCIP_HEUR *heur, SCIP_VAR **subvars, SCIP_Bool *success, int *solindex)
    Definition: scip_copy.c:1438
    SCIP_RETCODE SCIPcopyVars(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int nfixedvars, SCIP_Bool global)
    Definition: scip_copy.c:1168
    SCIP_RETCODE SCIPcopyConsCompression(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, const char *suffix, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int nfixedvars, SCIP_Bool global, SCIP_Bool enablepricing, SCIP_Bool threadsafe, SCIP_Bool passmessagehdlr, SCIP_Bool *valid)
    Definition: scip_copy.c:2962
    int SCIPgetSubscipDepth(SCIP *scip)
    Definition: scip_copy.c:2589
    SCIP_RETCODE SCIPcopyCuts(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, int *ncutsadded)
    Definition: scip_copy.c:2114
    SCIP_RETCODE SCIPcopyParamSettings(SCIP *sourcescip, SCIP *targetscip)
    Definition: scip_copy.c:2548
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:767
    SCIP_RETCODE SCIPfree(SCIP **scip)
    Definition: scip_general.c:402
    SCIP_RETCODE SCIPcreate(SCIP **scip)
    Definition: scip_general.c:370
    SCIP_STATUS SCIPgetStatus(SCIP *scip)
    Definition: scip_general.c:562
    int SCIPgetNObjVars(SCIP *scip)
    Definition: scip_prob.c:2616
    const char * SCIPgetProbName(SCIP *scip)
    Definition: scip_prob.c:1242
    SCIP_RETCODE SCIPwriteOrigProblem(SCIP *scip, const char *filename, const char *extension, SCIP_Bool genericnames)
    Definition: scip_prob.c:742
    SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
    Definition: scip_prob.c:2115
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:3274
    SCIP_VAR ** SCIPgetVars(SCIP *scip)
    Definition: scip_prob.c:2201
    SCIP_RETCODE SCIPcreateProbBasic(SCIP *scip, const char *name)
    Definition: scip_prob.c:182
    SCIP_Bool SCIPisObjIntegral(SCIP *scip)
    Definition: scip_prob.c:1801
    void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
    Definition: misc.c:3095
    void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3284
    SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
    Definition: misc.c:3061
    SCIP_Real SCIPgetNodeLowerbound(SCIP *scip, SCIP_NODE *node)
    Definition: scip_prob.c:4215
    void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:208
    void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:225
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
    Definition: scip_param.c:250
    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_Bool SCIPisParamFixed(SCIP *scip, const char *name)
    Definition: scip_param.c:219
    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 SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:83
    SCIP_RETCODE SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
    Definition: scip_param.c:545
    SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:139
    SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
    Definition: scip_param.c:487
    SCIP_RETCODE SCIPsetSubscipsOff(SCIP *scip, SCIP_Bool quiet)
    Definition: scip_param.c:904
    SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
    Definition: scip_param.c:307
    SCIP_RETCODE SCIPwriteParams(SCIP *scip, const char *filename, SCIP_Bool comments, SCIP_Bool onlychanged)
    Definition: scip_param.c:813
    SCIP_RETCODE SCIPsetPresolving(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
    Definition: scip_param.c:956
    SCIP_RETCODE SCIPsetCharParam(SCIP *scip, const char *name, char value)
    Definition: scip_param.c:661
    SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:57
    SCIP_RETCODE SCIPgetLongintParam(SCIP *scip, const char *name, SCIP_Longint *value)
    Definition: scip_param.c:288
    SCIP_RETCODE SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
    Definition: scip_param.c:429
    SCIP_RETCODE SCIPsetRealParam(SCIP *scip, const char *name, SCIP_Real value)
    Definition: scip_param.c:603
    SCIP_RETCODE SCIPsetSeparating(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
    Definition: scip_param.c:985
    SCIP_RETCODE SCIPincludeHeurLpface(SCIP *scip)
    Definition: heur_lpface.c:1321
    SCIP_BRANCHRULE * SCIPfindBranchrule(SCIP *scip, const char *name)
    Definition: scip_branch.c:304
    SCIP_Real SCIPgetColRedcost(SCIP *scip, SCIP_COL *col)
    Definition: scip_lp.c:1163
    SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
    Definition: lp.c:17425
    SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
    Definition: scip_event.c:111
    const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
    Definition: event.c:396
    SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
    Definition: event.c:1194
    SCIP_RETCODE SCIPcatchEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
    Definition: scip_event.c:293
    SCIP_Bool SCIPisExact(SCIP *scip)
    Definition: scip_exact.c:193
    SCIP_RETCODE SCIPenableExactSolving(SCIP *scip, SCIP_Bool enable)
    Definition: scip_exact.c:151
    SCIP_RETCODE SCIPsetHeurExitsol(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXITSOL((*heurexitsol)))
    Definition: scip_heur.c:247
    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 SCIPheurGetNCalls(SCIP_HEUR *heur)
    Definition: heur.c:1593
    SCIP_RETCODE SCIPsetHeurInitsol(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINITSOL((*heurinitsol)))
    Definition: scip_heur.c:231
    void SCIPheurMarkExact(SCIP_HEUR *heur)
    Definition: heur.c:1457
    SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
    Definition: scip_heur.c:199
    const char * SCIPheurGetName(SCIP_HEUR *heur)
    Definition: heur.c:1467
    void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
    Definition: heur.c:1378
    SCIP_Bool SCIPisLPRelax(SCIP *scip)
    Definition: scip_lp.c:231
    SCIP_RETCODE SCIPgetLPRowsData(SCIP *scip, SCIP_ROW ***rows, int *nrows)
    Definition: scip_lp.c:576
    SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
    Definition: scip_lp.c:174
    SCIP_Bool SCIPallColsInLP(SCIP *scip)
    Definition: scip_lp.c:655
    SCIP_Real SCIPgetLPObjval(SCIP *scip)
    Definition: scip_lp.c:253
    SCIP_Longint SCIPgetMemExternEstim(SCIP *scip)
    Definition: scip_mem.c:126
    #define SCIPfreeBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:110
    SCIP_Longint SCIPgetMemUsed(SCIP *scip)
    Definition: scip_mem.c:100
    BMS_BLKMEM * SCIPblkmem(SCIP *scip)
    Definition: scip_mem.c:57
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    #define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
    Definition: scip_mem.h:105
    SCIP_Real SCIPnodeGetLowerbound(SCIP_NODE *node)
    Definition: tree.c:8533
    SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
    Definition: tree.c:8812
    SCIP_NODESEL * SCIPfindNodesel(SCIP *scip, const char *name)
    Definition: scip_nodesel.c:242
    SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
    Definition: lp.c:17686
    int SCIProwGetNNonz(SCIP_ROW *row)
    Definition: lp.c:17607
    SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
    Definition: lp.c:17632
    SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
    Definition: lp.c:17696
    SCIP_Bool SCIProwIsLocal(SCIP_ROW *row)
    Definition: lp.c:17795
    const char * SCIProwGetName(SCIP_ROW *row)
    Definition: lp.c:17745
    SCIP_Real SCIPgetRowActivity(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:2068
    SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
    Definition: lp.c:17652
    SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
    Definition: lp.c:17706
    SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
    Definition: lp.c:17642
    SCIP_SOL * SCIPgetBestSol(SCIP *scip)
    Definition: scip_sol.c:2986
    int SCIPgetNSols(SCIP *scip)
    Definition: scip_sol.c:2887
    int SCIPsolGetIndex(SCIP_SOL *sol)
    Definition: sol.c:4305
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1763
    SCIP_Real SCIPretransformObj(SCIP *scip, SCIP_Real obj)
    Definition: scip_sol.c:2134
    SCIP_RETCODE SCIPtransformProb(SCIP *scip)
    Definition: scip_solve.c:232
    SCIP_RETCODE SCIPinterruptSolve(SCIP *scip)
    Definition: scip_solve.c:3561
    SCIP_RETCODE SCIPsolve(SCIP *scip)
    Definition: scip_solve.c:2611
    SCIP_Real SCIPgetLowerboundRoot(SCIP *scip)
    SCIP_Longint SCIPgetNNodes(SCIP *scip)
    SCIP_RETCODE SCIPprintStatistics(SCIP *scip, FILE *file)
    SCIP_Real SCIPgetLowerbound(SCIP *scip)
    SCIP_Longint SCIPgetNLPs(SCIP *scip)
    SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
    SCIP_Real SCIPgetSolvingTime(SCIP *scip)
    Definition: scip_timing.c:378
    SCIP_Real SCIPgetPresolvingTime(SCIP *scip)
    Definition: scip_timing.c:442
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPfrac(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisDualfeasZero(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    int SCIPgetDepth(SCIP *scip)
    Definition: scip_tree.c:672
    SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
    Definition: scip_tree.c:91
    SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
    Definition: var.c:23715
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23418
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23932
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24174
    int SCIPvarGetProbindex(SCIP_VAR *var)
    Definition: var.c:23694
    SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
    Definition: var.c:19144
    SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
    Definition: var.c:23522
    SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
    Definition: var.c:24696
    SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
    Definition: var.c:23632
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24152
    SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
    Definition: scip_var.c:5372
    SCIP_Real SCIPgetVarAvgInferences(SCIP *scip, SCIP_VAR *var, SCIP_BRANCHDIR dir)
    Definition: scip_var.c:11891
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    static SCIP_RETCODE setSubscipLimits(SCIP *scip, SCIP *subscip, SCIP_HEUR *heur, SCIP_HEURDATA *heurdata, SCIP_Bool *success)
    Definition: heur_lpface.c:427
    static SCIP_RETCODE createRows(SCIP *scip, SCIP *subscip, SCIP_VAR **subvars, SCIP_Bool dualbasisequations)
    Definition: heur_lpface.c:237
    #define DEFAULT_NODESQUOT
    Definition: heur_lpface.c:81
    static SCIP_RETCODE subscipdataCopySubscip(SCIP *scip, SUBSCIPDATA *subscipdata, SCIP *subscip, SCIP_VAR **subvars, int nvars)
    Definition: heur_lpface.c:586
    static SCIP_RETCODE setSubscipParameters(SCIP *subscip)
    Definition: heur_lpface.c:489
    static SCIP_DECL_HEUREXEC(heurExecLpface)
    Definition: heur_lpface.c:1083
    static SCIP_RETCODE setupSubscipLpface(SCIP *scip, SCIP *subscip, SCIP_HEURDATA *heurdata, SCIP_VAR **subvars, SCIP_VAR **vars, SCIP_VAR **fixvars, SCIP_Real *fixvals, int nfixvars, int nvars)
    Definition: heur_lpface.c:735
    static SCIP_RETCODE subscipdataFreeSubscip(SCIP *scip, SUBSCIPDATA *subscipdata)
    Definition: heur_lpface.c:557
    #define DEFAULT_NODESOFS
    Definition: heur_lpface.c:80
    static SCIP_RETCODE changeSubvariableObjective(SCIP *scip, SCIP *subscip, SCIP_VAR *var, SCIP_VAR *subvar, SCIP_HEURDATA *heurdata)
    Definition: heur_lpface.c:644
    #define DEFAULT_COPYCUTS
    Definition: heur_lpface.c:85
    #define DEFAULT_MAXNODES
    Definition: heur_lpface.c:77
    #define HEUR_TIMING
    Definition: heur_lpface.c:74
    #define DEFAULT_MINNODES
    Definition: heur_lpface.c:78
    #define HEUR_FREQOFS
    Definition: heur_lpface.c:72
    #define HEUR_DESC
    Definition: heur_lpface.c:68
    static SCIP_RETCODE solveSubscipLpface(SCIP *scip, SCIP *subscip, SCIP_HEUR *heur, SCIP_HEURDATA *heurdata, SCIP_VAR **subvars, SCIP_RESULT *result, SCIP_Real focusnodelb, SCIP_Bool *keepthisscip)
    Definition: heur_lpface.c:826
    static SCIP_Longint calcNodeLimit(SCIP *scip, SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
    Definition: heur_lpface.c:395
    #define DEFAULT_KEEPSUBSCIP
    Definition: heur_lpface.c:88
    #define heurExitLpface
    Definition: heur_lpface.c:1078
    #define DEFAULT_LPLIMFAC
    Definition: heur_lpface.c:82
    static SCIP_DECL_HEURINITSOL(heurInitsolLpface)
    Definition: heur_lpface.c:1007
    #define DEFAULT_DUALBASISEQUATIONS
    Definition: heur_lpface.c:87
    #define DEFAULT_MINFIXINGRATE
    Definition: heur_lpface.c:79
    #define HEUR_DISPCHAR
    Definition: heur_lpface.c:69
    #define HEUR_MAXDEPTH
    Definition: heur_lpface.c:73
    #define HEUR_PRIORITY
    Definition: heur_lpface.c:70
    #define HEUR_NAME
    Definition: heur_lpface.c:67
    static SCIP_RETCODE determineVariableFixings(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR **fixvars, SCIP_Real *fixvals, int *nfixvars, SCIP_Bool *success)
    Definition: heur_lpface.c:147
    #define DEFAULT_USELPROWS
    Definition: heur_lpface.c:83
    #define DEFAULT_MINPATHLEN
    Definition: heur_lpface.c:89
    static SCIP_DECL_HEURCOPY(heurCopyLpface)
    Definition: heur_lpface.c:946
    #define EVENTHDLR_DESC
    Definition: heur_lpface.c:93
    static void updateFailureStatistic(SCIP *scip, SCIP_HEURDATA *heurdata)
    Definition: heur_lpface.c:381
    #define HEUR_FREQ
    Definition: heur_lpface.c:71
    #define HEUR_USESSUBSCIP
    Definition: heur_lpface.c:75
    static SCIP_DECL_HEURFREE(heurFreeLpface)
    Definition: heur_lpface.c:961
    static SCIP_DECL_EVENTEXEC(eventExecLpface)
    Definition: heur_lpface.c:709
    #define EVENTHDLR_NAME
    Definition: heur_lpface.c:92
    static SCIP_DECL_HEURINIT(heurInitLpface)
    Definition: heur_lpface.c:981
    static void subscipdataReset(SUBSCIPDATA *subscipdata)
    Definition: heur_lpface.c:545
    static SCIP_RETCODE setupSubproblem(SCIP *scip, SCIP *subscip, SCIP_VAR **subvars, SCIP_HEURDATA *heurdata)
    Definition: heur_lpface.c:332
    static SCIP_DECL_HEUREXITSOL(heurExitsolLpface)
    Definition: heur_lpface.c:1032
    LNS heuristic that tries to compute integral solution on optimal LP face.
    memory allocation routines
    public methods for managing events
    public methods for primal heuristics
    public methods for LP management
    public methods for message output
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    #define SCIPdebug(x)
    Definition: pub_message.h:93
    public data structures and miscellaneous methods
    public methods for primal CIP solutions
    public methods for branch and bound tree
    public methods for problem variables
    public methods for branching rule plugins and branching
    public methods for constraint handler plugins and constraints
    public methods for problem copies
    public methods for event handler plugins and event handlers
    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 node selector plugins
    public methods for numerical tolerances
    public methods for SCIP parameter handling
    public methods for global and local (sub)problems
    public methods for solutions
    public solving methods
    public methods for querying solving statistics
    public methods for timing
    public methods for the branch-and-bound tree
    public methods for SCIP variables
    default SCIP plugins
    SCIP * subscip
    Definition: heur_lpface.c:102
    SCIP_VAR ** subvars
    Definition: heur_lpface.c:103
    SCIP_Real objbound
    Definition: heur_lpface.c:105
    struct SCIP_EventData SCIP_EVENTDATA
    Definition: type_event.h:179
    #define SCIP_EVENTTYPE_LPSOLVED
    Definition: type_event.h:102
    struct SCIP_HeurData SCIP_HEURDATA
    Definition: type_heur.h:77
    #define SCIP_DECL_HEUREXIT(x)
    Definition: type_heur.h:121
    @ SCIP_BRANCHDIR_DOWNWARDS
    Definition: type_history.h:43
    @ SCIP_BRANCHDIR_UPWARDS
    Definition: type_history.h:44
    @ SCIP_LPSOLSTAT_OPTIMAL
    Definition: type_lp.h:44
    @ SCIP_VERBLEVEL_HIGH
    Definition: type_message.h:61
    @ SCIP_PARAMSETTING_FAST
    Definition: type_paramset.h:62
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_DELAYED
    Definition: type_result.h:43
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_FOUNDSOL
    Definition: type_result.h:56
    enum SCIP_Result SCIP_RESULT
    Definition: type_result.h:61
    @ SCIP_PLUGINNOTFOUND
    Definition: type_retcode.h:54
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_STATUS_UNKNOWN
    Definition: type_stat.h:42
    @ SCIP_STATUS_INFEASIBLE
    Definition: type_stat.h:44
    enum SCIP_Status SCIP_STATUS
    Definition: type_stat.h:64
    @ SCIP_VARSTATUS_COLUMN
    Definition: type_var.h:53