Scippy

    SCIP

    Solving Constraint Integer Programs

    heur_locks.c
    Go to the documentation of this file.
    1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    2/* */
    3/* This file is part of the program and library */
    4/* SCIP --- Solving Constraint Integer Programs */
    5/* */
    6/* Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file heur_locks.c
    26 * @ingroup DEFPLUGINS_HEUR
    27 * @brief rounding locks primal heuristic
    28 * @author Michael Winkler
    29 * @author Gerald Gamrath
    30 */
    31
    32/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    33
    35#include "scip/heur_locks.h"
    36#include "scip/pub_cons.h"
    37#include "scip/pub_heur.h"
    38#include "scip/pub_lp.h"
    39#include "scip/pub_message.h"
    40#include "scip/pub_misc.h"
    41#include "scip/pub_var.h"
    42#include "scip/scip_branch.h"
    44#include "scip/scip_cons.h"
    45#include "scip/scip_copy.h"
    46#include "scip/scip_exact.h"
    47#include "scip/scip_general.h"
    48#include "scip/scip_heur.h"
    49#include "scip/scip_lp.h"
    50#include "scip/scip_mem.h"
    51#include "scip/scip_message.h"
    52#include "scip/scip_numerics.h"
    53#include "scip/scip_param.h"
    54#include "scip/scip_prob.h"
    55#include "scip/scip_probing.h"
    57#include "scip/scip_sol.h"
    58#include "scip/scip_solve.h"
    60#include "scip/scip_timing.h"
    61#include "scip/scip_tree.h"
    62#include <string.h>
    63
    64#define HEUR_NAME "locks"
    65#define HEUR_DESC "heuristic that fixes variables based on their rounding locks"
    66#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_PROP
    67#define HEUR_PRIORITY 3000
    68#define HEUR_FREQ 0
    69#define HEUR_FREQOFS 0
    70#define HEUR_MAXDEPTH -1
    71#define HEUR_TIMING SCIP_HEURTIMING_BEFORENODE
    72#define HEUR_USESSUBSCIP TRUE /**< does the heuristic use a secondary SCIP instance? */
    73
    74#define DEFAULT_MAXNODES 5000LL /**< maximum number of nodes to regard in the subproblem */
    75#define DEFAULT_ROUNDUPPROBABILITY 0.67 /**< probability for rounding a variable up in case of ties */
    76#define DEFAULT_MINFIXINGRATE 0.65 /**< minimum percentage of variables that have to be fixed */
    77#define DEFAULT_MINIMPROVE 0.01 /**< factor by which locks heuristic should at least improve the
    78 * incumbent */
    79#define DEFAULT_MINNODES 500LL /**< minimum number of nodes to regard in the subproblem */
    80#define DEFAULT_NODESOFS 500LL /**< 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_MAXPROPROUNDS 2 /**< maximum number of propagation rounds during probing */
    83#define DEFAULT_UPDATELOCKS TRUE /**< should the locks be updated based on LP rows? */
    84#define DEFAULT_COPYCUTS TRUE /**< should all active cuts from the cutpool of the
    85 * original scip be copied to constraints of the subscip? */
    86#define DEFAULT_USEFINALSUBMIP TRUE /**< should a final sub-MIP be solved to construct a feasible
    87 * solution if the LP was not roundable? */
    88#define DEFAULT_RANDSEED 73 /**< initial random seed */
    89#define DEFAULT_MINFIXINGRATELP 0.0 /**< minimum fixing rate over all variables (including continuous)
    90 * to solve LP */
    91
    92/** primal heuristic data */
    93struct SCIP_HeurData
    94{
    95 SCIP_RANDNUMGEN* randnumgen; /**< random number generation */
    96 SCIP_Longint maxnodes; /**< maximum number of nodes to regard in the subproblem */
    97 SCIP_Longint minnodes; /**< minimum number of nodes to regard in the subproblem */
    98 SCIP_Longint nodesofs; /**< number of nodes added to the contingent of the total nodes */
    99 SCIP_Longint usednodes; /**< nodes already used by locks heuristic in earlier calls */
    100 SCIP_Real roundupprobability; /**< probability for rounding a variable up in case of ties */
    101 SCIP_Real minfixingrate; /**< minimum percentage of variables that have to be fixed */
    102 SCIP_Real minfixingratelp; /**< minimum fixing rate over all variables (including continuous) to solve LP */
    103 SCIP_Real minimprove; /**< factor by which locks heuristic should at least improve the incumbent */
    104 SCIP_Real nodesquot; /**< subproblem nodes in relation to nodes of the original problem */
    105 int maxproprounds; /**< maximum number of propagation rounds during probing */
    106 SCIP_Bool updatelocks; /**< should the locks be updated based on LP rows? */
    107 SCIP_Bool copycuts; /**< should all active cuts from cutpool be copied to constraints in
    108 * the subproblem? */
    109 SCIP_Bool usefinalsubmip; /**< should a final sub-MIP be solved to construct a feasible solution if
    110 * the LP was not roundable? */
    111};
    112
    113/*
    114 * Local methods
    115 */
    116
    117/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
    118static
    119SCIP_DECL_HEURCOPY(heurCopyLocks)
    120{ /*lint --e{715}*/
    121 assert(scip != NULL);
    122 assert(heur != NULL);
    123 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    124
    125 /* call inclusion method of primal heuristic */
    127
    128 return SCIP_OKAY;
    129}
    130
    131/** free method for primal heuristic plugins (called when SCIP is exiting) */
    132static
    133SCIP_DECL_HEURFREE(heurFreeLocks)
    134{ /*lint --e{715}*/
    135 SCIP_HEURDATA* heurdata;
    136
    137 assert(scip != NULL);
    138 assert(heur != NULL);
    139 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    140
    141 heurdata = SCIPheurGetData(heur);
    142
    143 /* free primal heuristic data */
    144 SCIPfreeBlockMemory(scip, &heurdata);
    145
    146 return SCIP_OKAY;
    147}
    148
    149/** initialization method of primal heuristic (called after problem was transformed) */
    150static
    151SCIP_DECL_HEURINIT(heurInitLocks) /*lint --e{715}*/
    152{ /*lint --e{715}*/
    153 SCIP_HEURDATA* heurdata;
    154
    155 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    156 heurdata = SCIPheurGetData(heur);
    157 assert(heurdata != NULL);
    158
    159 /* initialize data */
    160 heurdata->usednodes = 0;
    161
    162 /* create random number generator */
    163 SCIP_CALL( SCIPcreateRandom(scip, &heurdata->randnumgen,
    165
    166 return SCIP_OKAY;
    167}
    168
    169/** deinitialization method of primal heuristic (called before transformed problem is freed) */
    170static
    171SCIP_DECL_HEUREXIT(heurExitLocks) /*lint --e{715}*/
    172{ /*lint --e{715}*/
    173 SCIP_HEURDATA* heurdata;
    174
    175 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    176
    177 /* free heuristic data */
    178 heurdata = SCIPheurGetData(heur);
    179 assert(heurdata != NULL);
    180
    181 /* free random number generator */
    182 SCIPfreeRandom(scip, &heurdata->randnumgen);
    183
    184 return SCIP_OKAY;
    185}
    186
    187/** apply fix-and-propagate scheme based on variable locks
    188 *
    189 * @note probing mode of SCIP needs to be enabled before
    190 */
    192 SCIP* scip, /**< SCIP data structure */
    193 SCIP_HEURDATA* heurdata, /**< primal heuristic data */
    194 SCIP_Bool* cutoff, /**< pointer to store if a cutoff was detected */
    195 SCIP_Bool* allrowsfulfilled /**< pointer to store if all rows became redundant */
    196 )
    197{
    198 SCIP_ROW** lprows;
    199 SCIP_VAR** vars;
    200 SCIP_VAR** sortvars;
    201 SCIP_Real* minact;
    202 SCIP_Real* maxact;
    203 SCIP_Bool* fulfilled;
    204 SCIP_VAR* var;
    205 SCIP_ROW* row;
    206 SCIP_COL* col;
    207 SCIP_ROW** colrows;
    208 SCIP_Real* colvals;
    209 int ncolrows;
    210 int* ndownlocks;
    211 int* nuplocks;
    212 int* varpos = NULL;
    213 SCIP_Real lastfixval;
    214 SCIP_Real randnumber;
    215 SCIP_Real roundupprobability;
    216 SCIP_Bool propagate;
    217 SCIP_Bool propagated;
    218 SCIP_Bool haslhs;
    219 SCIP_Bool hasrhs;
    220 SCIP_Bool updatelocks;
    221 int lastfixlocks;
    222 int maxproprounds;
    223 int nglbfulfilledrows;
    224 int rowpos;
    225 int nbinvars;
    226 int nvars;
    227 int nlprows;
    228 int nfulfilledrows;
    229 int bestpos;
    230 int lastbestscore;
    231 int bestscore;
    232 int score;
    233 int v;
    234 int r;
    235 int i;
    236
    237 assert(scip != NULL);
    238 assert(cutoff != NULL);
    239 assert(allrowsfulfilled != NULL);
    240 assert(SCIPinProbing(scip));
    241
    242 if( heurdata == NULL )
    243 {
    245 heurdata = SCIPheurGetData(heur);
    246 }
    247 assert(heurdata != NULL);
    248
    249 *cutoff = FALSE;
    250 *allrowsfulfilled = FALSE;
    251
    252 propagate = (heurdata->maxproprounds != 0);
    253
    254 if( heurdata->maxproprounds == -2 )
    255 maxproprounds = 0;
    256 else
    257 maxproprounds = heurdata->maxproprounds;
    258
    259 roundupprobability = heurdata->roundupprobability;
    260
    261 updatelocks = heurdata->updatelocks && (SCIPgetNCheckConss(scip) == SCIPgetNLPRows(scip));
    262
    263 SCIPdebugMsg(scip, "%d constraints: %d logicor, updatelocks=%u\n", SCIPgetNConss(scip), SCIPconshdlrGetNCheckConss(SCIPfindConshdlr(scip, "logicor")), updatelocks);
    264
    265 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, NULL, NULL, NULL) );
    266 assert(vars != NULL);
    267
    268 /* allocate memory */
    269 SCIP_CALL( SCIPduplicateBufferArray(scip, &sortvars, vars, nbinvars) );
    270 SCIP_CALL( SCIPallocBufferArray(scip, &nuplocks, nbinvars) );
    271 SCIP_CALL( SCIPallocBufferArray(scip, &ndownlocks, nbinvars) );
    272
    273 /* get LP data */
    274 SCIP_CALL( SCIPgetLPRowsData(scip, &lprows, &nlprows) );
    275 SCIP_CALL( SCIPallocBufferArray(scip, &minact, nlprows) );
    276 SCIP_CALL( SCIPallocBufferArray(scip, &maxact, nlprows) );
    277 SCIP_CALL( SCIPallocClearBufferArray(scip, &fulfilled, nlprows) );
    278
    279 /* @todo add objective value as second sorting criteria */
    280
    281 nglbfulfilledrows = 0;
    282
    283 /* get locks of variables */
    284 for( v = 0; v < nbinvars; ++v )
    285 {
    286 var = sortvars[v];
    288 ndownlocks[v] = SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL);
    289 }
    290
    291 /* get activities of rows */
    292 for( r = 0; r < nlprows; ++r )
    293 {
    294 row = lprows[r];
    295 assert(SCIProwGetLPPos(row) == r);
    296
    297 /* no trivial rows */
    299
    300 minact[r] = SCIPgetRowMinActivity(scip, row);
    301 maxact[r] = SCIPgetRowMaxActivity(scip, row);
    302 }
    303
    304 propagated = TRUE;
    305 lastbestscore = INT_MAX;
    306
    307 /* fix variables */
    308 for( v = 0; v < nbinvars; v++ )
    309 {
    310 if( SCIPisStopped(scip) )
    311 break;
    312
    313 assert(!(*cutoff));
    314
    315 nfulfilledrows = 0;
    316
    317 while( v < nbinvars && (SCIPvarGetLbLocal(sortvars[v]) > 0.5 || SCIPvarGetUbLocal(sortvars[v]) < 0.5) )
    318 {
    319 ++v;
    320 }
    321 if( v == nbinvars )
    322 break;
    323
    324 bestpos = v;
    325 bestscore = nuplocks[v] + ndownlocks[v];
    326
    327 /* get best variable */
    328 if( bestscore < lastbestscore )
    329 {
    330 for( i = v + 1; i < nbinvars; ++i )
    331 {
    332 var = sortvars[i];
    333
    334 /* variable is already fixed; move it to the front and increment v to ignore it */
    335 if( SCIPvarGetLbLocal(var) > 0.5 || SCIPvarGetUbLocal(var) < 0.5 )
    336 {
    337 int locks;
    338
    339 sortvars[i] = sortvars[v];
    340 sortvars[v] = var;
    341
    342 locks = nuplocks[i];
    343 nuplocks[i] = nuplocks[v];
    344 nuplocks[v] = locks;
    345
    346 locks = ndownlocks[i];
    347 ndownlocks[i] = ndownlocks[v];
    348 ndownlocks[v] = locks;
    349
    350 if( varpos != NULL )
    351 {
    352 varpos[SCIPvarGetProbindex(sortvars[i])] = i;
    353 varpos[SCIPvarGetProbindex(sortvars[v])] = v;
    354 }
    355
    356 if( bestpos == v )
    357 bestpos = i;
    358
    359 ++v;
    360
    361 continue;
    362 }
    363
    364 score = nuplocks[i] + ndownlocks[i];
    365 assert(score <= lastbestscore);
    366
    367 if( score > bestscore )
    368 {
    369 bestscore = score;
    370 bestpos = i;
    371
    372 if( bestscore == lastbestscore )
    373 break;
    374 }
    375 }
    376 if( v == nbinvars )
    377 break;
    378 }
    379 lastbestscore = bestscore;
    380
    381 /* move best variable to the front (at position v) */
    382 if( bestpos != v )
    383 {
    384 int locks;
    385
    386 var = sortvars[bestpos];
    387 sortvars[bestpos] = sortvars[v];
    388 sortvars[v] = var;
    389
    390 locks = nuplocks[bestpos];
    391 nuplocks[bestpos] = nuplocks[v];
    392 nuplocks[v] = locks;
    393
    394 locks = ndownlocks[bestpos];
    395 ndownlocks[bestpos] = ndownlocks[v];
    396 ndownlocks[v] = locks;
    397
    398 if( varpos != NULL )
    399 {
    400 varpos[SCIPvarGetProbindex(sortvars[bestpos])] = bestpos;
    401 varpos[SCIPvarGetProbindex(sortvars[v])] = v;
    402 }
    403 }
    404
    405 var = sortvars[v];
    406
    407 /* all remaining variables are fixed, we can break the fix-and-propagate loop */
    408 if( SCIPvarGetLbLocal(var) > 0.5 || SCIPvarGetUbLocal(var) < 0.5 )
    409 {
    410 assert(v == nbinvars);
    411
    412 break;
    413 }
    414
    415 /* stop if we reached the depth limit */
    417 break;
    418
    419 if( propagated )
    420 {
    422 propagated = FALSE;
    423 }
    424
    425 /* set variables to the bound with fewer locks, if tie choose an average value */
    426 if( ndownlocks[v] > nuplocks[v] )
    427 lastfixval = 1.0;
    428 else if( ndownlocks[v] < nuplocks[v] )
    429 lastfixval = 0.0;
    430 else
    431 {
    432 /* prefer one-fixing if objective value is not positive */
    433 if( !SCIPisPositive(scip, SCIPvarGetObj(var)) )
    434 lastfixval = 1.0;
    435 else
    436 {
    437 randnumber = SCIPrandomGetReal(heurdata->randnumgen, 0.0, 1.0);
    438
    439 /* if a tie occurs, we randomly round the variable based on the parameter 'roundupprobability' */
    440 if( randnumber < roundupprobability )
    441 lastfixval = 1.0;
    442 else
    443 lastfixval = 0.0;
    444 }
    445 }
    446
    447 lastfixlocks = lastfixval > 0.5 ? nuplocks[v] : ndownlocks[v];
    448
    449 SCIP_CALL( SCIPfixVarProbing(scip, var, lastfixval) );
    450
    451 SCIPdebugMsg(scip, "iteration %d: fixing variable <%s> to %d with locks (%d, %d)\n", v, SCIPvarGetName(var), lastfixval > 0.5 ? 1 : 0, ndownlocks[v], nuplocks[v]);
    452
    453 if( propagate && lastfixlocks > 0 )
    454 {
    455 /* apply propagation */
    456 SCIP_CALL( SCIPpropagateProbing(scip, maxproprounds, cutoff, NULL) );
    457 propagated = TRUE;
    458
    459 if( *cutoff )
    460 {
    461 SCIPdebugMsg(scip, "last fixing led to infeasibility trying other bound\n");
    462
    463 /* fix cutoff variable in other direction */
    465 *cutoff = FALSE;
    466
    467 if( lastfixval < 0.5 )
    468 {
    469 lastfixval = 1.0;
    470
    471 if( SCIPvarGetUbLocal(var) > 0.5 )
    472 {
    473 SCIP_CALL( SCIPfixVarProbing(scip, var, 1.0) );
    474 }
    475 /* because of the limited number of propagation rounds, it may happen that conflict analysis finds a
    476 * valid global fixing for the last fixed variable that conflicts with applying the reverse fixing
    477 * after backtracking; in that case, we ran into a deadend and stop
    478 */
    479 else
    480 *cutoff = TRUE;
    481 }
    482 else
    483 {
    484 lastfixval = 0.0;
    485
    486 if( SCIPvarGetLbLocal(var) < 0.5 )
    487 {
    488 SCIP_CALL( SCIPfixVarProbing(scip, var, 0.0) );
    489 }
    490 /* because of the limited number of propagation rounds, it may happen that conflict analysis finds a
    491 * valid global fixing for the last fixed variable that conflicts with applying the reverse fixing
    492 * after backtracking; in that case, we ran into a deadend and stop
    493 */
    494 else
    495 *cutoff = TRUE;
    496 }
    497
    498 if( !(*cutoff) )
    499 {
    500 SCIP_CALL( SCIPpropagateProbing(scip, maxproprounds, cutoff, NULL) );
    501 }
    502 if( *cutoff )
    503 {
    504 SCIPdebugMsg(scip, "probing was infeasible\n");
    505
    506 break;
    507 }
    508 }
    509 /* @todo collect propagated bounds and use them to update row activities as well */
    510 }
    511
    512 if( updatelocks )
    513 {
    515 continue;
    516
    517 col = SCIPvarGetCol(var);
    518 assert(col != NULL);
    519
    520 colrows = SCIPcolGetRows(col);
    521 colvals = SCIPcolGetVals(col);
    522 ncolrows = SCIPcolGetNNonz(col);
    523
    524 /* update activities */
    525 for( r = 0; r < ncolrows; ++r )
    526 {
    527 row = colrows[r];
    528 rowpos = SCIProwGetLPPos(row);
    529
    530 /* the row is not in the LP */
    531 if( rowpos == -1 )
    532 continue;
    533
    534 assert(lprows[rowpos] == row);
    535
    536 /* we disregard cuts */
    537 if( SCIProwGetRank(row) > 0 )
    538 continue;
    539
    540 /* the row is already fulfilled */
    541 if( fulfilled[rowpos] )
    542 continue;
    543
    544 haslhs = !SCIPisInfinity(scip, -SCIProwGetLhs(row));
    545 hasrhs = !SCIPisInfinity(scip, SCIProwGetRhs(row));
    546
    547 /* no trivial rows */
    548 assert(hasrhs || haslhs);
    549
    550 if( ((colvals[r] > 0) == (lastfixval < 0.5)) )
    551 {
    552 maxact[rowpos] -= REALABS(colvals[r]);
    553 }
    554 if( ((colvals[r] > 0) == (lastfixval > 0.5)) )
    555 {
    556 minact[rowpos] += REALABS(colvals[r]);
    557 }
    558
    559 /* check if the row cannot be violated anymore */
    560 if( (!haslhs || SCIPisFeasGE(scip, minact[rowpos], SCIProwGetLhs(row)))
    561 && (!hasrhs || SCIPisFeasLE(scip, maxact[rowpos], SCIProwGetRhs(row))) )
    562 {
    563 SCIP_COL** cols;
    564 SCIP_VAR* colvar;
    565 SCIP_Real* vals;
    566 int ncols;
    567 int pos;
    568 int w;
    569
    570 SCIPdebugMsg(scip, "Row <%s> has activity [%g, %g], lhs=%g, rhs=%g\n", SCIProwGetName(row), minact[rowpos], maxact[rowpos], SCIProwGetLhs(row), SCIProwGetRhs(row));
    572
    573 if( varpos == NULL )
    574 {
    575 SCIP_CALL( SCIPallocBufferArray(scip, &varpos, nbinvars) );
    576
    577 for( pos = 0; pos < nbinvars; ++pos )
    578 varpos[SCIPvarGetProbindex(sortvars[pos])] = pos;
    579 }
    580
    581 ++nfulfilledrows;
    582 fulfilled[rowpos] = TRUE;
    583 cols = SCIProwGetCols(row);
    584 vals = SCIProwGetVals(row);
    585 ncols = SCIProwGetNNonz(row);
    586
    587 /* we assume that all rows are locking the variables */
    588 for( w = ncols - 1; w >= 0; --w )
    589 {
    590 colvar = SCIPcolGetVar(cols[w]);
    591 if( SCIPvarGetType(colvar) == SCIP_VARTYPE_BINARY && !SCIPvarIsImpliedIntegral(colvar) && colvar != var )
    592 {
    593 assert(sortvars[varpos[SCIPvarGetProbindex(colvar)]] == colvar);
    594 pos = varpos[SCIPvarGetProbindex(colvar)];
    595
    596 if( haslhs )
    597 {
    598 if( vals[w] > 0.0 )
    599 --(ndownlocks[pos]);
    600 else
    601 --(nuplocks[pos]);
    602 }
    603 if( hasrhs )
    604 {
    605 if( vals[w] > 0.0 )
    606 --(nuplocks[pos]);
    607 else
    608 --(ndownlocks[pos]);
    609 }
    610 }
    611 }
    612
    613 continue;
    614 }
    615 else if( SCIPisFeasLT(scip, maxact[rowpos], SCIProwGetLhs(row)) || SCIPisFeasGT(scip, minact[rowpos], SCIProwGetRhs(row)) )
    616 {
    617 *cutoff = TRUE;
    618 break;
    619 }
    620 }
    621
    622 if( *cutoff )
    623 {
    624 SCIPdebugMsg(scip, "found infeasible row, stopping heur\n");
    625 break;
    626 }
    627
    628 nglbfulfilledrows += nfulfilledrows;
    629 SCIPdebugMsg(scip, "last fixing led to %d fulfilled rows, now %d of %d rows are fulfilled\n", nfulfilledrows, nglbfulfilledrows, nlprows);
    630
    631 if( nglbfulfilledrows == nlprows )
    632 {
    633 *allrowsfulfilled = TRUE;
    634 break;
    635 }
    636 }
    637 } /*lint --e{850}*/
    638
    640 SCIPfreeBufferArray(scip, &fulfilled);
    641 SCIPfreeBufferArray(scip, &maxact);
    642 SCIPfreeBufferArray(scip, &minact);
    643 SCIPfreeBufferArray(scip, &ndownlocks);
    644 SCIPfreeBufferArray(scip, &nuplocks);
    645 SCIPfreeBufferArray(scip, &sortvars);
    646
    647 return SCIP_OKAY;
    648}
    649
    650
    651
    652
    653/** execution method of primal heuristic */
    654static
    655SCIP_DECL_HEUREXEC(heurExecLocks)
    656{ /*lint --e{715}*/
    657 SCIP_HEURDATA* heurdata;
    658 SCIP_VAR** vars;
    660 SCIP_Real lowerbound;
    661 SCIP_Bool cutoff;
    662 SCIP_Bool lperror;
    663 SCIP_Bool allrowsfulfilled = FALSE;
    664#ifdef NOCONFLICT
    665 SCIP_Bool enabledconflicts;
    666#endif
    667 int oldnpscands;
    668 int npscands;
    669
    670 int nvars;
    671 int i;
    672
    673 *result = SCIP_DIDNOTRUN;
    674
    675 /* only run once */
    676 if( SCIPgetNRuns(scip) > 1 )
    677 return SCIP_OKAY;
    678
    679 if( SCIPgetNBinVars(scip) == 0 )
    680 return SCIP_OKAY;
    681
    682 /* only run if we are allowed to solve an LP at the current node in the tree */
    684 return SCIP_OKAY;
    685
    687 {
    688 SCIP_CALL( SCIPconstructLP(scip, &cutoff) );
    689
    690 /* manually cut off the node if the LP construction detected infeasibility (heuristics cannot return such a
    691 * result); the cutoff result is safe to use in exact solving mode, but we don't have enough information to
    692 * give a certificate for the cutoff
    693 */
    694 if( cutoff && !SCIPisCertified(scip) )
    695 {
    697 return SCIP_OKAY;
    698 }
    699
    701
    702 /* we need an LP */
    703 if( SCIPgetNLPRows(scip) == 0 )
    704 return SCIP_OKAY;
    705 }
    706
    707 *result = SCIP_DIDNOTFIND;
    708
    709 heurdata = SCIPheurGetData(heur);
    710 assert(heurdata != NULL);
    711
    712#ifdef NOCONFLICT
    713 /* disable conflict analysis */
    714 SCIP_CALL( SCIPgetBoolParam(scip, "conflict/enable", &enabledconflicts) );
    715
    716 if( !SCIPisParamFixed(scip, "conflict/enable") )
    717 {
    718 SCIP_CALL( SCIPsetBoolParam(scip, "conflict/enable", FALSE) );
    719 }
    720#endif
    721
    722 lowerbound = SCIPgetLowerbound(scip);
    723 oldnpscands = SCIPgetNPseudoBranchCands(scip);
    724
    725 /* start probing mode */
    727
    728#ifdef COLLECTSTATISTICS
    730#endif
    731
    732 cutoff = FALSE;
    733 lperror = FALSE;
    734
    735 SCIP_CALL( SCIPapplyLockFixings(scip, heurdata, &cutoff, &allrowsfulfilled) );
    736
    737 if( cutoff || SCIPisStopped(scip) )
    738 goto TERMINATE;
    739
    740 /* check that we had enough fixings */
    742
    743 SCIPdebugMsg(scip, "npscands=%d, oldnpscands=%d, allrowsfulfilled=%u heurdata->minfixingrate=%g\n",
    744 npscands, oldnpscands, allrowsfulfilled, heurdata->minfixingrate);
    745
    746 if( !allrowsfulfilled && npscands > oldnpscands * (1 - heurdata->minfixingrate) )
    747 {
    748 SCIPdebugMsg(scip, "--> too few fixings\n");
    749
    750 goto TERMINATE;
    751 }
    752 else
    753 {
    754 char strbuf[SCIP_MAXSTRLEN];
    755 int ncols;
    756
    757 if( SCIPgetNContVars(scip) > 0 )
    758 {
    759 int nminfixings;
    760 int nfixedvars = 0;
    761
    762 nvars = SCIPgetNVars(scip);
    763 vars = SCIPgetVars(scip);
    764 nminfixings = (int)(SCIPceil(scip, heurdata->minfixingratelp * nvars));
    765
    766 /* count fixed variables */
    767 for( i = 0; i < nvars && nfixedvars < nminfixings; ++i )
    768 {
    769 if( SCIPisEQ(scip, SCIPvarGetLbLocal(vars[i]), SCIPvarGetUbLocal(vars[i])) )
    770 ++nfixedvars;
    771 }
    772
    773 SCIPdebugMsg(scip, "Fixed %d of %d (%.1f %%) variables after probing -> %s\n",
    774 nfixedvars, nvars, (100.0 * nfixedvars / (SCIP_Real)nvars),
    775 nfixedvars >= nminfixings ? "continue and solve LP for remaining variables" : "terminate without LP");
    776
    777 if( nfixedvars < nminfixings )
    778 goto TERMINATE;
    779 }
    780
    781 /* print message if relatively large LP is solved from scratch, since this could lead to a longer period during
    782 * which the user sees no output; more detailed probing stats only in debug mode */
    783 ncols = SCIPgetNLPCols(scip);
    784 if( !SCIPisLPSolBasic(scip) && ncols > 1000 )
    785 {
    786 int nunfixedcols = SCIPgetNUnfixedLPCols(scip);
    787
    788 if( nunfixedcols > 0.5 * ncols )
    789 {
    791 "Heuristic " HEUR_NAME " solving LP from scratch with %.1f %% unfixed columns (%d of %d) ...\n",
    792 100.0 * (nunfixedcols / (SCIP_Real)ncols), nunfixedcols, ncols);
    793 }
    794 }
    795 SCIPdebugMsg(scip, "Heuristic " HEUR_NAME " probing LP: %s\n",
    797
    798 /* solve LP;
    799 * errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
    800 * hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
    801 */
    802 SCIPdebugMsg(scip, "starting solving locks-lp at time %g\n", SCIPgetSolvingTime(scip));
    803#ifdef NDEBUG
    804 {
    805 SCIP_Bool retstat;
    806 retstat = SCIPsolveProbingLP(scip, -1, &lperror, &cutoff);
    807 if( retstat != SCIP_OKAY )
    808 {
    809 SCIPwarningMessage(scip, "Error while solving LP in LOCKS heuristic; LP solve terminated with code <%d>\n",
    810 retstat);
    811 }
    812 }
    813#else
    814 SCIP_CALL( SCIPsolveProbingLP(scip, -1, &lperror, &cutoff) );
    815#endif
    816 SCIPdebugMsg(scip, "ending solving locks-lp at time %g\n", SCIPgetSolvingTime(scip));
    817
    818 lpstatus = SCIPgetLPSolstat(scip);
    819
    820 SCIPdebugMsg(scip, " -> new LP iterations: %" SCIP_LONGINT_FORMAT "\n", SCIPgetNLPIterations(scip));
    821 SCIPdebugMsg(scip, " -> error=%u, status=%d\n", lperror, SCIPgetLPSolstat(scip));
    822
    823 /* check if this is a feasible solution */
    824 if( !lperror && lpstatus == SCIP_LPSOLSTAT_OPTIMAL )
    825 {
    826 SCIP_SOL* sol;
    827 SCIP_Bool success;
    828
    829 lowerbound = SCIPgetLPObjval(scip);
    830
    831 /* create a copy of the current LP solution */
    832 SCIP_CALL( SCIPcreateSol(scip, &sol, heur) );
    834
    835 SCIP_CALL( SCIProundSol(scip, sol, &success) );
    836
    837 if( success )
    838 {
    839 SCIP_Bool stored;
    840
    841 /* check solution for feasibility, and add it to solution store if possible.
    842 * Neither integrality nor feasibility of LP rows have to be checked, because they
    843 * are guaranteed by the heuristic at this stage.
    844 */
    845 SCIP_CALL( SCIPtrySol(scip, sol, FALSE, FALSE, FALSE, FALSE, FALSE, &stored) );
    846
    847 if( stored )
    848 {
    849#ifdef SCIP_MORE_DEBUG
    850 SCIP_Bool feasible;
    851 SCIP_CALL( SCIPcheckSol(scip, sol, TRUE, TRUE, TRUE, TRUE, TRUE, &feasible) );
    852 assert(feasible);
    853#endif
    854
    855 SCIPdebugMsg(scip, "found feasible solution:\n");
    857 *result = SCIP_FOUNDSOL;
    858 }
    859
    860 SCIP_CALL( SCIPfreeSol(scip, &sol) );
    861
    862 /* we found a solution, so we are done */
    863 goto TERMINATE;
    864 }
    865
    866 SCIP_CALL( SCIPfreeSol(scip, &sol) );
    867 }
    868 }
    869
    870 if( heurdata->usefinalsubmip && !cutoff && !lperror && lpstatus != SCIP_LPSOLSTAT_INFEASIBLE && lpstatus != SCIP_LPSOLSTAT_OBJLIMIT )
    871 {
    872 SCIP* subscip;
    873 SCIP_VAR** subvars;
    874 SCIP_HASHMAP* varmap;
    875 SCIP_Longint nstallnodes;
    876 SCIP_Bool valid;
    877
    878 /* calculate the maximal number of branching nodes until heuristic is aborted */
    879 nstallnodes = (SCIP_Longint)(heurdata->nodesquot * SCIPgetNNodes(scip));
    880
    881 /* reward locks heuristic if it succeeded often */
    882 nstallnodes = (SCIP_Longint)(nstallnodes * 3.0 * (SCIPheurGetNBestSolsFound(heur)+1.0)/(SCIPheurGetNCalls(heur) + 1.0));
    883 nstallnodes -= 100 * SCIPheurGetNCalls(heur); /* count the setup costs for the sub-MIP as 100 nodes */
    884 nstallnodes += heurdata->nodesofs;
    885
    886 /* determine the node limit for the current process */
    887 nstallnodes -= heurdata->usednodes;
    888 nstallnodes = MIN(nstallnodes, heurdata->maxnodes);
    889
    890 /* check whether we have enough nodes left to call subproblem solving */
    891 if( nstallnodes < heurdata->minnodes )
    892 {
    893 SCIPdebugMsg(scip, "skipping " HEUR_NAME ": nstallnodes=%" SCIP_LONGINT_FORMAT ", minnodes=%" SCIP_LONGINT_FORMAT "\n", nstallnodes, heurdata->minnodes);
    894 goto TERMINATE;
    895 }
    896
    897 /* check whether there is enough time and memory left */
    899
    900 if( !valid )
    901 goto TERMINATE;
    902
    903 /* get all variables */
    904 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
    905
    906 /* create subproblem */
    907 SCIP_CALL( SCIPcreate(&subscip) );
    908
    909 /* allocate temporary memory for subscip variables */
    910 SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
    911
    912 /* create the variable mapping hash map */
    913 SCIP_CALL( SCIPhashmapCreate(&varmap, SCIPblkmem(subscip), nvars) );
    914
    915 SCIP_CALL( SCIPcopy(scip, subscip, varmap, NULL, "_locks", FALSE, FALSE, FALSE, TRUE, &valid) );
    916
    917 if( heurdata->copycuts )
    918 {
    919 /* copies all active cuts from cutpool of sourcescip to linear constraints in targetscip */
    920 SCIP_CALL( SCIPcopyCuts(scip, subscip, varmap, NULL, FALSE, NULL) );
    921 }
    922
    923 for( i = 0; i < nvars; i++ )
    924 subvars[i] = (SCIP_VAR*) SCIPhashmapGetImage(varmap, vars[i]);
    925
    926 /* free hash map */
    927 SCIPhashmapFree(&varmap);
    928
    929 /* do not abort subproblem on CTRL-C */
    930 SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
    931
    932#ifdef SCIP_DEBUG
    933 /* for debugging, enable full output */
    934 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) );
    935 SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 100000000) );
    936#else
    937 /* disable statistic timing inside sub SCIP and output to console */
    938 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
    939 SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
    940#endif
    941
    942 /* set limits for the subproblem */
    943 SCIP_CALL( SCIPcopyLimits(scip, subscip) );
    944 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/stallnodes", nstallnodes) );
    945 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", heurdata->maxnodes) );
    946
    947 /* forbid call of heuristics and separators solving sub-CIPs */
    948 SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );
    949
    950 /* disable cutting plane separation */
    952
    953 /* disable expensive presolving */
    955
    956 /* use inference branching */
    957 if( SCIPfindBranchrule(subscip, "inference") != NULL && !SCIPisParamFixed(subscip, "branching/inference/priority") )
    958 {
    959 SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
    960 }
    961
    962 /* speed up sub-SCIP by not checking dual LP feasibility */
    963 SCIP_CALL( SCIPsetBoolParam(subscip, "lp/checkdualfeas", FALSE) );
    964
    965 /* if there is already a solution, add an objective cutoff */
    966 if( SCIPgetNSols(scip) > 0 )
    967 {
    968 SCIP_Real upperbound;
    969 SCIP_Real minimprove;
    970 SCIP_Real cutoffbound;
    971
    972 minimprove = heurdata->minimprove;
    974
    975 upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);
    976
    977 if( !SCIPisInfinity(scip, -1.0 * lowerbound) )
    978 {
    979 cutoffbound = (1-minimprove) * SCIPgetUpperbound(scip) + minimprove * lowerbound;
    980 }
    981 else
    982 {
    983 if( SCIPgetUpperbound ( scip ) >= 0 )
    984 cutoffbound = (1 - minimprove) * SCIPgetUpperbound(scip);
    985 else
    986 cutoffbound = (1 + minimprove) * SCIPgetUpperbound(scip);
    987 }
    988 cutoffbound = MIN(upperbound, cutoffbound);
    989 SCIP_CALL( SCIPsetObjlimit(subscip, cutoffbound) );
    990 SCIPdebugMsg(scip, "setting objlimit for subscip to %g\n", cutoffbound);
    991 }
    992
    993 SCIPdebugMsg(scip, "starting solving locks-submip at time %g\n", SCIPgetSolvingTime(scip));
    994
    995 /* solve the subproblem */
    996 /* Errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
    997 * Hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
    998 */
    999#ifdef NDEBUG
    1000 {
    1001 SCIP_RETCODE retstat;
    1002 retstat = SCIPpresolve(subscip);
    1003 if( retstat != SCIP_OKAY )
    1004 {
    1005 SCIPwarningMessage(scip, "Error while presolving subMIP in locks heuristic; sub-SCIP terminated with code <%d>\n", retstat);
    1006
    1007 goto FREESCIPANDTERMINATE;
    1008 }
    1009 }
    1010#else
    1011 SCIP_CALL_ABORT( SCIPpresolve(subscip) );
    1012#endif
    1013
    1014 SCIPdebugMsg(scip, "locks heuristic presolved subproblem at time %g : %d vars, %d cons; fixing value = %g\n", SCIPgetSolvingTime(scip), SCIPgetNVars(subscip), SCIPgetNConss(subscip), ((nvars - SCIPgetNVars(subscip)) / (SCIP_Real)nvars));
    1015
    1016 /* after presolving, we should have at least reached a certain fixing rate over ALL variables (including continuous)
    1017 * to ensure that not only the MIP but also the LP relaxation is easy enough
    1018 */
    1019 if( ((nvars - SCIPgetNVars(subscip)) / (SCIP_Real)nvars) >= heurdata->minfixingrate )
    1020 {
    1021 SCIP_Bool success;
    1022
    1023 SCIPdebugMsg(scip, "solving subproblem: nstallnodes=%" SCIP_LONGINT_FORMAT ", maxnodes=%" SCIP_LONGINT_FORMAT "\n", nstallnodes, heurdata->maxnodes);
    1024
    1025#ifdef NDEBUG
    1026 {
    1027 SCIP_RETCODE retstat;
    1028 retstat = SCIPsolve(subscip);
    1029 if( retstat != SCIP_OKAY )
    1030 {
    1031 SCIPwarningMessage(scip, "Error while solving subMIP in locks heuristic; sub-SCIP terminated with code <%d>\n",retstat);
    1032
    1033 goto FREESCIPANDTERMINATE;
    1034 }
    1035 }
    1036#else
    1037 SCIP_CALL_ABORT( SCIPsolve(subscip) );
    1038#endif
    1039 SCIPdebugMsg(scip, "ending solving locks-submip at time %g, status = %d\n", SCIPgetSolvingTime(scip), SCIPgetStatus(subscip));
    1040
    1041 /* check, whether a solution was found; due to numerics, it might happen that not all solutions are feasible ->
    1042 * try all solutions until one was accepted
    1043 */
    1044 SCIP_CALL( SCIPtranslateSubSols(scip, subscip, heur, subvars, &success, NULL) );
    1045 if( success )
    1046 *result = SCIP_FOUNDSOL;
    1047 }
    1048
    1049#ifdef SCIP_DEBUG
    1050 SCIP_CALL( SCIPprintStatistics(subscip, NULL) );
    1051#endif
    1052
    1053 heurdata->usednodes += SCIPgetNNodes(subscip);
    1054#ifdef NDEBUG
    1055 FREESCIPANDTERMINATE:
    1056#endif
    1057 /* free subproblem */
    1058 SCIPfreeBufferArray(scip, &subvars);
    1059 SCIP_CALL( SCIPfree(&subscip) );
    1060 }
    1061
    1062 TERMINATE:
    1063 /* exit probing mode */
    1065
    1066#ifdef NOCONFLICT
    1067 /* reset the conflict analysis */
    1068 if( !SCIPisParamFixed(scip, "conflict/enable") )
    1069 {
    1070 SCIP_CALL( SCIPsetBoolParam(scip, "conflict/enable", enabledconflicts) );
    1071 }
    1072#endif
    1073
    1074 return SCIP_OKAY;
    1075}
    1076
    1077
    1078/*
    1079 * primal heuristic specific interface methods
    1080 */
    1081
    1082/** creates the locks primal heuristic and includes it in SCIP */
    1084 SCIP* scip /**< SCIP data structure */
    1085 )
    1086{
    1087 SCIP_HEURDATA* heurdata;
    1088 SCIP_HEUR* heur;
    1089
    1090 /* create primal heuristic data */
    1091 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    1092
    1093 /* include primal heuristic */
    1096 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecLocks, heurdata) );
    1097
    1098 assert(heur != NULL);
    1099
    1100 /* primal heuristic is safe to use in exact solving mode */
    1101 SCIPheurMarkExact(heur);
    1102
    1103 /* set non-NULL pointers to callback methods */
    1104 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyLocks) );
    1105 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeLocks) );
    1106 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitLocks) );
    1107 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitLocks) );
    1108
    1109 /* add locks primal heuristic parameters */
    1110 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxproprounds",
    1111 "maximum number of propagation rounds to be performed in each propagation call (-1: no limit, -2: parameter settings)",
    1112 &heurdata->maxproprounds, TRUE, DEFAULT_MAXPROPROUNDS, -2, INT_MAX, NULL, NULL) );
    1113
    1114 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minfixingrate",
    1115 "minimum percentage of integer variables that have to be fixable",
    1116 &heurdata->minfixingrate, FALSE, DEFAULT_MINFIXINGRATE, 0.0, 1.0, NULL, NULL) );
    1117
    1118 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/roundupprobability",
    1119 "probability for rounding a variable up in case of ties",
    1120 &heurdata->roundupprobability, FALSE, DEFAULT_ROUNDUPPROBABILITY, 0.0, 1.0, NULL, NULL) );
    1121
    1122 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/usefinalsubmip",
    1123 "should a final sub-MIP be solved to costruct a feasible solution if the LP was not roundable?",
    1124 &heurdata->usefinalsubmip, TRUE, DEFAULT_USEFINALSUBMIP, NULL, NULL) );
    1125
    1126 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
    1127 "maximum number of nodes to regard in the subproblem",
    1128 &heurdata->maxnodes, TRUE, DEFAULT_MAXNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
    1129
    1130 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/nodesofs",
    1131 "number of nodes added to the contingent of the total nodes",
    1132 &heurdata->nodesofs, FALSE, DEFAULT_NODESOFS, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
    1133
    1134 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/minnodes",
    1135 "minimum number of nodes required to start the subproblem",
    1136 &heurdata->minnodes, TRUE, DEFAULT_MINNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
    1137
    1138 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesquot",
    1139 "contingent of sub problem nodes in relation to the number of nodes of the original problem",
    1140 &heurdata->nodesquot, FALSE, DEFAULT_NODESQUOT, 0.0, 1.0, NULL, NULL) );
    1141
    1142 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprove",
    1143 "factor by which " HEUR_NAME " heuristic should at least improve the incumbent",
    1144 &heurdata->minimprove, TRUE, DEFAULT_MINIMPROVE, 0.0, 1.0, NULL, NULL) );
    1145
    1146 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/copycuts",
    1147 "should all active cuts from cutpool be copied to constraints in subproblem?",
    1148 &heurdata->copycuts, TRUE, DEFAULT_COPYCUTS, NULL, NULL) );
    1149
    1150 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/updatelocks",
    1151 "should the locks be updated based on LP rows?",
    1152 &heurdata->updatelocks, TRUE, DEFAULT_UPDATELOCKS, NULL, NULL) );
    1153
    1154 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minfixingratelp",
    1155 "minimum fixing rate over all variables (including continuous) to solve LP",
    1156 &heurdata->minfixingratelp, TRUE, DEFAULT_MINFIXINGRATELP, 0.0, 1.0, NULL, NULL) );
    1157
    1158 return SCIP_OKAY;
    1159}
    SCIP_VAR * w
    Definition: circlepacking.c:67
    SCIP_Real * r
    Definition: circlepacking.c:59
    #define NULL
    Definition: def.h:248
    #define SCIP_MAXSTRLEN
    Definition: def.h:269
    #define SCIP_Longint
    Definition: def.h:141
    #define SCIP_MAXTREEDEPTH
    Definition: def.h:297
    #define SCIP_Bool
    Definition: def.h:91
    #define MIN(x, y)
    Definition: def.h:224
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define SCIP_CALL_ABORT(x)
    Definition: def.h:334
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:148
    #define REALABS(x)
    Definition: def.h:182
    #define SCIP_LONGINT_MAX
    Definition: def.h:142
    #define SCIP_CALL(x)
    Definition: def.h:355
    SCIP_RETCODE SCIPtranslateSubSols(SCIP *scip, SCIP *subscip, SCIP_HEUR *heur, SCIP_VAR **subvars, SCIP_Bool *success, int *solindex)
    Definition: scip_copy.c:1437
    SCIP_RETCODE SCIPcopy(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, const char *suffix, SCIP_Bool global, SCIP_Bool enablepricing, SCIP_Bool threadsafe, SCIP_Bool passmessagehdlr, SCIP_Bool *valid)
    Definition: scip_copy.c:2865
    SCIP_RETCODE SCIPcheckCopyLimits(SCIP *sourcescip, SCIP_Bool *success)
    Definition: scip_copy.c:3249
    SCIP_RETCODE SCIPcopyCuts(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, int *ncutsadded)
    Definition: scip_copy.c:2113
    SCIP_RETCODE SCIPcopyLimits(SCIP *sourcescip, SCIP *targetscip)
    Definition: scip_copy.c:3292
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:759
    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 SCIPgetNContVars(SCIP *scip)
    Definition: scip_prob.c:2569
    int SCIPgetNCheckConss(SCIP *scip)
    Definition: scip_prob.c:3762
    SCIP_RETCODE SCIPsetObjlimit(SCIP *scip, SCIP_Real objlimit)
    Definition: scip_prob.c:1661
    SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
    Definition: scip_prob.c:2115
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    int SCIPgetNConss(SCIP *scip)
    Definition: scip_prob.c:3620
    SCIP_VAR ** SCIPgetVars(SCIP *scip)
    Definition: scip_prob.c:2201
    int SCIPgetNBinVars(SCIP *scip)
    Definition: scip_prob.c:2293
    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
    void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:225
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
    Definition: scip_message.c:120
    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 SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:83
    SCIP_RETCODE SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
    Definition: scip_param.c:545
    SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:139
    SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
    Definition: scip_param.c:487
    SCIP_RETCODE SCIPsetSubscipsOff(SCIP *scip, SCIP_Bool quiet)
    Definition: scip_param.c:904
    SCIP_RETCODE SCIPsetPresolving(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
    Definition: scip_param.c:956
    SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:57
    SCIP_RETCODE SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
    Definition: scip_param.c:429
    SCIP_RETCODE SCIPsetSeparating(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
    Definition: scip_param.c:985
    SCIP_RETCODE SCIPincludeHeurLocks(SCIP *scip)
    Definition: heur_locks.c:1083
    SCIP_BRANCHRULE * SCIPfindBranchrule(SCIP *scip, const char *name)
    Definition: scip_branch.c:304
    int SCIPgetNPseudoBranchCands(SCIP *scip)
    Definition: scip_branch.c:766
    SCIP_Bool SCIPisCertified(SCIP *scip)
    SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
    Definition: lp.c:17425
    int SCIPcolGetNNonz(SCIP_COL *col)
    Definition: lp.c:17520
    SCIP_Real * SCIPcolGetVals(SCIP_COL *col)
    Definition: lp.c:17555
    SCIP_ROW ** SCIPcolGetRows(SCIP_COL *col)
    Definition: lp.c:17545
    int SCIPconshdlrGetNCheckConss(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4798
    SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
    Definition: scip_cons.c:940
    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
    SCIP_HEUR * SCIPfindHeur(SCIP *scip, const char *name)
    Definition: scip_heur.c:263
    void SCIPheurMarkExact(SCIP_HEUR *heur)
    Definition: heur.c:1457
    SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
    Definition: scip_heur.c:199
    const char * SCIPheurGetName(SCIP_HEUR *heur)
    Definition: heur.c:1467
    SCIP_RETCODE SCIPflushLP(SCIP *scip)
    Definition: scip_lp.c:154
    SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
    Definition: scip_lp.c:87
    SCIP_RETCODE SCIPconstructLP(SCIP *scip, SCIP_Bool *cutoff)
    Definition: scip_lp.c:130
    SCIP_Bool SCIPisLPConstructed(SCIP *scip)
    Definition: scip_lp.c:105
    SCIP_RETCODE SCIPgetLPRowsData(SCIP *scip, SCIP_ROW ***rows, int *nrows)
    Definition: scip_lp.c:576
    int SCIPgetNLPRows(SCIP *scip)
    Definition: scip_lp.c:632
    SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
    Definition: scip_lp.c:174
    SCIP_Real SCIPgetLPObjval(SCIP *scip)
    Definition: scip_lp.c:253
    int SCIPgetNUnfixedLPCols(SCIP *scip)
    Definition: scip_lp.c:554
    int SCIPgetNLPCols(SCIP *scip)
    Definition: scip_lp.c:533
    SCIP_Bool SCIPisLPSolBasic(SCIP *scip)
    Definition: scip_lp.c:673
    BMS_BLKMEM * SCIPblkmem(SCIP *scip)
    Definition: scip_mem.c:57
    #define SCIPallocClearBufferArray(scip, ptr, num)
    Definition: scip_mem.h:126
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPduplicateBufferArray(scip, ptr, source, num)
    Definition: scip_mem.h:132
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPfreeBufferArrayNull(scip, ptr)
    Definition: scip_mem.h:137
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    int SCIPgetProbingDepth(SCIP *scip)
    Definition: scip_probing.c:199
    char * SCIPsnprintfProbingStats(SCIP *scip, char *strbuf, int len)
    SCIP_RETCODE SCIPpropagateProbing(SCIP *scip, int maxproprounds, SCIP_Bool *cutoff, SCIP_Longint *ndomredsfound)
    Definition: scip_probing.c:581
    SCIP_RETCODE SCIPbacktrackProbing(SCIP *scip, int probingdepth)
    Definition: scip_probing.c:226
    SCIP_Bool SCIPinProbing(SCIP *scip)
    Definition: scip_probing.c:98
    SCIP_RETCODE SCIPstartProbing(SCIP *scip)
    Definition: scip_probing.c:120
    SCIP_RETCODE SCIPnewProbingNode(SCIP *scip)
    Definition: scip_probing.c:166
    SCIP_RETCODE SCIPsolveProbingLP(SCIP *scip, int itlim, SCIP_Bool *lperror, SCIP_Bool *cutoff)
    Definition: scip_probing.c:825
    SCIP_RETCODE SCIPfixVarProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval)
    Definition: scip_probing.c:419
    SCIP_RETCODE SCIPendProbing(SCIP *scip)
    Definition: scip_probing.c:261
    SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
    Definition: lp.c:17686
    SCIP_Real SCIPgetRowMinActivity(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:1903
    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_Real SCIPgetRowMaxActivity(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:1920
    int SCIProwGetLPPos(SCIP_ROW *row)
    Definition: lp.c:17895
    SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
    Definition: scip_lp.c:2176
    const char * SCIProwGetName(SCIP_ROW *row)
    Definition: lp.c:17745
    int SCIProwGetRank(SCIP_ROW *row)
    Definition: lp.c:17775
    SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
    Definition: lp.c:17642
    SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:516
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1252
    SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
    Definition: scip_sol.c:2349
    int SCIPgetNSols(SCIP *scip)
    Definition: scip_sol.c:2882
    SCIP_RETCODE SCIProundSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool *success)
    Definition: scip_sol.c:3123
    SCIP_RETCODE SCIPtrySol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
    Definition: scip_sol.c:4012
    SCIP_RETCODE SCIPcheckSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *feasible)
    Definition: scip_sol.c:4312
    SCIP_RETCODE SCIPlinkLPSol(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1295
    SCIP_RETCODE SCIPpresolve(SCIP *scip)
    Definition: scip_solve.c:2449
    SCIP_RETCODE SCIPsolve(SCIP *scip)
    Definition: scip_solve.c:2635
    SCIP_Real SCIPgetUpperbound(SCIP *scip)
    SCIP_Longint SCIPgetNNodes(SCIP *scip)
    SCIP_RETCODE SCIPprintStatistics(SCIP *scip, FILE *file)
    SCIP_Real SCIPgetLowerbound(SCIP *scip)
    int SCIPgetNRuns(SCIP *scip)
    SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
    SCIP_Real SCIPgetSolvingTime(SCIP *scip)
    Definition: scip_timing.c:378
    SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPsumepsilon(SCIP *scip)
    int SCIPgetDepth(SCIP *scip)
    Definition: scip_tree.c:672
    SCIP_RETCODE SCIPcutoffNode(SCIP *scip, SCIP_NODE *node)
    Definition: scip_tree.c:436
    SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
    Definition: scip_tree.c:91
    SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
    Definition: var.c:23683
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23386
    int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4386
    SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
    Definition: var.c:23498
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24268
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23900
    SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
    Definition: var.c:23453
    int SCIPvarGetProbindex(SCIP_VAR *var)
    Definition: var.c:23662
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24234
    int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4328
    void SCIPenableVarHistory(SCIP *scip)
    Definition: scip_var.c:11083
    void SCIPfreeRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen)
    SCIP_Real SCIPrandomGetReal(SCIP_RANDNUMGEN *randnumgen, SCIP_Real minrandval, SCIP_Real maxrandval)
    Definition: misc.c:10245
    SCIP_RETCODE SCIPcreateRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen, unsigned int initialseed, SCIP_Bool useglobalseed)
    #define DEFAULT_NODESQUOT
    Definition: heur_locks.c:81
    static SCIP_DECL_HEUREXEC(heurExecLocks)
    Definition: heur_locks.c:655
    static SCIP_DECL_HEURFREE(heurFreeLocks)
    Definition: heur_locks.c:133
    static SCIP_DECL_HEUREXIT(heurExitLocks)
    Definition: heur_locks.c:171
    #define DEFAULT_NODESOFS
    Definition: heur_locks.c:80
    #define DEFAULT_MINFIXINGRATELP
    Definition: heur_locks.c:89
    #define DEFAULT_COPYCUTS
    Definition: heur_locks.c:84
    #define DEFAULT_MAXNODES
    Definition: heur_locks.c:74
    #define DEFAULT_ROUNDUPPROBABILITY
    Definition: heur_locks.c:75
    #define HEUR_TIMING
    Definition: heur_locks.c:71
    #define DEFAULT_MINNODES
    Definition: heur_locks.c:79
    static SCIP_DECL_HEURINIT(heurInitLocks)
    Definition: heur_locks.c:151
    static SCIP_DECL_HEURCOPY(heurCopyLocks)
    Definition: heur_locks.c:119
    #define HEUR_FREQOFS
    Definition: heur_locks.c:69
    #define HEUR_DESC
    Definition: heur_locks.c:65
    #define DEFAULT_MINFIXINGRATE
    Definition: heur_locks.c:76
    SCIP_RETCODE SCIPapplyLockFixings(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_Bool *cutoff, SCIP_Bool *allrowsfulfilled)
    Definition: heur_locks.c:191
    #define HEUR_DISPCHAR
    Definition: heur_locks.c:66
    #define HEUR_MAXDEPTH
    Definition: heur_locks.c:70
    #define HEUR_PRIORITY
    Definition: heur_locks.c:67
    #define DEFAULT_MINIMPROVE
    Definition: heur_locks.c:77
    #define HEUR_NAME
    Definition: heur_locks.c:64
    #define DEFAULT_UPDATELOCKS
    Definition: heur_locks.c:83
    #define DEFAULT_RANDSEED
    Definition: heur_locks.c:88
    #define DEFAULT_USEFINALSUBMIP
    Definition: heur_locks.c:86
    #define HEUR_FREQ
    Definition: heur_locks.c:68
    #define HEUR_USESSUBSCIP
    Definition: heur_locks.c:72
    #define DEFAULT_MAXPROPROUNDS
    Definition: heur_locks.c:82
    locks primal heuristic
    memory allocation routines
    public methods for managing constraints
    public methods for primal heuristics
    public methods for LP management
    public methods for message output
    #define SCIPdebug(x)
    Definition: pub_message.h:93
    public data structures and miscellaneous methods
    public methods for problem variables
    public methods for branching rule plugins and branching
    public methods for certified solving
    public methods for constraint handler plugins and constraints
    public methods for problem copies
    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 the probing mode
    public methods for random numbers
    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
    struct SCIP_HeurData SCIP_HEURDATA
    Definition: type_heur.h:77
    enum SCIP_LPSolStat SCIP_LPSOLSTAT
    Definition: type_lp.h:52
    @ SCIP_LPSOLSTAT_ERROR
    Definition: type_lp.h:50
    @ SCIP_LPSOLSTAT_OPTIMAL
    Definition: type_lp.h:44
    @ SCIP_LPSOLSTAT_INFEASIBLE
    Definition: type_lp.h:45
    @ SCIP_LPSOLSTAT_OBJLIMIT
    Definition: type_lp.h:47
    @ SCIP_VERBLEVEL_FULL
    Definition: type_message.h:62
    @ SCIP_PARAMSETTING_OFF
    Definition: type_paramset.h:63
    @ SCIP_PARAMSETTING_FAST
    Definition: type_paramset.h:62
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_FOUNDSOL
    Definition: type_result.h:56
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_VARTYPE_BINARY
    Definition: type_var.h:64
    @ SCIP_VARSTATUS_COLUMN
    Definition: type_var.h:53
    @ SCIP_LOCKTYPE_MODEL
    Definition: type_var.h:141