Scippy

    SCIP

    Solving Constraint Integer Programs

    heur_vbounds.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_vbounds.c
    26 * @ingroup DEFPLUGINS_HEUR
    27 * @brief LNS heuristic uses the variable lower and upper bounds to determine the search neighborhood
    28 * @author Timo Berthold
    29 * @author Stefan Heinz
    30 * @author Jens Schulz
    31 * @author Gerald Gamrath
    32 *
    33 * @todo allow smaller fixing rate for probing LP?
    34 * @todo allow smaller fixing rate after presolve if total number of variables is small (<= 1000)?
    35 *
    36 * More details about the heuristic can be found in@n
    37 * Structure-Based Primal Heuristics for Mixed Integer Programming@n
    38 * Gerald Gamrath, Timo Berthold, Stefan Heinz, and Michael Winkler@n
    39 * Optimization in the Real World, Volume 13 of the series Mathematics for Industry, pp 37-53@n
    40 * Preliminary version available as <a href="https://opus4.kobv.de/opus4-zib/frontdoor/index/index/docId/5551">ZIB-Report 15-26</a>.
    41 */
    42
    43/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    44
    46#include "scip/heur_locks.h"
    47#include "scip/heur_vbounds.h"
    48#include "scip/pub_heur.h"
    49#include "scip/pub_implics.h"
    50#include "scip/pub_message.h"
    51#include "scip/pub_misc.h"
    52#include "scip/pub_tree.h"
    53#include "scip/pub_var.h"
    54#include "scip/scip_branch.h"
    56#include "scip/scip_cons.h"
    57#include "scip/scip_copy.h"
    58#include "scip/scip_exact.h"
    59#include "scip/scip_general.h"
    60#include "scip/scip_heur.h"
    61#include "scip/scip_lp.h"
    62#include "scip/scip_mem.h"
    63#include "scip/scip_message.h"
    64#include "scip/scip_numerics.h"
    65#include "scip/scip_param.h"
    66#include "scip/scip_prob.h"
    67#include "scip/scip_probing.h"
    68#include "scip/scip_sol.h"
    69#include "scip/scip_solve.h"
    71#include "scip/scip_timing.h"
    72#include "scip/scip_tree.h"
    73#include "scip/scip_var.h"
    74#include <string.h>
    75
    76#ifdef SCIP_STATISTIC
    77#include "scip/clock.h"
    78#endif
    79
    80#define VBOUNDVARIANT_NOOBJ 0x001u
    81#define VBOUNDVARIANT_BESTBOUND 0x002u
    82#define VBOUNDVARIANT_WORSTBOUND 0x004u
    83
    84#define HEUR_NAME "vbounds"
    85#define HEUR_DESC "LNS heuristic uses the variable lower and upper bounds to determine the search neighborhood"
    86#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_PROP
    87#define HEUR_PRIORITY 2500
    88#define HEUR_FREQ 0
    89#define HEUR_FREQOFS 0
    90#define HEUR_MAXDEPTH -1
    91#define HEUR_TIMING SCIP_HEURTIMING_BEFORENODE
    92#define HEUR_USESSUBSCIP TRUE /**< does the heuristic use a secondary SCIP instance? */
    93
    94#define DEFAULT_MAXNODES 5000LL /**< maximum number of nodes to regard in the subproblem */
    95#define DEFAULT_MININTFIXINGRATE 0.65 /**< minimum percentage of integer variables that have to be fixed */
    96#define DEFAULT_MINMIPFIXINGRATE 0.65 /**< minimuskipobjm percentage of variables that have to be fixed within sub-SCIP
    97 * (integer and continuous) */
    98#define DEFAULT_MINIMPROVE 0.01 /**< factor by which vbounds heuristic should at least improve the
    99 * incumbent */
    100#define DEFAULT_MINNODES 500LL /**< minimum number of nodes to regard in the subproblem */
    101#define DEFAULT_NODESOFS 500LL /**< number of nodes added to the contingent of the total nodes */
    102#define DEFAULT_NODESQUOT 0.1 /**< subproblem nodes in relation to nodes of the original problem */
    103#define DEFAULT_MAXPROPROUNDS 2 /**< maximum number of propagation rounds during probing */
    104#define DEFAULT_MAXBACKTRACKS 10 /**< maximum number of backtracks during the fixing process */
    105#define DEFAULT_COPYCUTS TRUE /**< should all active cuts from the cutpool of the original scip be copied to
    106 * constraints of the subscip? */
    107#define DEFAULT_USELOCKFIXINGS FALSE /**< should more variables be fixed based on variable locks if
    108 * the fixing rate was not reached?
    109 */
    110
    111/** which variants of the vbounds heuristic that try to stay feasible should be called? */
    112#define DEFAULT_FEASVARIANT (VBOUNDVARIANT_BESTBOUND | VBOUNDVARIANT_WORSTBOUND)
    113
    114/** which tightening variants of the vbounds heuristic should be called? */
    115#define DEFAULT_TIGHTENVARIANT (VBOUNDVARIANT_NOOBJ | VBOUNDVARIANT_BESTBOUND | VBOUNDVARIANT_WORSTBOUND)
    116
    117
    118/*
    119 * Data structures
    120 */
    121
    122/** primal heuristic data */
    123struct SCIP_HeurData
    124{
    125 SCIP_VAR** vbvars; /**< topological sorted variables with respect to the variable bounds */
    126 SCIP_BOUNDTYPE* vbbounds; /**< topological sorted variables with respect to the variable bounds */
    127 int nvbvars; /**< number of variables in variable lower bound array */
    128 SCIP_Longint maxnodes; /**< maximum number of nodes to regard in the subproblem */
    129 SCIP_Longint minnodes; /**< minimum number of nodes to regard in the subproblem */
    130 SCIP_Longint nodesofs; /**< number of nodes added to the contingent of the total nodes */
    131 SCIP_Longint usednodes; /**< nodes already used by vbounds heuristic in earlier calls */
    132 SCIP_Real minintfixingrate; /**< minimum percentage of integer variables that have to be fixed */
    133 SCIP_Real minmipfixingrate; /**< minimum percentage of variables that have to be fixed within sub-SCIP
    134 * (integer and continuous) */
    135 SCIP_Real minimprove; /**< factor by which vbounds heuristic should at least improve the incumbent */
    136 SCIP_Real nodesquot; /**< subproblem nodes in relation to nodes of the original problem */
    137 SCIP_Real cutoffbound;
    138 int maxproprounds; /**< maximum number of propagation rounds during probing */
    139 int maxbacktracks; /**< maximum number of backtracks during the fixing process */
    140 int feasvariant; /**< which variants of the vbounds heuristic that try to stay feasible
    141 * should be called? */
    142 int tightenvariant; /**< which tightening variants of the vbounds heuristic should be called? */
    143 SCIP_Bool initialized; /**< is the candidate list initialized? */
    144 SCIP_Bool applicable; /**< is the heuristic applicable? */
    145 SCIP_Bool copycuts; /**< should all active cuts from cutpool be copied to constraints in
    146 * subproblem? */
    147 SCIP_Bool uselockfixings; /**< should more variables be fixed based on variable locks if
    148 * the fixing rate was not reached? */
    149};
    150
    151/**@name Heuristic defines
    152 *
    153 * @{
    154 *
    155 * The heuristic works on indices representing a bound of a variable. This index will be called bound index in the
    156 * following. For a given active variable with problem index i (note that active variables have problem indices
    157 * between 0 and nactivevariable - 1), the bound index of its lower bound is 2*i, the bound index of its upper
    158 * bound is 2*i + 1. The other way around, a given bound index i corresponds to the variable with problem index
    159 * i/2 (rounded down), and to the lower bound, if i is even, to the upper bound if i is odd.
    160 * The following macros can be used to convert bound index into variable problem index and boundtype and vice versa.
    161 */
    162#define getLbIndex(idx) (2*(idx))
    163#define getUbIndex(idx) (2*(idx)+1)
    164#define getVarIndex(idx) ((idx)/2)
    165#define getBoundtype(idx) (((idx) % 2 == 0) ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER)
    166#define isIndexLowerbound(idx) ((idx) % 2 == 0)
    167#define getOtherBoundIndex(idx) (((idx) % 2 == 0) ? (idx) + 1 : (idx) - 1)
    168
    169
    170/*
    171 * Local methods
    172 */
    173
    174/** reset heuristic data structure */
    175static
    177 SCIP_HEURDATA* heurdata /**< structure containing heurdata */
    178 )
    179{
    180 heurdata->vbvars = NULL;
    181 heurdata->vbbounds = NULL;
    182 heurdata->nvbvars = 0;
    183 heurdata->initialized = FALSE;
    184 heurdata->applicable = FALSE;
    185}
    186
    187
    188/** performs depth-first-search in the implicitly given directed graph from the given start index */
    189static
    191 SCIP* scip, /**< SCIP data structure */
    192 int startnode, /**< node to start the depth-first-search */
    193 SCIP_Shortbool* visited, /**< array to store for each node, whether it was already visited */
    194 int* dfsstack, /**< array of size number of nodes to store the stack;
    195 * only needed for performance reasons */
    196 int* stacknextedge, /**< array of size number of nodes to store the number of adjacent nodes
    197 * already visited for each node on the stack; only needed for
    198 * performance reasons */
    199 int* stacknextcliquevar, /**< array of size number of nodes to store the number of variables
    200 * already evaluated for the clique currently being evaluated */
    201 int* cliqueexit, /**< exit node when entering a clique */
    202 int* dfsnodes, /**< array of nodes that can be reached starting at startnode, in reverse
    203 * dfs order */
    204 int* ndfsnodes /**< pointer to store number of nodes that can be reached starting at
    205 * startnode */
    206 )
    207{
    208 SCIP_VAR** vars;
    209 SCIP_VAR* startvar;
    210 SCIP_VAR** vbvars;
    211 SCIP_Real* coefs;
    212 SCIP_Bool lower;
    213 SCIP_Bool found;
    214 int maxstacksize;
    215 int stacksize;
    216 int curridx;
    217 int idx;
    218 int nvbvars;
    219 int i;
    220
    221 assert(startnode >= 0);
    222 assert(startnode < 2 * SCIPgetNVars(scip));
    223 assert(visited != NULL);
    224 assert(visited[startnode] == FALSE);
    225 assert(dfsstack != NULL);
    226 assert(dfsnodes != NULL);
    227 assert(ndfsnodes != NULL);
    228
    229 vars = SCIPgetVars(scip);
    230
    231 /* put start node on the stack */
    232 dfsstack[0] = startnode;
    233 stacknextcliquevar[0] = 0;
    234 stacknextedge[0] = 0;
    235 maxstacksize = 1;
    236 stacksize = 1;
    237 idx = -1;
    238
    239 /* we run until no more bounds indices are on the stack */
    240 while( stacksize > 0 )
    241 {
    242 /* get next node from stack */
    243 curridx = dfsstack[stacksize - 1];
    244
    245 /* mark current node as visited */
    246 assert(visited[curridx] == (stacknextedge[stacksize - 1] != 0));
    247 visited[curridx] = TRUE;
    248 found = FALSE;
    249
    250 startvar = vars[getVarIndex(curridx)];
    251 lower = isIndexLowerbound(curridx);
    252
    253 if( stacknextedge[stacksize - 1] >= 0 )
    254 {
    255 /* go over edges corresponding to varbounds */
    256 if( lower )
    257 {
    258 vbvars = SCIPvarGetVlbVars(startvar);
    259 coefs = SCIPvarGetVlbCoefs(startvar);
    260 nvbvars = SCIPvarGetNVlbs(startvar);
    261 }
    262 else
    263 {
    264 vbvars = SCIPvarGetVubVars(startvar);
    265 coefs = SCIPvarGetVubCoefs(startvar);
    266 nvbvars = SCIPvarGetNVubs(startvar);
    267 }
    268
    269 /* iterate over all vbounds for the given bound */
    270 for( i = stacknextedge[stacksize - 1]; i < nvbvars; ++i )
    271 {
    272 if( !SCIPvarIsActive(vbvars[i]) )
    273 continue;
    274
    275 idx = (SCIPisPositive(scip, coefs[i]) == lower) ? getLbIndex(SCIPvarGetProbindex(vbvars[i])) : getUbIndex(SCIPvarGetProbindex(vbvars[i]));
    276 assert(idx >= 0);
    277
    278 /* break when the first unvisited node is reached */
    279 if( !visited[idx] )
    280 break;
    281 }
    282
    283 /* we stopped because we found an unhandled node and not because we reached the end of the list */
    284 if( i < nvbvars )
    285 {
    286 assert(!visited[idx]);
    287
    288 /* put the adjacent node onto the stack */
    289 dfsstack[stacksize] = idx;
    290 stacknextedge[stacksize] = 0;
    291 stacknextcliquevar[stacksize] = 0;
    292 stacknextedge[stacksize - 1] = i + 1;
    293 stacksize++;
    294 assert(stacksize <= 2* SCIPgetNVars(scip));
    295
    296 /* restart while loop, get next index from stack */
    297 continue;
    298 }
    299 }
    300
    301 stacknextedge[stacksize - 1] = -1;
    302
    303 /* treat cliques */
    304 if( SCIPvarIsBinary(startvar) )
    305 {
    306 SCIP_CLIQUE** cliques = SCIPvarGetCliques(startvar, !lower);
    307 int ncliques = SCIPvarGetNCliques(startvar, !lower);
    308 int j;
    309
    310 /* iterate over all not yet handled cliques and search for an unvisited node */
    311 for( j = -stacknextedge[stacksize - 1] - 1; j < ncliques; ++j )
    312 {
    313 SCIP_VAR** cliquevars;
    314 SCIP_Bool* cliquevals;
    315 int ncliquevars;
    316
    317 /* the first time we evaluate this clique for the current node */
    318 if( stacknextcliquevar[stacksize - 1] == 0 )
    319 {
    320 if( cliqueexit[SCIPcliqueGetIndex(cliques[j])] > 0 )
    321 {
    322 if( !visited[cliqueexit[SCIPcliqueGetIndex(cliques[j])] - 1] &&
    323 cliqueexit[SCIPcliqueGetIndex(cliques[j])] - 1 != curridx )
    324 {
    325 stacknextedge[stacksize - 1] = -j - 2;
    326 stacknextcliquevar[stacksize - 1] = 0;
    327 idx = cliqueexit[SCIPcliqueGetIndex(cliques[j])] - 1;
    328 cliqueexit[SCIPcliqueGetIndex(cliques[j])] = -1;
    329 found = TRUE;
    330 }
    331 else
    332 continue;
    333 }
    334 else if( cliqueexit[SCIPcliqueGetIndex(cliques[j])] == 0 )
    335 {
    336 cliqueexit[SCIPcliqueGetIndex(cliques[j])] = getOtherBoundIndex(curridx) + 1;
    337 }
    338 else
    339 continue;
    340 }
    341 if( !found )
    342 {
    343 cliquevars = SCIPcliqueGetVars(cliques[j]);
    344 cliquevals = SCIPcliqueGetValues(cliques[j]);
    345 ncliquevars = SCIPcliqueGetNVars(cliques[j]);
    346
    347 for( i = 0; i < ncliquevars; ++i )
    348 {
    349 assert(SCIPvarIsActive(cliquevars[i]));
    350
    351 if( cliquevars[i] == startvar )
    352 continue;
    353
    354 if( cliquevals[i] )
    355 idx = getLbIndex(SCIPvarGetProbindex(cliquevars[i]));
    356 else
    357 idx = getUbIndex(SCIPvarGetProbindex(cliquevars[i]));
    358
    359 assert(idx >= 0 && idx < 2 * SCIPgetNVars(scip));
    360
    361 /* break when the first unvisited node is reached */
    362 if( idx >= 0 && !visited[idx] )
    363 {
    364 if( i < ncliquevars - 1 )
    365 {
    366 stacknextedge[stacksize - 1] = -j - 1;
    367 stacknextcliquevar[stacksize - 1] = i + 1;
    368 }
    369 else
    370 {
    371 stacknextedge[stacksize - 1] = -j - 2;
    372 stacknextcliquevar[stacksize - 1] = 0;
    373 }
    374 found = TRUE;
    375 break;
    376 }
    377 }
    378 }
    379 if( found )
    380 {
    381 assert(!visited[idx]);
    382
    383 /* put the adjacent node onto the stack */
    384 dfsstack[stacksize] = idx;
    385 stacknextedge[stacksize] = 0;
    386 stacknextcliquevar[stacksize] = 0;
    387 stacksize++;
    388 assert(stacksize <= 2* SCIPgetNVars(scip));
    389
    390 break;
    391 }
    392 }
    393 /* restart while loop, get next index from stack */
    394 if( found )
    395 continue;
    396 }
    397
    398 maxstacksize = MAX(maxstacksize, stacksize);
    399
    400 /* the current node was completely handled, remove it from the stack */
    401 stacksize--;
    402
    403 if( maxstacksize > 1 && SCIPvarIsIntegral(startvar) )
    404 {
    405 /* store node in the sorted nodes array */
    406 dfsnodes[(*ndfsnodes)] = curridx;
    407 (*ndfsnodes)++;
    408 }
    409 else
    410 visited[curridx] = FALSE;
    411 }
    412
    413 return SCIP_OKAY;
    414}
    415
    416
    417/** sort the bounds of variables topologically */
    418static
    420 SCIP* scip, /**< SCIP data structure */
    421 int* vbvars, /**< array to store variable bounds in topological order */
    422 int* nvbvars /**< pointer to store number of variable bounds in the graph */
    423 )
    424{
    425 int* dfsstack;
    426 int* stacknextedge;
    427 int* stacknextcliquevar;
    428 int* cliqueexit;
    429 SCIP_Shortbool* visited;
    430 int nbounds;
    431 int i;
    432
    433 assert(scip != NULL);
    434
    435 nbounds = 2 * SCIPgetNVars(scip);
    436
    437 SCIP_CALL( SCIPallocBufferArray(scip, &dfsstack, nbounds) );
    438 SCIP_CALL( SCIPallocBufferArray(scip, &stacknextedge, nbounds) );
    439 SCIP_CALL( SCIPallocBufferArray(scip, &stacknextcliquevar, nbounds) );
    441 SCIP_CALL( SCIPallocClearBufferArray(scip, &visited, nbounds) );
    442
    443 /* while there are unvisited nodes, run dfs on the inverse graph starting from one of these nodes; the dfs orders are
    444 * stored in the topoorder array, later dfs calls are just appended after the stacks of previous dfs calls, which
    445 * gives us a topological order
    446 */
    447 for( i = 0; i < nbounds; ++i )
    448 {
    449 if( !visited[i] )
    450 {
    451 SCIP_CALL( dfs(scip, i, visited, dfsstack, stacknextedge, stacknextcliquevar, cliqueexit, vbvars, nvbvars) );
    452 }
    453 }
    454 assert(*nvbvars <= nbounds);
    455
    456 SCIPfreeBufferArray(scip, &visited);
    457 SCIPfreeBufferArray(scip, &cliqueexit);
    458 SCIPfreeBufferArray(scip, &stacknextcliquevar);
    459 SCIPfreeBufferArray(scip, &stacknextedge);
    460 SCIPfreeBufferArray(scip, &dfsstack);
    461
    462 return SCIP_OKAY;
    463}
    464
    465/** initialize candidate lists */
    466static
    468 SCIP* scip, /**< original SCIP data structure */
    469 SCIP_HEURDATA* heurdata /**< structure containing heurdata */
    470 )
    471{
    472 SCIP_VAR** vars;
    473 int* vbs;
    474 int nvars;
    475 int nvbs;
    476 int v;
    477
    478 SCIPdebugMsg(scip, "initialize variable bound heuristic (%s)\n", SCIPgetProbName(scip));
    479
    480 vars = SCIPgetVars(scip);
    482 nvbs = 0;
    483
    484 /* initialize data */
    485 heurdata->usednodes = 0;
    486 heurdata->initialized = TRUE;
    487
    488 if( nvars == 0 )
    489 return SCIP_OKAY;
    490
    491 /* allocate memory for the arrays of the heurdata */
    492 SCIP_CALL( SCIPallocBufferArray(scip, &vbs, 2 * nvars) );
    493
    494 /* create the topological sorted variable array with respect to the variable bounds */
    495 SCIP_CALL( topologicalSort(scip, vbs, &nvbs) );
    496
    497 /* check if the candidate list contains enough candidates */
    498 if( nvbs > 0 && nvbs >= 0.1 * heurdata->minintfixingrate * nvars )
    499 {
    500 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &heurdata->vbvars, nvbs) );
    501 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &heurdata->vbbounds, nvbs) );
    502
    503 /* capture variable candidate list */
    504 for( v = 0; v < nvbs; ++v )
    505 {
    506 heurdata->vbvars[v] = vars[getVarIndex(vbs[v])];
    507 heurdata->vbbounds[v] = getBoundtype(vbs[v]);
    508 assert(SCIPvarIsIntegral(heurdata->vbvars[v]));
    509
    510 SCIP_CALL( SCIPcaptureVar(scip, heurdata->vbvars[v]) );
    511 }
    512
    513 heurdata->nvbvars = nvbs;
    514 heurdata->applicable = TRUE;
    515 }
    516
    517 /* free buffer arrays */
    519
    520 SCIPstatisticMessage("vbvars %.3g (%s)\n",
    521 (nvbs * 100.0) / nvars, SCIPgetProbName(scip));
    522
    523 /* if there is already a solution, add an objective cutoff */
    524 if( SCIPgetNSols(scip) > 0 )
    525 {
    526 SCIP_Real upperbound;
    527 SCIP_Real minimprove;
    528 SCIP_Real cutoffbound;
    529
    530 minimprove = heurdata->minimprove;
    531
    533 upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);
    534
    536 {
    537 cutoffbound = (1-minimprove) * SCIPgetUpperbound(scip) + minimprove * SCIPgetLowerbound(scip);
    538 }
    539 else
    540 {
    541 if( SCIPgetUpperbound ( scip ) >= 0 )
    542 cutoffbound = (1 - minimprove) * SCIPgetUpperbound(scip);
    543 else
    544 cutoffbound = (1 + minimprove) * SCIPgetUpperbound(scip);
    545 }
    546 heurdata->cutoffbound = MIN(upperbound, cutoffbound);
    547 }
    548 else
    549 heurdata->cutoffbound = SCIPinfinity(scip);
    550 return SCIP_OKAY;
    551}
    552
    553/** apply variable bound fixing during probing */
    554static
    556 SCIP* scip, /**< original SCIP data structure */
    557 SCIP_HEURDATA* heurdata, /**< structure containing heurdata */
    558 SCIP_VAR** vars, /**< variables to fix during probing */
    559 int nvbvars, /**< number of variables in the variable bound graph */
    560 SCIP_Bool tighten, /**< should variables be fixed to cause other fixings? */
    561 int obj, /**< should the objective be taken into account? */
    562 SCIP_Bool* allobj1, /**< pointer to store whether all variables were fixed according to obj=1 scheme */
    563 SCIP_Bool* allobj2, /**< pointer to store whether all variables were fixed according to obj=2 scheme */
    564 SCIP_Bool* backtracked, /**< was backtracking performed at least once? */
    565 SCIP_Bool* infeasible /**< pointer to store whether propagation detected infeasibility */
    566 )
    567{
    568 SCIP_VAR* lastvar;
    569 SCIP_VAR* var;
    570 SCIP_Real lastfixval;
    571 SCIP_Bool lastfixedlb;
    572 SCIP_Bool fixtolower;
    574 int nbacktracks = 0;
    575 int v;
    576
    577 /* loop over variables in topological order */
    578 for( v = 0; v < nvbvars && !(*infeasible); ++v )
    579 {
    580 var = vars[v];
    581 bound = heurdata->vbbounds[v];
    582
    583 /*SCIPdebugMsg(scip, "topoorder[%d]: %s(%s) (%s) [%g,%g] (obj=%g)\n", v,
    584 bound == SCIP_BOUNDTYPE_UPPER ? "ub" : "lb", SCIPvarGetName(var),
    585 SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS ? "c" : "d",
    586 SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), SCIPvarGetObj(var));*/
    587
    588 /* only check integer or binary variables */
    589 if( !SCIPvarIsIntegral(var) )
    590 continue;
    591
    592 /* skip variables which are already fixed */
    593 if( SCIPvarGetLbLocal(var) + 0.5 > SCIPvarGetUbLocal(var) )
    594 continue;
    595
    596 /* there are two cases for tighten:
    597 * 1) tighten == TRUE: we go through the list of variables and fix variables to force propagation;
    598 * this is be obtained by fixing the variable to the other bound (which means
    599 * that the current bound is changed and so, much propagation is triggered
    600 * since we are starting with the bounds which are most influential).
    601 * 2) tighten == FALSE: we fix variables to avoid too much propagation in order to avoid reaching
    602 * infeasibility. Therefore, we fix the variable to the current bound, so that
    603 * this bound is not changed and does not propagate. The other bound is changed
    604 * and propagates, but is later in the order, so less influential.
    605 */
    606 fixtolower = (tighten == (bound == SCIP_BOUNDTYPE_UPPER));
    607
    608 /* if we want to take into account the objective function coefficients, we only perform a fixing if the variable
    609 * would be fixed to its best bound; otherwise, we just continue
    610 */
    611 if( ((SCIPvarGetObj(var) >= 0) != fixtolower) )
    612 {
    613 if( obj == 1 )
    614 continue;
    615 else
    616 *allobj1 = FALSE;
    617 }
    618 /* if we want to take into account the objective function coefficients but reverted, we only perform a fixing if the variable
    619 * would be fixed to its worst bound; otherwise, we just continue
    620 */
    621 if( ((SCIPvarGetObj(var) >= 0) == fixtolower) )
    622 {
    623 if( obj == 2 )
    624 continue;
    625 else
    626 *allobj2 = FALSE;
    627 }
    628 lastvar = var;
    629
    630 /* fix the variable to its bound */
    631 if( fixtolower )
    632 {
    633 /* we cannot fix to infinite bounds */
    635 continue;
    636
    637 /* only open a new probing node if we will not exceed the maximal tree depth */
    639 {
    641 }
    642
    643 /* fix variable to lower bound */
    645 SCIPdebugMsg(scip, "fixing %d: variable <%s> (obj=%g) to lower bound <%g> (%d pseudo cands)\n",
    647 lastfixedlb = TRUE;
    648 lastfixval = SCIPvarGetLbLocal(var);
    649 }
    650 else
    651 {
    652 /* we cannot fix to infinite bounds */
    654 continue;
    655
    656 /* only open a new probing node if we will not exceed the maximal tree depth */
    658 {
    660 }
    661
    662 /* fix variable to upper bound */
    664 SCIPdebugMsg(scip, "fixing %d: variable <%s> (obj=%g) to upper bound <%g> (%d pseudo cands)\n",
    666 lastfixedlb = FALSE;
    667 lastfixval = SCIPvarGetUbLocal(var);
    668 }
    669
    670 /* check if problem is already infeasible */
    671 SCIP_CALL( SCIPpropagateProbing(scip, heurdata->maxproprounds, infeasible, NULL) );
    672
    673 /* probing detected infeasibility: backtrack */
    674 if( *infeasible )
    675 {
    676 assert(lastvar != NULL);
    677
    679 ++nbacktracks;
    680 *infeasible = FALSE;
    681
    682 /* increase the lower bound of the variable which caused the infeasibility */
    683 if( lastfixedlb && lastfixval + 0.5 < SCIPvarGetUbLocal(lastvar) )
    684 {
    685 if( lastfixval + 0.5 > SCIPvarGetLbLocal(lastvar) )
    686 {
    687 SCIP_CALL( SCIPchgVarLbProbing(scip, lastvar, lastfixval + 1.0) );
    688 }
    689 }
    690 else if( !lastfixedlb && lastfixval - 0.5 > SCIPvarGetLbLocal(lastvar) )
    691 {
    692 if( lastfixval - 0.5 < SCIPvarGetUbLocal(lastvar) )
    693 {
    694 SCIP_CALL( SCIPchgVarUbProbing(scip, lastvar, lastfixval - 1.0) );
    695 }
    696 }
    697 /* because of the limited number of propagation rounds, it may happen that conflict analysis finds a valid
    698 * global bound for the last fixed variable that conflicts with applying the reverse bound change after backtracking;
    699 * in that case, we ran into a deadend and stop
    700 */
    701 else
    702 {
    703 *infeasible = TRUE;
    704 }
    705 lastvar = NULL;
    706
    707 if( !(*infeasible) )
    708 {
    709 /* propagate fixings */
    710 SCIP_CALL( SCIPpropagateProbing(scip, heurdata->maxproprounds, infeasible, NULL) );
    711
    712 SCIPdebugMessage("backtrack %d was %sfeasible\n", nbacktracks, (*infeasible ? "in" : ""));
    713 }
    714
    715 if( *infeasible )
    716 {
    717 SCIPdebugMsg(scip, "probing was infeasible after %d backtracks\n", nbacktracks);
    718
    719 break;
    720 }
    721 else if( nbacktracks > heurdata->maxbacktracks )
    722 {
    723 SCIPdebugMsg(scip, "interrupt probing after %d backtracks\n", nbacktracks);
    724 break;
    725 }
    726 }
    727 }
    728
    729 *backtracked = (nbacktracks > 0);
    730
    731 return SCIP_OKAY;
    732}
    733
    734/** copy problem to sub-SCIP, solve it, and add solutions */
    735static
    737 SCIP* scip, /**< original SCIP data structure */
    738 SCIP* subscip, /**< SCIP structure of the subproblem */
    739 SCIP_HEUR* heur, /**< heuristic */
    740 SCIP_VAR** vars, /**< variables of the main SCIP */
    741 int nvars, /**< number of variables of the main SCIP */
    742 SCIP_Longint nstallnodes, /**< stalling node limit for the sub-SCIP */
    743 SCIP_Real lowerbound, /**< lower bound of the main SCIP / current subproblem */
    744 int* nprevars, /**< pointer to store the number of presolved variables */
    745 SCIP_Bool* wasfeas, /**< pointer to store if a feasible solution was found */
    746 SCIP_RESULT* result /**< pointer to store the result */
    747 )
    748{
    749 SCIP_HEURDATA* heurdata;
    750 SCIP_VAR** subvars;
    751 SCIP_HASHMAP* varmap;
    752 int i;
    753
    754 assert(scip != NULL);
    755 assert(subscip != NULL);
    756 assert(heur != NULL);
    757
    758 heurdata = SCIPheurGetData(heur);
    759 assert(heurdata != NULL);
    760
    761 /* create the variable mapping hash map */
    762 SCIP_CALL( SCIPhashmapCreate(&varmap, SCIPblkmem(subscip), nvars) );
    763
    764 SCIP_CALL( SCIPcopyConsCompression(scip, subscip, varmap, NULL, "_vbounds", NULL, NULL, 0, FALSE, FALSE, FALSE,
    765 TRUE, NULL) );
    766
    767 if( heurdata->copycuts )
    768 {
    769 /* copies all active cuts from cutpool of sourcescip to linear constraints in targetscip */
    770 SCIP_CALL( SCIPcopyCuts(scip, subscip, varmap, NULL, FALSE, NULL) );
    771 }
    772
    773 SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
    774
    775 for( i = 0; i < nvars; i++ )
    776 subvars[i] = (SCIP_VAR*) SCIPhashmapGetImage(varmap, vars[i]);
    777
    778 /* free hash map */
    779 SCIPhashmapFree(&varmap);
    780
    781 /* do not abort subproblem on CTRL-C */
    782 SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
    783
    784#ifdef SCIP_DEBUG
    785 /* for debugging, enable full output */
    786 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) );
    787 SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 100000000) );
    788#else
    789 /* disable statistic timing inside sub SCIP and output to console */
    790 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
    791 SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
    792#endif
    793
    794 /* set limits for the subproblem */
    795 SCIP_CALL( SCIPcopyLimits(scip, subscip) );
    796 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/stallnodes", nstallnodes) );
    797 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", heurdata->maxnodes) );
    798
    799 /* speed up sub-SCIP by not checking dual LP feasibility */
    800 SCIP_CALL( SCIPsetBoolParam(subscip, "lp/checkdualfeas", FALSE) );
    801
    802 /* forbid call of heuristics and separators solving sub-CIPs */
    803 SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );
    804
    805 /* disable cutting plane separation */
    807
    808 /* disable expensive presolving */
    810
    811 /* use inference branching */
    812 if( SCIPfindBranchrule(subscip, "inference") != NULL && !SCIPisParamFixed(subscip, "branching/inference/priority") )
    813 {
    814 SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
    815 }
    816
    817 /* set a cutoff bound */
    818 if( SCIPgetNSols(scip) > 0 )
    819 {
    820 SCIP_Real upperbound;
    821 SCIP_Real minimprove;
    822 SCIP_Real cutoffbound;
    823
    824 minimprove = heurdata->minimprove;
    825
    827 upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);
    828
    829 if( !SCIPisInfinity(scip, -1.0 * lowerbound) )
    830 {
    831 cutoffbound = (1-minimprove) * SCIPgetUpperbound(scip) + minimprove * lowerbound;
    832 }
    833 else
    834 {
    835 if( SCIPgetUpperbound ( scip ) >= 0 )
    836 cutoffbound = (1 - minimprove) * SCIPgetUpperbound(scip);
    837 else
    838 cutoffbound = (1 + minimprove) * SCIPgetUpperbound(scip);
    839 }
    840 heurdata->cutoffbound = MIN(upperbound, cutoffbound);
    841 }
    842
    843 if( !SCIPisInfinity(scip, heurdata->cutoffbound) )
    844 {
    845 SCIP_CALL( SCIPsetObjlimit(subscip, heurdata->cutoffbound) );
    846 SCIPdebugMsg(scip, "setting objlimit for subscip to %g\n", heurdata->cutoffbound);
    847 }
    848
    849 SCIPdebugMsg(scip, "starting solving vbound-submip at time %g\n", SCIPgetSolvingTime(scip));
    850
    851 /* solve the subproblem */
    852 /* Errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
    853 * Hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
    854 */
    855 SCIP_CALL_ABORT( SCIPpresolve(subscip) );
    856
    857 SCIPdebugMsg(scip, "vbounds heuristic presolved subproblem at time %g : %d vars, %d cons; fixing value = %g\n",
    859 ((nvars - SCIPgetNVars(subscip)) / (SCIP_Real)nvars));
    860
    861 *nprevars = SCIPgetNVars(subscip);
    862
    863 /* after presolving, we should have at least reached a certain fixing rate over ALL variables (including continuous)
    864 * to ensure that not only the MIP but also the LP relaxation is easy enough
    865 */
    866 if( ((nvars - SCIPgetNVars(subscip)) / (SCIP_Real)nvars) >= heurdata->minmipfixingrate )
    867 {
    868 SCIPdebugMsg(scip, "solving subproblem: nstallnodes=%" SCIP_LONGINT_FORMAT ", maxnodes=%" SCIP_LONGINT_FORMAT "\n", nstallnodes, heurdata->maxnodes);
    869
    870 SCIP_CALL_ABORT( SCIPsolve(subscip) );
    871
    872 SCIPdebugMsg(scip, "ending solving vbounds-submip at time %g, status = %d\n", SCIPgetSolvingTime(scip), SCIPgetStatus(subscip));
    873
    874 /* check, whether a solution was found; due to numerics, it might happen that not all solutions are feasible ->
    875 * try all solutions until one was accepted
    876 */
    877 SCIP_CALL( SCIPtranslateSubSols(scip, subscip, heur, subvars, wasfeas, NULL) );
    878 if( (*wasfeas) )
    879 {
    880 SCIPdebugMsg(scip, "found feasible solution in sub-MIP\n");
    881 *result = SCIP_FOUNDSOL;
    882 }
    883 }
    884
    885#ifdef SCIP_DEBUG
    887#endif
    888
    889 /* free subproblem */
    890 SCIPfreeBufferArray(scip, &subvars);
    891
    892 return SCIP_OKAY;
    893}
    894
    895/** main procedure of the vbounds heuristic */
    896static
    898 SCIP* scip, /**< original SCIP data structure */
    899 SCIP_HEUR* heur, /**< heuristic */
    900 SCIP_HEURDATA* heurdata, /**< heuristic data structure */
    901 SCIP_VAR** vbvars, /**< variables to fix during probing */
    902 int nvbvars, /**< number of variables to fix */
    903 SCIP_Bool tighten, /**< should variables be fixed to cause other fixings? */
    904 int obj, /**< should the objective be taken into account? */
    905 SCIP_Bool* skipobj1, /**< pointer to store whether the run with obj=1 can be skipped, or NULL */
    906 SCIP_Bool* skipobj2, /**< pointer to store whether the run with obj=2 can be skipped, or NULL */
    907 SCIP_RESULT* result /**< pointer to store the result */
    908 )
    909{
    910 SCIPstatistic( SCIP_CLOCK* clock; )
    911 SCIP_VAR** vars;
    912 SCIP_Longint nstallnodes;
    913 SCIP_LPSOLSTAT lpstatus;
    914 SCIP_Real lowerbound;
    915 SCIP_Bool wasfeas = FALSE;
    916 SCIP_Bool cutoff;
    917 SCIP_Bool lperror;
    918 SCIP_Bool solvelp;
    919 SCIP_Bool allobj1 = TRUE;
    920 SCIP_Bool allobj2 = TRUE;
    921 SCIP_Bool backtracked = TRUE;
    922 int oldnpscands;
    923 int npscands;
    924 int nvars;
    925 int nprevars;
    926
    927 assert(heur != NULL);
    928 assert(heurdata != NULL);
    929 assert(nvbvars > 0);
    930
    931 /* initialize default values */
    932 cutoff = FALSE;
    933
    934 if( skipobj1 != NULL )
    935 *skipobj1 = FALSE;
    936 if( skipobj2 != NULL )
    937 *skipobj2 = FALSE;
    938
    939 if( nvbvars < SCIPgetNVars(scip) * heurdata->minintfixingrate )
    940 return SCIP_OKAY;
    941
    942 if( *result == SCIP_DIDNOTRUN )
    943 *result = SCIP_DIDNOTFIND;
    944
    945 lowerbound = SCIPgetLowerbound(scip);
    946
    947 oldnpscands = SCIPgetNPseudoBranchCands(scip);
    948
    949 /* calculate the maximal number of branching nodes until heuristic is aborted */
    950 nstallnodes = (SCIP_Longint)(heurdata->nodesquot * SCIPgetNNodes(scip));
    951
    952 /* reward variable bounds heuristic if it succeeded often */
    953 nstallnodes = (SCIP_Longint)(nstallnodes * 3.0 * (SCIPheurGetNBestSolsFound(heur)+1.0)/(SCIPheurGetNCalls(heur) + 1.0));
    954 nstallnodes -= 100 * SCIPheurGetNCalls(heur); /* count the setup costs for the sub-MIP as 100 nodes */
    955 nstallnodes += heurdata->nodesofs;
    956
    957 /* determine the node limit for the current process */
    958 nstallnodes -= heurdata->usednodes;
    959 nstallnodes = MIN(nstallnodes, heurdata->maxnodes);
    960
    961 SCIPdebugMsg(scip, "apply variable bounds heuristic at node %lld on %d variable bounds, tighten: %u obj: %d\n",
    962 SCIPnodeGetNumber(SCIPgetCurrentNode(scip)), nvbvars, tighten, obj);
    963
    964 /* check whether we have enough nodes left to call subproblem solving */
    965 if( nstallnodes < heurdata->minnodes )
    966 {
    967 SCIPdebugMsg(scip, "skipping " HEUR_NAME ": nstallnodes=%" SCIP_LONGINT_FORMAT ", minnodes=%" SCIP_LONGINT_FORMAT "\n", nstallnodes, heurdata->minnodes);
    968 return SCIP_OKAY;
    969 }
    970
    971 if( SCIPisStopped(scip) )
    972 return SCIP_OKAY;
    973
    976
    977 /* check whether the LP should be solved at the current node in the tree to determine whether the heuristic
    978 * is allowed to solve an LP
    979 */
    980 solvelp = SCIPhasCurrentNodeLP(scip);
    981
    982 if( !SCIPisLPConstructed(scip) && solvelp )
    983 {
    984 SCIP_CALL( SCIPconstructLP(scip, &cutoff) );
    985
    986 /* manually cut off the node if the LP construction detected infeasibility (heuristics cannot return such a
    987 * result); the cutoff result is safe to use in exact solving mode, but we don't have enough information to
    988 * give a certificate for the cutoff
    989 */
    990 if( cutoff && !SCIPisCertified(scip) )
    991 {
    993 goto TERMINATE;
    994 }
    995
    997 }
    998
    999 /* get variable data of original problem */
    1000 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
    1001
    1002 SCIPstatistic( nprevars = nvars; )
    1003
    1004 /* start probing */
    1006
    1007#ifdef COLLECTSTATISTICS
    1009#endif
    1010
    1011 /* apply the variable fixings */
    1012 SCIP_CALL( applyVboundsFixings(scip, heurdata, vbvars, nvbvars, tighten, obj, &allobj1, &allobj2, &backtracked, &cutoff) );
    1013
    1014 if( skipobj1 != NULL )
    1015 *skipobj1 = allobj1;
    1016
    1017 if( skipobj2 != NULL )
    1018 *skipobj2 = allobj2;
    1019
    1020 if( cutoff || SCIPisStopped(scip) )
    1021 goto TERMINATE;
    1022
    1023 /* check that we had enough fixings */
    1024 npscands = SCIPgetNPseudoBranchCands(scip);
    1025
    1026 SCIPdebugMsg(scip, "npscands=%d, oldnpscands=%d, heurdata->minintfixingrate=%g\n", npscands, oldnpscands, heurdata->minintfixingrate);
    1027
    1028 /* check fixing rate */
    1029 if( npscands > oldnpscands * (1.0 - heurdata->minintfixingrate) )
    1030 {
    1031 if( heurdata->uselockfixings && npscands <= 2.0 * oldnpscands * (1.0 - heurdata->minintfixingrate) )
    1032 {
    1033 SCIP_Bool allrowsfulfilled = FALSE;
    1034
    1035 SCIP_CALL( SCIPapplyLockFixings(scip, NULL, &cutoff, &allrowsfulfilled) );
    1036
    1037 if( cutoff || SCIPisStopped(scip) )
    1038 {
    1039 SCIPdebugMsg(scip, "cutoff or timeout in locks fixing\n");
    1040 goto TERMINATE;
    1041 }
    1042
    1043 npscands = SCIPgetNPseudoBranchCands(scip);
    1044
    1045 SCIPdebugMsg(scip, "after lockfixings: npscands=%d, oldnpscands=%d, allrowsfulfilled=%u, heurdata->minintfixingrate=%g\n",
    1046 npscands, oldnpscands, allrowsfulfilled, heurdata->minintfixingrate);
    1047
    1048 if( !allrowsfulfilled && npscands > oldnpscands * (1 - heurdata->minintfixingrate) )
    1049 {
    1050 SCIPdebugMsg(scip, "--> too few fixings\n");
    1051
    1052 goto TERMINATE;
    1053 }
    1054 }
    1055 else
    1056 {
    1057 SCIPdebugMsg(scip, "--> too few fixings\n");
    1058
    1059 goto TERMINATE;
    1060 }
    1061 }
    1062
    1063 assert(!cutoff);
    1064
    1065 /*************************** Probing LP Solving ***************************/
    1066 lpstatus = SCIP_LPSOLSTAT_ERROR;
    1067 lperror = FALSE;
    1068 /* solve lp only if the problem is still feasible */
    1069 if( solvelp )
    1070 {
    1071 char strbuf[SCIP_MAXSTRLEN];
    1072 int ncols;
    1073
    1074 /* print message if relatively large LP is solved from scratch, since this could lead to a longer period during
    1075 * which the user sees no output; more detailed probing stats only in debug mode */
    1076 ncols = SCIPgetNLPCols(scip);
    1077 if( !SCIPisLPSolBasic(scip) && ncols > 1000 )
    1078 {
    1079 int nunfixedcols = SCIPgetNUnfixedLPCols(scip);
    1080
    1081 if( nunfixedcols > 0.5 * ncols )
    1082 {
    1084 "Heuristic " HEUR_NAME " solving LP from scratch with %.1f %% unfixed columns (%d of %d) ...\n",
    1085 100.0 * (nunfixedcols / (SCIP_Real)ncols), nunfixedcols, ncols);
    1086 }
    1087 }
    1088 SCIPdebugMsg(scip, "Heuristic " HEUR_NAME " probing LP: %s\n",
    1090
    1091 /* solve LP; errors in the LP solver should not kill the overall solving process, if the LP is just needed for a
    1092 * heuristic. hence in optimized mode, the return code is caught and a warning is printed, only in debug mode,
    1093 * SCIP will stop.
    1094 */
    1095 SCIPdebugMsg(scip, "starting solving vbound-lp at time %g\n", SCIPgetSolvingTime(scip));
    1096#ifdef NDEBUG
    1097 {
    1098 SCIP_Bool retstat;
    1099 retstat = SCIPsolveProbingLP(scip, -1, &lperror, NULL);
    1100 if( retstat != SCIP_OKAY )
    1101 {
    1102 SCIPwarningMessage(scip, "Error while solving LP in vbound heuristic; LP solve terminated with code <%d>\n",
    1103 retstat);
    1104 }
    1105 }
    1106#else
    1107 SCIP_CALL( SCIPsolveProbingLP(scip, -1, &lperror, NULL) );
    1108#endif
    1109 SCIPdebugMsg(scip, "ending solving vbound-lp at time %g\n", SCIPgetSolvingTime(scip));
    1110
    1111 lpstatus = SCIPgetLPSolstat(scip);
    1112
    1113 SCIPdebugMsg(scip, " -> new LP iterations: %" SCIP_LONGINT_FORMAT "\n", SCIPgetNLPIterations(scip));
    1114 SCIPdebugMsg(scip, " -> error=%u, status=%d\n", lperror, lpstatus);
    1115 }
    1116
    1117 /* check if this is a feasible solution */
    1118 if( lpstatus == SCIP_LPSOLSTAT_OPTIMAL && !lperror )
    1119 {
    1120 SCIP_Bool stored;
    1121 SCIP_Bool success;
    1122 SCIP_SOL* sol;
    1123
    1124 lowerbound = SCIPgetLPObjval(scip);
    1125
    1126 /* copy the current LP solution to the working solution */
    1127 SCIP_CALL( SCIPcreateSol(scip, &sol, heur) );
    1128 SCIP_CALL( SCIPlinkLPSol(scip, sol) );
    1129
    1130 SCIP_CALL( SCIProundSol(scip, sol, &success) );
    1131
    1132 if( success )
    1133 {
    1134 SCIPdebugMsg(scip, "vbound heuristic found roundable primal solution: obj=%g\n",
    1135 SCIPgetSolOrigObj(scip, sol));
    1136
    1137 /* check solution for feasibility, and add it to solution store if possible.
    1138 * Neither integrality nor feasibility of LP rows have to be checked, because they
    1139 * are guaranteed by the heuristic at this stage.
    1140 */
    1141#ifdef SCIP_DEBUG
    1142 SCIP_CALL( SCIPtrySol(scip, sol, TRUE, TRUE, TRUE, TRUE, TRUE, &stored) );
    1143#else
    1144 SCIP_CALL( SCIPtrySol(scip, sol, FALSE, FALSE, TRUE, FALSE, FALSE, &stored) );
    1145#endif
    1146
    1147#ifdef SCIP_DEBUG
    1148 SCIP_CALL( SCIPcheckSol(scip, sol, FALSE, FALSE, TRUE, TRUE, TRUE, &wasfeas) );
    1149 assert(wasfeas);
    1150 SCIPdebugMsg(scip, "found feasible solution by LP rounding: %16.9g\n", SCIPgetSolOrigObj(scip, sol));
    1151#endif
    1152
    1153 if( stored )
    1154 *result = SCIP_FOUNDSOL;
    1155
    1156 SCIP_CALL( SCIPfreeSol(scip, &sol) );
    1157
    1158 /* we found a solution, so we are done */
    1159 goto TERMINATE;
    1160 }
    1161
    1162 SCIP_CALL( SCIPfreeSol(scip, &sol) );
    1163 }
    1164 /*************************** END Probing LP Solving ***************************/
    1165
    1166 /*************************** Start Subscip Solving ***************************/
    1167 /* if no solution has been found --> fix all other variables by subscip if necessary */
    1168 if( !lperror && lpstatus != SCIP_LPSOLSTAT_INFEASIBLE && lpstatus != SCIP_LPSOLSTAT_OBJLIMIT )
    1169 {
    1170 SCIP* subscip;
    1171 SCIP_RETCODE retcode;
    1172 SCIP_Bool valid;
    1173
    1174 /* check whether there is enough time and memory left */
    1176
    1177 if( !valid )
    1178 goto TERMINATE;
    1179
    1180 /* create subproblem */
    1181 SCIP_CALL( SCIPcreate(&subscip) );
    1182
    1183 retcode = setupAndSolveSubscip(scip, subscip, heur, vars, nvars, nstallnodes, lowerbound,
    1184 &nprevars, &wasfeas, result);
    1185
    1186 SCIP_CALL( SCIPfree(&subscip) );
    1187
    1188 SCIP_CALL( retcode );
    1189 }
    1190
    1191 /*************************** End Subscip Solving ***************************/
    1192
    1193 TERMINATE:
    1194#ifdef SCIP_STATISTIC
    1195 SCIP_CALL( SCIPstopClock(scip, clock) );
    1196 SCIPstatisticMessage("vbound: tighten=%u obj=%d nvars=%d presolnvars=%d ratio=%.2f infeas=%u found=%d time=%.4f\n",
    1197 tighten, obj, nvars, nprevars, (nvars - nprevars) / (SCIP_Real)nvars, cutoff,
    1198 wasfeas ? 1 : 0, SCIPclockGetTime(clock) );
    1199#endif
    1200
    1202
    1203 /* exit probing mode */
    1204 if( SCIPinProbing(scip) )
    1205 {
    1207 }
    1208
    1209 return SCIP_OKAY; /*lint !e438*/
    1210}
    1211
    1212
    1213/*
    1214 * Callback methods of primal heuristic
    1215 */
    1216
    1217/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
    1218static
    1219SCIP_DECL_HEURCOPY(heurCopyVbounds)
    1220{ /*lint --e{715}*/
    1221 assert(scip != NULL);
    1222 assert(heur != NULL);
    1223 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    1224
    1225 /* call inclusion method of heuristic */
    1227
    1228 return SCIP_OKAY;
    1229}
    1230
    1231/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
    1232static
    1233SCIP_DECL_HEURFREE(heurFreeVbounds)
    1234{ /*lint --e{715}*/
    1235 SCIP_HEURDATA* heurdata;
    1236
    1237 /* free heuristic data */
    1238 heurdata = SCIPheurGetData(heur);
    1239
    1240 SCIPfreeBlockMemory(scip, &heurdata);
    1241 SCIPheurSetData(heur, NULL);
    1242
    1243 return SCIP_OKAY;
    1244}
    1245
    1246
    1247/** solving process deinitialization method of primal heuristic (called before branch and bound process data is freed) */
    1248static
    1249SCIP_DECL_HEUREXITSOL(heurExitsolVbounds)
    1250{ /*lint --e{715}*/
    1251 SCIP_HEURDATA* heurdata;
    1252 int v;
    1253
    1254 heurdata = SCIPheurGetData(heur);
    1255 assert(heurdata != NULL);
    1256
    1257 /* release all variables */
    1258 for( v = 0; v < heurdata->nvbvars; ++v )
    1259 {
    1260 SCIP_CALL( SCIPreleaseVar(scip, &heurdata->vbvars[v]) );
    1261 }
    1262
    1263 /* free varbounds array */
    1264 SCIPfreeBlockMemoryArrayNull(scip, &heurdata->vbbounds, heurdata->nvbvars);
    1265 SCIPfreeBlockMemoryArrayNull(scip, &heurdata->vbvars, heurdata->nvbvars);
    1266
    1267 /* reset heuristic data structure */
    1268 heurdataReset(heurdata);
    1269
    1270 return SCIP_OKAY;
    1271}
    1272
    1273/** execution method of primal heuristic */
    1274static
    1275SCIP_DECL_HEUREXEC(heurExecVbounds)
    1276{ /*lint --e{715}*/
    1277 SCIP_HEURDATA* heurdata;
    1278 SCIP_Bool skipobj1;
    1279 SCIP_Bool skipobj2;
    1280#ifdef NOCONFLICT
    1281 SCIP_Bool enabledconflicts;
    1282#endif
    1283
    1284 assert( heur != NULL );
    1285 assert( scip != NULL );
    1286 assert( result != NULL );
    1287
    1288 *result = SCIP_DIDNOTRUN;
    1289
    1291 return SCIP_OKAY;
    1292
    1293 heurdata = SCIPheurGetData(heur);
    1294 assert(heurdata != NULL);
    1295
    1296 if( !heurdata->initialized )
    1297 {
    1298 SCIP_CALL( initializeCandsLists(scip, heurdata) );
    1299 }
    1300
    1301 if( !heurdata->applicable )
    1302 return SCIP_OKAY;
    1303
    1304#ifdef NOCONFLICT
    1305 /* disable conflict analysis */
    1306 SCIP_CALL( SCIPgetBoolParam(scip, "conflict/enable", &enabledconflicts) );
    1307
    1308 if( !SCIPisParamFixed(scip, "conflict/enable") )
    1309 {
    1310 SCIP_CALL( SCIPsetBoolParam(scip, "conflict/enable", FALSE) );
    1311 }
    1312#endif
    1313
    1314 /* try variable bounds */
    1315 skipobj1 = FALSE;
    1316 skipobj2 = FALSE;
    1317 if( ((unsigned)heurdata->feasvariant & VBOUNDVARIANT_NOOBJ) != 0 )
    1318 {
    1319 SCIP_CALL( applyVbounds(scip, heur, heurdata, heurdata->vbvars, heurdata->nvbvars, FALSE, 0,
    1320 &skipobj1, &skipobj2, result) );
    1321 }
    1322 if( !skipobj1 && ((unsigned) heurdata->feasvariant & VBOUNDVARIANT_BESTBOUND) != 0)
    1323 {
    1324 SCIP_CALL( applyVbounds(scip, heur, heurdata, heurdata->vbvars, heurdata->nvbvars, FALSE, 1, NULL, NULL, result) );
    1325 }
    1326 if( !skipobj2 && ((unsigned) heurdata->feasvariant & VBOUNDVARIANT_WORSTBOUND) != 0)
    1327 {
    1328 SCIP_CALL( applyVbounds(scip, heur, heurdata, heurdata->vbvars, heurdata->nvbvars, FALSE, 2, NULL, NULL, result) );
    1329 }
    1330
    1331 skipobj1 = FALSE;
    1332 skipobj2 = FALSE;
    1333 if( ((unsigned) heurdata->tightenvariant & VBOUNDVARIANT_NOOBJ) != 0 )
    1334 {
    1335 SCIP_CALL( applyVbounds(scip, heur, heurdata, heurdata->vbvars, heurdata->nvbvars, TRUE, 0,
    1336 &skipobj1, &skipobj2, result) );
    1337 }
    1338 if( !skipobj1 && ((unsigned) heurdata->tightenvariant & VBOUNDVARIANT_BESTBOUND) != 0)
    1339 {
    1340 SCIP_CALL( applyVbounds(scip, heur, heurdata, heurdata->vbvars, heurdata->nvbvars, TRUE, 1, NULL, NULL, result) );
    1341 }
    1342 if( !skipobj2 && ((unsigned) heurdata->tightenvariant & VBOUNDVARIANT_WORSTBOUND) != 0)
    1343 {
    1344 SCIP_CALL( applyVbounds(scip, heur, heurdata, heurdata->vbvars, heurdata->nvbvars, TRUE, 2, NULL, NULL, result) );
    1345 }
    1346
    1347#ifdef NOCONFLICT
    1348 /* reset the conflict analysis */
    1349 if( !SCIPisParamFixed(scip, "conflict/enable") )
    1350 {
    1351 SCIP_CALL( SCIPsetBoolParam(scip, "conflict/enable", enabledconflicts) );
    1352 }
    1353#endif
    1354
    1355 return SCIP_OKAY;
    1356}
    1357
    1358/*
    1359 * primal heuristic specific interface methods
    1360 */
    1361
    1362/** creates the vbounds primal heuristic and includes it in SCIP */
    1364 SCIP* scip /**< SCIP data structure */
    1365 )
    1366{
    1367 SCIP_HEURDATA* heurdata;
    1368 SCIP_HEUR* heur;
    1369
    1370 /* create vbounds primal heuristic data */
    1371 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    1372 heurdataReset(heurdata);
    1373
    1374 /* include primal heuristic */
    1377 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecVbounds, heurdata) );
    1378
    1379 assert(heur != NULL);
    1380
    1381 /* primal heuristic is safe to use in exact solving mode */
    1382 SCIPheurMarkExact(heur);
    1383
    1384 /* set non-NULL pointers to callback methods */
    1385 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyVbounds) );
    1386 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeVbounds) );
    1387 SCIP_CALL( SCIPsetHeurExitsol(scip, heur, heurExitsolVbounds) );
    1388
    1389 /* add variable bounds primal heuristic parameters */
    1390 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minintfixingrate",
    1391 "minimum percentage of integer variables that have to be fixed",
    1392 &heurdata->minintfixingrate, FALSE, DEFAULT_MININTFIXINGRATE, 0.0, 1.0, NULL, NULL) );
    1393
    1394 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minmipfixingrate",
    1395 "minimum percentage of variables that have to be fixed within sub-SCIP (integer and continuous)",
    1396 &heurdata->minmipfixingrate, FALSE, DEFAULT_MINMIPFIXINGRATE, 0.0, 1.0, NULL, NULL) );
    1397
    1398 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
    1399 "maximum number of nodes to regard in the subproblem",
    1400 &heurdata->maxnodes, TRUE,DEFAULT_MAXNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
    1401
    1402 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/nodesofs",
    1403 "number of nodes added to the contingent of the total nodes",
    1404 &heurdata->nodesofs, FALSE, DEFAULT_NODESOFS, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
    1405
    1406 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/minnodes",
    1407 "minimum number of nodes required to start the subproblem",
    1408 &heurdata->minnodes, TRUE, DEFAULT_MINNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
    1409
    1410 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesquot",
    1411 "contingent of sub problem nodes in relation to the number of nodes of the original problem",
    1412 &heurdata->nodesquot, FALSE, DEFAULT_NODESQUOT, 0.0, 1.0, NULL, NULL) );
    1413
    1414 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprove",
    1415 "factor by which " HEUR_NAME " heuristic should at least improve the incumbent",
    1416 &heurdata->minimprove, TRUE, DEFAULT_MINIMPROVE, 0.0, 1.0, NULL, NULL) );
    1417
    1418 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxproprounds",
    1419 "maximum number of propagation rounds during probing (-1 infinity)",
    1420 &heurdata->maxproprounds, TRUE, DEFAULT_MAXPROPROUNDS, -1, INT_MAX/4, NULL, NULL) );
    1421
    1422 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/copycuts",
    1423 "should all active cuts from cutpool be copied to constraints in subproblem?",
    1424 &heurdata->copycuts, TRUE, DEFAULT_COPYCUTS, NULL, NULL) );
    1425
    1426 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/uselockfixings",
    1427 "should more variables be fixed based on variable locks if the fixing rate was not reached?",
    1428 &heurdata->uselockfixings, TRUE, DEFAULT_USELOCKFIXINGS, NULL, NULL) );
    1429
    1430 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxbacktracks",
    1431 "maximum number of backtracks during the fixing process",
    1432 &heurdata->maxbacktracks, TRUE, DEFAULT_MAXBACKTRACKS, -1, INT_MAX/4, NULL, NULL) );
    1433
    1434 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/feasvariant",
    1435 "which variants of the vbounds heuristic that try to stay feasible should be called? (0: off, 1: w/o looking at obj, 2: only fix to best bound, 4: only fix to worst bound",
    1436 &heurdata->feasvariant, TRUE, (int) DEFAULT_FEASVARIANT, 0, 7, NULL, NULL) );
    1437
    1438 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/tightenvariant",
    1439 "which tightening variants of the vbounds heuristic should be called? (0: off, 1: w/o looking at obj, 2: only fix to best bound, 4: only fix to worst bound",
    1440 &heurdata->tightenvariant, TRUE, (int) DEFAULT_TIGHTENVARIANT, 0, 7, NULL, NULL) );
    1441
    1442 return SCIP_OKAY;
    1443}
    1444
    1445/**@} */
    static long bound
    SCIP_Real SCIPclockGetTime(SCIP_CLOCK *clck)
    Definition: clock.c:438
    internal methods for clocks and timing issues
    #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_Shortbool
    Definition: def.h:99
    #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 MAX(x, y)
    Definition: def.h:220
    #define SCIP_CALL_ABORT(x)
    Definition: def.h:334
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:148
    #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 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:2961
    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 SCIPgetNIntVars(SCIP *scip)
    Definition: scip_prob.c:2340
    int SCIPgetNImplVars(SCIP *scip)
    Definition: scip_prob.c:2387
    const char * SCIPgetProbName(SCIP *scip)
    Definition: scip_prob.c:1242
    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 SCIPincludeHeurVbounds(SCIP *scip)
    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_Bool SCIPisExact(SCIP *scip)
    Definition: scip_exact.c:193
    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_Longint SCIPheurGetNBestSolsFound(SCIP_HEUR *heur)
    Definition: heur.c:1613
    SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
    Definition: heur.c:1593
    void SCIPheurMarkExact(SCIP_HEUR *heur)
    Definition: heur.c:1457
    const char * SCIPheurGetName(SCIP_HEUR *heur)
    Definition: heur.c:1467
    void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
    Definition: heur.c:1378
    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_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 SCIPallocBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:93
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
    Definition: scip_mem.h:111
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
    Definition: tree.c:8483
    int SCIPgetProbingDepth(SCIP *scip)
    Definition: scip_probing.c:199
    SCIP_RETCODE SCIPchgVarUbProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
    Definition: scip_probing.c:346
    char * SCIPsnprintfProbingStats(SCIP *scip, char *strbuf, int len)
    SCIP_RETCODE SCIPchgVarLbProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
    Definition: scip_probing.c:302
    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_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:516
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1252
    int SCIPgetNSols(SCIP *scip)
    Definition: scip_sol.c:2882
    SCIP_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_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1892
    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)
    SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
    SCIP_RETCODE SCIPcreateClock(SCIP *scip, SCIP_CLOCK **clck)
    Definition: scip_timing.c:76
    SCIP_RETCODE SCIPstopClock(SCIP *scip, SCIP_CLOCK *clck)
    Definition: scip_timing.c:178
    SCIP_Real SCIPgetSolvingTime(SCIP *scip)
    Definition: scip_timing.c:378
    SCIP_RETCODE SCIPfreeClock(SCIP *scip, SCIP_CLOCK **clck)
    Definition: scip_timing.c:127
    SCIP_RETCODE SCIPstartClock(SCIP *scip, SCIP_CLOCK *clck)
    Definition: scip_timing.c:161
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    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
    int SCIPvarGetNVlbs(SCIP_VAR *var)
    Definition: var.c:24482
    SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
    Definition: var.c:24504
    SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
    Definition: var.c:23642
    SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
    Definition: var.c:23478
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24268
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23900
    int SCIPvarGetProbindex(SCIP_VAR *var)
    Definition: var.c:23662
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
    Definition: scip_var.c:1887
    int SCIPvarGetNVubs(SCIP_VAR *var)
    Definition: var.c:24524
    SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
    Definition: var.c:23490
    int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
    Definition: var.c:24642
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24234
    int SCIPgetNCliques(SCIP *scip)
    Definition: scip_var.c:9512
    SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
    Definition: var.c:24494
    SCIP_CLIQUE ** SCIPvarGetCliques(SCIP_VAR *var, SCIP_Bool varfixing)
    Definition: var.c:24653
    SCIP_VAR ** SCIPvarGetVubVars(SCIP_VAR *var)
    Definition: var.c:24536
    SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
    Definition: var.c:24546
    void SCIPenableVarHistory(SCIP *scip)
    Definition: scip_var.c:11083
    SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:1853
    SCIP_RETCODE SCIPapplyLockFixings(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_Bool *cutoff, SCIP_Bool *allrowsfulfilled)
    Definition: heur_locks.c:191
    locks primal heuristic
    #define getOtherBoundIndex(idx)
    Definition: heur_vbounds.c:167
    #define DEFAULT_MININTFIXINGRATE
    Definition: heur_vbounds.c:95
    #define DEFAULT_NODESQUOT
    Definition: heur_vbounds.c:102
    #define isIndexLowerbound(idx)
    Definition: heur_vbounds.c:166
    static SCIP_DECL_HEURFREE(heurFreeVbounds)
    #define getUbIndex(idx)
    Definition: heur_vbounds.c:163
    #define DEFAULT_NODESOFS
    Definition: heur_vbounds.c:101
    #define DEFAULT_COPYCUTS
    Definition: heur_vbounds.c:105
    #define DEFAULT_MAXNODES
    Definition: heur_vbounds.c:94
    #define HEUR_TIMING
    Definition: heur_vbounds.c:91
    #define DEFAULT_MINNODES
    Definition: heur_vbounds.c:100
    static SCIP_DECL_HEUREXITSOL(heurExitsolVbounds)
    static SCIP_RETCODE applyVboundsFixings(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR **vars, int nvbvars, SCIP_Bool tighten, int obj, SCIP_Bool *allobj1, SCIP_Bool *allobj2, SCIP_Bool *backtracked, SCIP_Bool *infeasible)
    Definition: heur_vbounds.c:555
    static SCIP_RETCODE applyVbounds(SCIP *scip, SCIP_HEUR *heur, SCIP_HEURDATA *heurdata, SCIP_VAR **vbvars, int nvbvars, SCIP_Bool tighten, int obj, SCIP_Bool *skipobj1, SCIP_Bool *skipobj2, SCIP_RESULT *result)
    Definition: heur_vbounds.c:897
    #define VBOUNDVARIANT_WORSTBOUND
    Definition: heur_vbounds.c:82
    #define HEUR_FREQOFS
    Definition: heur_vbounds.c:89
    #define HEUR_DESC
    Definition: heur_vbounds.c:85
    #define DEFAULT_TIGHTENVARIANT
    Definition: heur_vbounds.c:115
    static SCIP_RETCODE setupAndSolveSubscip(SCIP *scip, SCIP *subscip, SCIP_HEUR *heur, SCIP_VAR **vars, int nvars, SCIP_Longint nstallnodes, SCIP_Real lowerbound, int *nprevars, SCIP_Bool *wasfeas, SCIP_RESULT *result)
    Definition: heur_vbounds.c:736
    static SCIP_RETCODE dfs(SCIP *scip, int startnode, SCIP_Shortbool *visited, int *dfsstack, int *stacknextedge, int *stacknextcliquevar, int *cliqueexit, int *dfsnodes, int *ndfsnodes)
    Definition: heur_vbounds.c:190
    #define getLbIndex(idx)
    Definition: heur_vbounds.c:162
    #define HEUR_DISPCHAR
    Definition: heur_vbounds.c:86
    #define HEUR_MAXDEPTH
    Definition: heur_vbounds.c:90
    #define HEUR_PRIORITY
    Definition: heur_vbounds.c:87
    #define DEFAULT_FEASVARIANT
    Definition: heur_vbounds.c:112
    static SCIP_RETCODE initializeCandsLists(SCIP *scip, SCIP_HEURDATA *heurdata)
    Definition: heur_vbounds.c:467
    static SCIP_DECL_HEURCOPY(heurCopyVbounds)
    #define DEFAULT_MINIMPROVE
    Definition: heur_vbounds.c:98
    #define HEUR_NAME
    Definition: heur_vbounds.c:84
    #define DEFAULT_MINMIPFIXINGRATE
    Definition: heur_vbounds.c:96
    static SCIP_RETCODE topologicalSort(SCIP *scip, int *vbvars, int *nvbvars)
    Definition: heur_vbounds.c:419
    #define DEFAULT_MAXBACKTRACKS
    Definition: heur_vbounds.c:104
    static void heurdataReset(SCIP_HEURDATA *heurdata)
    Definition: heur_vbounds.c:176
    #define getBoundtype(idx)
    Definition: heur_vbounds.c:165
    #define VBOUNDVARIANT_BESTBOUND
    Definition: heur_vbounds.c:81
    static SCIP_DECL_HEUREXEC(heurExecVbounds)
    #define getVarIndex(idx)
    Definition: heur_vbounds.c:164
    #define HEUR_FREQ
    Definition: heur_vbounds.c:88
    #define HEUR_USESSUBSCIP
    Definition: heur_vbounds.c:92
    #define DEFAULT_USELOCKFIXINGS
    Definition: heur_vbounds.c:107
    #define DEFAULT_MAXPROPROUNDS
    Definition: heur_vbounds.c:103
    #define VBOUNDVARIANT_NOOBJ
    Definition: heur_vbounds.c:80
    LNS heuristic uses the variable lower and upper bounds to determine the search neighborhood.
    SCIP_VAR ** SCIPcliqueGetVars(SCIP_CLIQUE *clique)
    Definition: implics.c:3384
    int SCIPcliqueGetNVars(SCIP_CLIQUE *clique)
    Definition: implics.c:3374
    SCIP_Bool * SCIPcliqueGetValues(SCIP_CLIQUE *clique)
    Definition: implics.c:3396
    int SCIPcliqueGetIndex(SCIP_CLIQUE *clique)
    Definition: implics.c:3420
    memory allocation routines
    public methods for primal heuristics
    public methods for implications, variable bounds, and cliques
    public methods for message output
    #define SCIPstatisticMessage
    Definition: pub_message.h:123
    #define SCIPdebugMessage
    Definition: pub_message.h:96
    #define SCIPstatistic(x)
    Definition: pub_message.h:120
    public data structures and miscellaneous methods
    public methods for branch and bound tree
    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 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
    struct SCIP_HeurData SCIP_HEURDATA
    Definition: type_heur.h:77
    enum SCIP_LPSolStat SCIP_LPSOLSTAT
    Definition: type_lp.h:52
    @ SCIP_BOUNDTYPE_UPPER
    Definition: type_lp.h:58
    enum SCIP_BoundType SCIP_BOUNDTYPE
    Definition: type_lp.h:60
    @ 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
    enum SCIP_Result SCIP_RESULT
    Definition: type_result.h:61
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63