SCIP

    Solving Constraint Integer Programs

    heur_clique.c
    Go to the documentation of this file.
    1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    2/* */
    3/* This file is part of the program and library */
    4/* SCIP --- Solving Constraint Integer Programs */
    5/* */
    6/* Copyright (c) 2002-2026 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file heur_clique.c
    26 * @ingroup DEFPLUGINS_HEUR
    27 * @brief LNS heuristic using a clique partition to restrict the search neighborhood
    28 * @brief clique primal heuristic
    29 * @author Stefan Heinz
    30 * @author Michael Winkler
    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/cons_logicor.h"
    47#include "scip/heur_clique.h"
    48#include "scip/heur_locks.h"
    49#include "scip/pub_heur.h"
    50#include "scip/pub_implics.h"
    51#include "scip/pub_message.h"
    52#include "scip/pub_misc.h"
    53#include "scip/pub_misc_sort.h"
    54#include "scip/pub_var.h"
    55#include "scip/scip_branch.h"
    57#include "scip/scip_cons.h"
    58#include "scip/scip_copy.h"
    59#include "scip/scip_exact.h"
    60#include "scip/scip_general.h"
    61#include "scip/scip_heur.h"
    62#include "scip/scip_lp.h"
    63#include "scip/scip_mem.h"
    64#include "scip/scip_message.h"
    65#include "scip/scip_numerics.h"
    66#include "scip/scip_param.h"
    67#include "scip/scip_prob.h"
    68#include "scip/scip_probing.h"
    69#include "scip/scip_sol.h"
    70#include "scip/scip_solve.h"
    72#include "scip/scip_timing.h"
    73#include "scip/scip_tree.h"
    74#include "scip/scip_var.h"
    75
    76
    77#define HEUR_NAME "clique"
    78#define HEUR_DESC "LNS heuristic using a clique partition to restrict the search neighborhood"
    79#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_PROP
    80#define HEUR_PRIORITY 5000
    81#define HEUR_FREQ 0
    82#define HEUR_FREQOFS 0
    83#define HEUR_MAXDEPTH -1
    84#define HEUR_TIMING SCIP_HEURTIMING_BEFORENODE
    85#define HEUR_USESSUBSCIP TRUE /**< does the heuristic use a secondary SCIP instance? */
    86
    87#define DEFAULT_MAXNODES 5000LL /**< maximum number of nodes to regard in the subproblem */
    88#define DEFAULT_MININTFIXINGRATE 0.65 /**< minimum percentage of integer variables that have to be fixed */
    89#define DEFAULT_MINMIPFIXINGRATE 0.65 /**< minimum percentage of variables that have to be fixed within sub-SCIP
    90 * (integer and continuous) */
    91#define DEFAULT_MINIMPROVE 0.01 /**< factor by which clique heuristic should at least improve the
    92 * incumbent */
    93#define DEFAULT_MINNODES 500LL /**< minimum number of nodes to regard in the subproblem */
    94#define DEFAULT_NODESOFS 500LL /**< number of nodes added to the contingent of the total nodes */
    95#define DEFAULT_NODESQUOT 0.1 /**< subproblem nodes in relation to nodes of the original problem */
    96#define DEFAULT_MAXPROPROUNDS 2 /**< maximum number of propagation rounds during probing */
    97#define DEFAULT_MAXBACKTRACKS 10 /**< maximum number of backtracks during the fixing process */
    98#define DEFAULT_COPYCUTS TRUE /**< should all active cuts from the cutpool of the
    99 * original scip be copied to constraints of the subscip */
    100#define DEFAULT_USELOCKFIXINGS FALSE /**< should more variables be fixed based on variable locks if
    101 * the fixing rate was not reached? */
    102
    103
    104/*
    105 * Data structures
    106 */
    107
    108/** primal heuristic data */
    109struct SCIP_HeurData
    110{
    111 SCIP_Longint maxnodes; /**< maximum number of nodes to regard in the subproblem */
    112 SCIP_Longint minnodes; /**< minimum number of nodes to regard in the subproblem */
    113 SCIP_Longint nodesofs; /**< number of nodes added to the contingent of the total nodes */
    114 SCIP_Longint usednodes; /**< nodes already used by clique heuristic in earlier calls */
    115 SCIP_Real minintfixingrate; /**< minimum percentage of integer variables that have to be fixed */
    116 SCIP_Real minmipfixingrate; /**< minimum percentage of variables that have to be fixed within sub-SCIP
    117 * (integer and continuous) */
    118 SCIP_Real minimprove; /**< factor by which clique heuristic should at least improve the incumbent */
    119 SCIP_Real nodesquot; /**< subproblem nodes in relation to nodes of the original problem */
    120 int maxproprounds; /**< maximum number of propagation rounds during probing */
    121 int maxbacktracks; /**< maximum number of backtracks during the fixing process */
    122 SCIP_Bool copycuts; /**< should all active cuts from cutpool be copied to constraints in
    123 * subproblem?
    124 */
    125 SCIP_Bool uselockfixings; /**< should more variables be fixed based on variable locks if
    126 * the fixing rate was not reached?
    127 */
    128};
    129
    130/*
    131 * Local methods
    132 */
    133
    134/** comparison method for sorting cliques by their size */
    135static
    136SCIP_DECL_SORTINDCOMP(compCliquesSize)
    137{
    138 int* cliquesizes = (int*)dataptr;
    139
    140 return cliquesizes[ind2] - cliquesizes[ind1];
    141}
    142
    143static
    145 SCIP_CLIQUE* clique
    146 )
    147{
    148 SCIP_VAR** cliquevars;
    149 SCIP_VAR* var;
    150 int ncliquevars;
    151 int nunfixed = 0;
    152 int v;
    153
    154 ncliquevars = SCIPcliqueGetNVars(clique);
    155 cliquevars = SCIPcliqueGetVars(clique);
    156
    157 for( v = 0; v < ncliquevars; ++v )
    158 {
    159 var = cliquevars[v];
    160
    161 /* is variable unfixed? */
    162 if( SCIPvarGetUbLocal(var) > SCIPvarGetLbLocal(var) + 0.5 )
    163 ++nunfixed;
    164 }
    165
    166 return nunfixed;
    167}
    168
    169/** apply clique fixing using probing */
    170static
    172 SCIP* scip, /**< original SCIP data structure */
    173 SCIP_HEURDATA* heurdata, /**< structure containing heurdata */
    174 SCIP_Bool enabledconflicts, /**< was conflict analysis enabled before the heuristic call? */
    175 SCIP_VAR** onefixvars, /**< array to store all variables which are fixed to one in the cliques */
    176 SCIP_Shortbool* onefixvals, /**< array to store the values of all variables fixed to one in the cliques */
    177 int* nonefixvars, /**< pointer to store the number of variables fixed to one */
    178 SCIP_Bool* cutoff /**< pointer to store whether the propagation stopped with infeasibility */
    179 )
    180{
    181 SCIP_CLIQUE** cliques;
    182 SCIP_CLIQUE* clique;
    183 SCIP_VAR** cliquevars;
    184 SCIP_VAR* var;
    185 SCIP_Bool* cliquevals;
    186 SCIP_Bool* propagated;
    187 int* cliquesizes;
    188 int* permutation;
    189 SCIP_Real bestobj;
    190 SCIP_Real obj;
    191 SCIP_Bool alreadyone;
    192 SCIP_Bool newnode;
    193 int probingdepthofonefix;
    194 int ncliquevars;
    195 int ncliques;
    196 int bestpos;
    197 int firstclique;
    198 int bestclique;
    199 int cliquesize;
    200 int bestcliquesize;
    201 int nbacktracks = 0;
    202 int v = 0;
    203 int c;
    204 int i;
    205
    206 assert(scip != NULL);
    207 assert(heurdata != NULL);
    208 assert(onefixvars != NULL);
    209 assert(nonefixvars != NULL);
    210 assert(cutoff != NULL);
    211
    212 cliques = SCIPgetCliques(scip);
    213 ncliques = SCIPgetNCliques(scip);
    214
    215 /* allocate memory */
    216 SCIP_CALL( SCIPallocBufferArray(scip, &cliquesizes, ncliques) );
    217 SCIP_CALL( SCIPallocBufferArray(scip, &permutation, ncliques) );
    218 SCIP_CALL( SCIPallocClearBufferArray(scip, &propagated, ncliques) );
    219
    220 for( c = ncliques - 1; c >= 0; --c )
    221 {
    222 cliquesizes[c] = SCIPcliqueGetNVars(cliques[c]);
    223 }
    224
    225 SCIPsort(permutation, compCliquesSize, (void*)cliquesizes, ncliques);
    226
    227#ifndef NDEBUG
    228 for( c = ncliques - 1; c >= 1; --c )
    229 {
    230 assert(cliquesizes[permutation[c]] <= cliquesizes[permutation[c-1]]);
    231 }
    232#endif
    233
    234 *cutoff = FALSE;
    235 probingdepthofonefix = 0;
    236 firstclique = 0;
    237
    239
    240 /* @todo maybe try to fix more than one variable to one in each probing node, to gain faster results */
    241 for( c = 0; c < ncliques; ++c )
    242 {
    243 bestpos = -1;
    244 bestobj = SCIPinfinity(scip);
    245 alreadyone = FALSE;
    246 newnode = FALSE;
    247
    248 bestclique = firstclique;
    249
    250 if( bestclique >= ncliques )
    251 break;
    252
    253 bestcliquesize = getCliqueUnfixedVars(cliques[permutation[bestclique]]);
    254 assert(!propagated[permutation[bestclique]]);
    255
    256 for( i = firstclique + 1; i < ncliques; ++i)
    257 {
    258 if( cliquesizes[permutation[i]] < bestcliquesize )
    259 break;
    260
    261 if( propagated[permutation[i]] )
    262 continue;
    263
    264 cliquesize = getCliqueUnfixedVars(cliques[permutation[i]]);
    265
    266 if( cliquesize > bestcliquesize )
    267 {
    268 bestclique = i;
    269 bestcliquesize = cliquesize;
    270 }
    271 else if( cliquesize == 0 )
    272 {
    273 propagated[permutation[i]] = TRUE;
    274 }
    275 }
    276 clique = cliques[permutation[bestclique]];
    277 propagated[permutation[bestclique]] = TRUE;
    278
    279 while( firstclique < ncliques && propagated[permutation[firstclique]] )
    280 ++firstclique;
    281
    282 ncliquevars = SCIPcliqueGetNVars(clique);
    283 cliquevars = SCIPcliqueGetVars(clique);
    284 cliquevals = SCIPcliqueGetValues(clique);
    285
    286 for( v = 0; v < ncliquevars; ++v )
    287 {
    288 var = cliquevars[v];
    289
    290 /* variable is already fixed */
    291 if( SCIPvarGetUbLocal(var) < SCIPvarGetLbLocal(var) + 0.5 )
    292 {
    293 SCIPdebugMsg(scip, "<%s> is already fixed to %g\n", SCIPvarGetName(var), SCIPvarGetUbLocal(var));
    294
    295 /* clique variable is fixed to 1 */
    296 if( cliquevals[v] == (SCIPvarGetLbLocal(var) > 0.5) )
    297 {
    298 assert(!alreadyone);
    299 alreadyone = TRUE;
    300 break;
    301 }
    302 continue;
    303 }
    304
    305 obj = cliquevals[v] ? SCIPvarGetObj(var) : -SCIPvarGetObj(var);
    306
    307 /* @todo use a tiebreaker (locks?) */
    308 if( obj < bestobj )
    309 {
    310 /* variable is not the best one in the clique anymore, fix it to 0 */
    311 if( bestpos >= 0 )
    312 {
    313 assert(bestpos < ncliquevars);
    314 if( cliquevals[bestpos] )
    315 {
    316 SCIP_CALL( SCIPfixVarProbing(scip, cliquevars[bestpos], 0.0) );
    317 }
    318 else
    319 {
    320 SCIP_CALL( SCIPfixVarProbing(scip, cliquevars[bestpos], 1.0) );
    321 }
    322 SCIPdebugMsg(scip, "fixed <%s> to %g\n", SCIPvarGetName(cliquevars[bestpos]), SCIPvarGetUbLocal(cliquevars[bestpos]));
    323 newnode = TRUE;
    324 }
    325
    326 bestobj = obj;
    327 bestpos = v;
    328 }
    329 /* variable is not the best one in the clique, fix it to 0 */
    330 else
    331 {
    332 assert(bestpos >= 0);
    333
    334 if( cliquevals[v] )
    335 {
    336 SCIP_CALL( SCIPfixVarProbing(scip, var, 0.0) );
    337 }
    338 else
    339 {
    340 SCIP_CALL( SCIPfixVarProbing(scip, var, 1.0) );
    341 }
    342 SCIPdebugMsg(scip, "fixed <%s> to %g\n", SCIPvarGetName(var), SCIPvarGetUbLocal(var));
    343 newnode = TRUE;
    344 }
    345 }
    346 /* we found a variable in the clique which is already fixed to 1 */
    347 if( alreadyone )
    348 {
    349 /* fix (so far) best candidate to 0 */
    350 if( bestpos >= 0 )
    351 {
    352 assert(bestpos < ncliquevars);
    353 if( cliquevals[bestpos] )
    354 {
    355 SCIP_CALL( SCIPfixVarProbing(scip, cliquevars[bestpos], 0.0) );
    356 }
    357 else
    358 {
    359 SCIP_CALL( SCIPfixVarProbing(scip, cliquevars[bestpos], 1.0) );
    360 }
    361 SCIPdebugMsg(scip, "fixed <%s> to %g\n", SCIPvarGetName(cliquevars[bestpos]), SCIPvarGetUbLocal(cliquevars[bestpos]));
    362 newnode = TRUE;
    363 }
    364
    365 /* fix all variables not yet processed to 0 */
    366 for( ; v < ncliquevars; ++v )
    367 {
    368 var = cliquevars[v];
    369
    370 if( SCIPvarGetUbLocal(var) < SCIPvarGetLbLocal(var) + 0.5 )
    371 continue;
    372
    373 if( cliquevals[v] )
    374 {
    375 SCIP_CALL( SCIPfixVarProbing(scip, var, 0.0) );
    376 }
    377 else
    378 {
    379 SCIP_CALL( SCIPfixVarProbing(scip, var, 1.0) );
    380 }
    381 SCIPdebugMsg(scip, "fixed <%s> to %g\n", SCIPvarGetName(var), SCIPvarGetUbLocal(var));
    382 newnode = TRUE;
    383 }
    384 }
    385 /* fix the best variable to 1 */
    386 else if( bestpos >= 0 )
    387 {
    388 assert(bestpos < ncliquevars);
    389 onefixvars[*nonefixvars] = cliquevars[bestpos];
    390 probingdepthofonefix = SCIPgetProbingDepth(scip);
    391
    392 /* @todo should we even fix the best candidate to 1? */
    393 if( cliquevals[bestpos] )
    394 {
    395 SCIP_CALL( SCIPfixVarProbing(scip, cliquevars[bestpos], 1.0) );
    396 onefixvals[*nonefixvars] = 1;
    397 }
    398 else
    399 {
    400 SCIP_CALL( SCIPfixVarProbing(scip, cliquevars[bestpos], 0.0) );
    401 onefixvals[*nonefixvars] = 0;
    402 }
    403 SCIPdebugMsg(scip, "fixed <%s> to %g*\n", SCIPvarGetName(cliquevars[bestpos]), SCIPvarGetUbLocal(cliquevars[bestpos]));
    404 ++(*nonefixvars);
    405 newnode = TRUE;
    406 }
    407
    408 if( newnode )
    409 {
    410 /* propagate fixings */
    411 SCIP_CALL( SCIPpropagateProbing(scip, heurdata->maxproprounds, cutoff, NULL) );
    412
    413 SCIPdebugMsg(scip, "propagate fixings of clique %d: cutoff=%u\n", c, *cutoff);
    414
    415 if( SCIPisStopped(scip) )
    416 break;
    417
    418 /* stop if we reached the depth limit */
    420 break;
    421
    422 /* probing detected infeasibility: backtrack */
    423 if( *cutoff )
    424 {
    425 if( *nonefixvars > 0 )
    426 {
    427 if( probingdepthofonefix > 0 )
    428 {
    429 SCIP_CALL( SCIPbacktrackProbing(scip, probingdepthofonefix - 1) );
    430 probingdepthofonefix = 0;
    431 ++nbacktracks;
    432
    433 /* because of the limited number of propagation rounds, it may happen that conflict analysis finds a
    434 * valid global fixing for the last fixed variable that conflicts with applying the reverse fixing
    435 * after backtracking; in that case, we ran into a deadend and stop
    436 */
    437 if( SCIPvarGetLbLocal(onefixvars[*nonefixvars - 1]) < 1.5 - onefixvals[*nonefixvars - 1]
    438 && SCIPvarGetUbLocal(onefixvars[*nonefixvars - 1]) > 0.5 - onefixvals[*nonefixvars - 1] )
    439 {
    440 /* fix the last variable, which was fixed to 1 and led to the cutoff, to 0 */
    441 SCIP_CALL( SCIPfixVarProbing(scip, onefixvars[*nonefixvars - 1], 1.0 - onefixvals[*nonefixvars - 1]) );
    442 --(*nonefixvars);
    443
    444 /* propagate fixings */
    445 SCIP_CALL( SCIPpropagateProbing(scip, heurdata->maxproprounds, cutoff, NULL) );
    446
    447 SCIPdebugMsg(scip, "backtrack %d was %sfeasible\n", nbacktracks, (*cutoff ? "in" : ""));
    448 }
    449#ifndef NDEBUG
    450 else
    451 assert(*cutoff == TRUE);
    452#endif
    453 }
    454 if( *cutoff )
    455 {
    456 SCIPdebugMsg(scip, "probing was infeasible after %d backtracks\n", nbacktracks);
    457#ifndef NOCONFLICT
    458 if( enabledconflicts )
    459 {
    460 SCIP_CONS* conflictcons;
    461 char consname[SCIP_MAXSTRLEN];
    462
    463 /* create own conflict */
    464 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "conf%" SCIP_LONGINT_FORMAT "", SCIPgetNNodes(scip));
    465
    466 /* get variables for the conflict */
    467 for( i = 0; i < *nonefixvars; ++i )
    468 {
    469 /* if the variable was fixed to 1 by the heuristic, get its negated variable */
    470 if( onefixvals[i] )
    471 {
    472 SCIP_CALL( SCIPgetNegatedVar(scip, onefixvars[i], &onefixvars[i]) );
    473 }
    474 }
    475
    476 /* create conflict constraint */
    477 SCIP_CALL( SCIPcreateConsLogicor(scip, &conflictcons, consname, *nonefixvars, onefixvars,
    479 SCIPdebugPrintCons(scip, conflictcons, NULL);
    481 }
    482#endif
    483 break;
    484 }
    485 else if( nbacktracks > heurdata->maxbacktracks )
    486 {
    487 SCIPdebugMsg(scip, "interrupt probing after %d backtracks\n", nbacktracks);
    488 break;
    489 }
    490 }
    491 /* we had a cutoff without a single one-fixing, so the current problem seems to be infeasible already */
    492 else
    493 break;
    494 }
    495
    497 }
    498 }
    499 assert((*nonefixvars > 0) || probingdepthofonefix == 0 );
    500
    501 SCIPfreeBufferArray(scip, &propagated);
    502 SCIPfreeBufferArray(scip, &permutation);
    503 SCIPfreeBufferArray(scip, &cliquesizes);
    504
    505 SCIPdebugMsg(scip, "fixed %d of %d variables in probing\n", v, SCIPgetNVars(scip) - SCIPgetNContVars(scip));
    506 SCIPdebugMsg(scip, "applied %d of %d cliques in probing\n", c, ncliques);
    507 SCIPdebugMsg(scip, "probing was %sfeasible\n", (*cutoff) ? "in" : "");
    508
    509 return SCIP_OKAY;
    510}
    511
    512/*
    513 * Callback methods of primal heuristic
    514 */
    515
    516/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
    517static
    518SCIP_DECL_HEURCOPY(heurCopyClique)
    519{ /*lint --e{715}*/
    520 assert(scip != NULL);
    521 assert(heur != NULL);
    522
    524
    525 /* call inclusion method of primal heuristic */
    527
    528 return SCIP_OKAY;
    529}
    530
    531/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
    532static
    533SCIP_DECL_HEURFREE(heurFreeClique)
    534{ /*lint --e{715}*/
    535 SCIP_HEURDATA* heurdata;
    536
    537 assert(heur != NULL);
    538 assert(scip != NULL);
    539
    541
    542 /* free heuristic data */
    543 heurdata = SCIPheurGetData(heur);
    544 assert(heurdata != NULL);
    545
    546 SCIPfreeBlockMemory(scip, &heurdata);
    547 SCIPheurSetData(heur, NULL);
    548
    549 return SCIP_OKAY;
    550}
    551
    552
    553/** initialization method of primal heuristic (called after problem was transformed) */
    554static
    555SCIP_DECL_HEURINIT(heurInitClique)
    556{ /*lint --e{715}*/
    557 SCIP_HEURDATA* heurdata;
    558
    559 assert(heur != NULL);
    560 assert(scip != NULL);
    561
    563
    564 /* reset heuristic data */
    565 heurdata = SCIPheurGetData(heur);
    566 assert(heurdata != NULL);
    567
    568 heurdata->usednodes = 0;
    569
    570 return SCIP_OKAY;
    571}
    572
    573/** execution method of primal heuristic */
    574static
    575SCIP_DECL_HEUREXEC(heurExecClique)
    576{ /*lint --e{715}*/
    577 SCIP_HEURDATA* heurdata;
    578 SCIP_VAR** vars;
    579 SCIP_Real lowerbound;
    580 int nvars;
    581 int nbinvars;
    582 int oldnpscands;
    583 int npscands;
    584 int i;
    585 SCIP_Bool cutoff;
    586 SCIP_Bool lperror;
    587
    588 SCIP_VAR** onefixvars;
    589 SCIP_Shortbool* onefixvals;
    590 int nonefixvars;
    591 SCIP_Bool enabledconflicts;
    592 SCIP_LPSOLSTAT lpstatus;
    593 SCIP_CONS* conflictcons;
    594 SCIP_Bool solvelp;
    595 char consname[SCIP_MAXSTRLEN];
    596
    597 SCIP_Longint nstallnodes;
    598
    599 assert(heur != NULL);
    600 assert(scip != NULL);
    601 assert(result != NULL);
    602
    604
    605 *result = SCIP_DIDNOTRUN;
    606
    607 /* get heuristic's data */
    608 heurdata = SCIPheurGetData(heur);
    609 assert(heurdata != NULL);
    610
    611 nbinvars = SCIPgetNBinVars(scip);
    612
    613 if( nbinvars < 2 )
    614 return SCIP_OKAY;
    615
    616 /* check for necessary information to apply this heuristic */
    617 if( SCIPgetNCliques(scip) == 0 )
    618 return SCIP_OKAY;
    619
    620 lowerbound = SCIPgetLowerbound(scip);
    621
    622 /* calculate the maximal number of branching nodes until heuristic is aborted */
    623 nstallnodes = (SCIP_Longint)(heurdata->nodesquot * SCIPgetNNodes(scip));
    624
    625 /* reward clique heuristic if it succeeded often */
    626 nstallnodes = (SCIP_Longint)(nstallnodes * 3.0 * (SCIPheurGetNBestSolsFound(heur)+1.0)/(SCIPheurGetNCalls(heur) + 1.0));
    627 nstallnodes -= 100 * SCIPheurGetNCalls(heur); /* count the setup costs for the sub-MIP as 100 nodes */
    628 nstallnodes += heurdata->nodesofs;
    629
    630 /* determine the node limit for the current process */
    631 nstallnodes -= heurdata->usednodes;
    632 nstallnodes = MIN(nstallnodes, heurdata->maxnodes);
    633
    634 /* check whether we have enough nodes left to call subproblem solving */
    635 if( nstallnodes < heurdata->minnodes )
    636 {
    637 SCIPdebugMsg(scip, "skipping " HEUR_NAME ": nstallnodes=%" SCIP_LONGINT_FORMAT ", minnodes=%" SCIP_LONGINT_FORMAT "\n", nstallnodes, heurdata->minnodes);
    638 return SCIP_OKAY;
    639 }
    640
    641 oldnpscands = SCIPgetNPseudoBranchCands(scip);
    642 onefixvars = NULL;
    643 onefixvals = NULL;
    644
    645 /* disable conflict analysis, because we can it better than SCIP itself, cause we have more information */
    646 SCIP_CALL( SCIPgetBoolParam(scip, "conflict/enable", &enabledconflicts) );
    647
    648 if( !SCIPisParamFixed(scip, "conflict/enable") )
    649 {
    650 SCIP_CALL( SCIPsetBoolParam(scip, "conflict/enable", FALSE) );
    651 }
    652
    653 solvelp = SCIPhasCurrentNodeLP(scip);
    654
    655 if( !SCIPisLPConstructed(scip) && solvelp )
    656 {
    657 SCIP_CALL( SCIPconstructLP(scip, &cutoff) );
    658
    659 /* manually cut off the node if the LP construction detected infeasibility (heuristics cannot return such a
    660 * result); the cutoff result is safe to use in exact solving mode, but we don't have enough information to
    661 * give a certificate for the cutoff
    662 */
    663 if( cutoff && !SCIPisCertified(scip) )
    664 {
    666 goto TERMINATE;
    667 }
    668
    670 }
    671
    672 /* get number of possible binary variables */
    673 nbinvars = SCIPgetNVars(scip) - SCIPgetNContVars(scip);
    674 assert(nbinvars >= 2);
    675
    676 *result = SCIP_DIDNOTFIND;
    677
    678 /* start probing */
    680
    681#ifdef COLLECTSTATISTICS
    683#endif
    684
    685 /* allocate memory for all variables which will be fixed to one during probing */
    686 SCIP_CALL( SCIPallocBufferArray(scip, &onefixvars, nbinvars) );
    687 SCIP_CALL( SCIPallocBufferArray(scip, &onefixvals, nbinvars) );
    688 nonefixvars = 0;
    689
    690 /* apply fixings due to clique information */
    691 SCIP_CALL( applyCliqueFixings(scip, heurdata, enabledconflicts, onefixvars, onefixvals, &nonefixvars, &cutoff) );
    692
    693 if( cutoff || SCIPisStopped(scip) )
    694 goto TERMINATE;
    695
    696 /* check that we had enough fixings */
    698
    699 SCIPdebugMsg(scip, "npscands=%d, oldnpscands=%d, heurdata->minintfixingrate=%g\n", npscands, oldnpscands, heurdata->minintfixingrate);
    700
    701 if( npscands > oldnpscands * (1.0 - heurdata->minintfixingrate) )
    702 {
    703 if( heurdata->uselockfixings && npscands <= 2.0 * oldnpscands * (1.0 - heurdata->minintfixingrate) )
    704 {
    705 SCIP_Bool allrowsfulfilled = FALSE;
    706
    707 SCIP_CALL( SCIPapplyLockFixings(scip, NULL, &cutoff, &allrowsfulfilled) );
    708
    709 if( cutoff || SCIPisStopped(scip) )
    710 {
    711 SCIPdebugMsg(scip, "cutoff or timeout in locks fixing\n");
    712 goto TERMINATE;
    713 }
    714
    716
    717 SCIPdebugMsg(scip, "after lockfixings: npscands=%d, oldnpscands=%d, allrowsfulfilled=%u, heurdata->minintfixingrate=%g\n",
    718 npscands, oldnpscands, allrowsfulfilled, heurdata->minintfixingrate);
    719
    720 if( !allrowsfulfilled && npscands > oldnpscands * (1 - heurdata->minintfixingrate) )
    721 {
    722 SCIPdebugMsg(scip, "--> too few fixings\n");
    723
    724 goto TERMINATE;
    725 }
    726 }
    727 else
    728 {
    729 SCIPdebugMsg(scip, "--> too few fixings\n");
    730
    731 goto TERMINATE;
    732 }
    733 }
    734
    735 /*************************** Probing LP Solving ***************************/
    736
    737 lpstatus = SCIP_LPSOLSTAT_ERROR;
    738 lperror = FALSE;
    739
    740 /* solve lp only if the problem is still feasible */
    741 if( solvelp )
    742 {
    743 char strbuf[SCIP_MAXSTRLEN];
    744 int ncols;
    745
    746 /* print message if relatively large LP is solved from scratch, since this could lead to a longer period during
    747 * which the user sees no output; more detailed probing stats only in debug mode */
    748 ncols = SCIPgetNLPCols(scip);
    749 if( !SCIPisLPSolBasic(scip) && ncols > 1000 )
    750 {
    751 int nunfixedcols = SCIPgetNUnfixedLPCols(scip);
    752
    753 if( nunfixedcols > 0.5 * ncols )
    754 {
    756 "Heuristic " HEUR_NAME " solving LP from scratch with %.1f %% unfixed columns (%d of %d) ...\n",
    757 100.0 * (nunfixedcols / (SCIP_Real)ncols), nunfixedcols, ncols);
    758 }
    759 }
    760 SCIPdebugMsg(scip, "Heuristic " HEUR_NAME " probing LP: %s\n",
    762
    763 /* solve LP; errors in the LP solver should not kill the overall solving process, if the LP is just needed for a
    764 * heuristic. hence in optimized mode, the return code is caught and a warning is printed, only in debug mode,
    765 * SCIP will stop.
    766 */
    767 SCIPdebugMsg(scip, "starting solving clique-lp at time %g\n", SCIPgetSolvingTime(scip));
    768#ifdef NDEBUG
    769 {
    770 SCIP_Bool retstat;
    771 retstat = SCIPsolveProbingLP(scip, -1, &lperror, NULL);
    772 if( retstat != SCIP_OKAY )
    773 {
    774 SCIPwarningMessage(scip, "Error while solving LP in clique heuristic; LP solve terminated with code <%d>\n",
    775 retstat);
    776 }
    777 }
    778#else
    779 SCIP_CALL( SCIPsolveProbingLP(scip, -1, &lperror, NULL) );
    780#endif
    781 SCIPdebugMsg(scip, "ending solving clique-lp at time %g\n", SCIPgetSolvingTime(scip));
    782
    783 lpstatus = SCIPgetLPSolstat(scip);
    784
    785 SCIPdebugMsg(scip, " -> new LP iterations: %" SCIP_LONGINT_FORMAT "\n", SCIPgetNLPIterations(scip));
    786 SCIPdebugMsg(scip, " -> error=%u, status=%d\n", lperror, lpstatus);
    787 }
    788
    789 /* check if this is a feasible solution */
    790 if( lpstatus == SCIP_LPSOLSTAT_OPTIMAL && !lperror )
    791 {
    792 SCIP_SOL* sol;
    793 SCIP_Bool stored;
    794 SCIP_Bool success;
    795
    796 assert(!cutoff);
    797
    798 lowerbound = SCIPgetLPObjval(scip);
    799
    800 /* create a solution from the current LP solution */
    801 SCIP_CALL( SCIPcreateSol(scip, &sol, heur) );
    803
    804 SCIP_CALL( SCIProundSol(scip, sol, &success) );
    805
    806 if( success )
    807 {
    808 SCIPdebugMsg(scip, "clique heuristic found roundable primal solution: obj=%g\n",
    809 SCIPgetSolOrigObj(scip, sol));
    810
    811 /* check solution for feasibility, and add it to solution store if possible.
    812 * Neither integrality nor feasibility of LP rows have to be checked, because they
    813 * are guaranteed by the heuristic at this stage.
    814 */
    815#ifdef SCIP_DEBUG
    816 SCIP_CALL( SCIPtrySol(scip, sol, TRUE, TRUE, TRUE, TRUE, TRUE, &stored) );
    817#else
    818 SCIP_CALL( SCIPtrySol(scip, sol, FALSE, FALSE, TRUE, FALSE, FALSE, &stored) );
    819#endif
    820
    821 if( stored )
    822 {
    823 SCIPdebugMsg(scip, "found feasible solution:\n");
    825 *result = SCIP_FOUNDSOL;
    826 }
    827
    828 SCIP_CALL( SCIPfreeSol(scip, &sol) );
    829
    830 /* we found a solution, so we are done */
    831 goto TERMINATE;
    832 }
    833
    834 SCIP_CALL( SCIPfreeSol(scip, &sol) );
    835 }
    836 /*************************** END Probing LP Solving ***************************/
    837
    838 /*************************** Create Conflict ***************************/
    839 if( enabledconflicts && SCIPallColsInLP(scip) &&
    840 (lpstatus == SCIP_LPSOLSTAT_INFEASIBLE || lpstatus == SCIP_LPSOLSTAT_OBJLIMIT) )
    841 {
    842#ifndef NOCONFLICT
    843 /* create own conflict */
    844 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "conf%" SCIP_LONGINT_FORMAT "", SCIPgetNNodes(scip));
    845
    846 /* get variables for the conflict */
    847 for( i = 0; i < nonefixvars; ++i )
    848 {
    849 /* if the variable was fixed to 1 by the heuristic, get its negated variable */
    850 if( onefixvals[i] )
    851 {
    852 SCIP_CALL( SCIPgetNegatedVar(scip, onefixvars[i], &onefixvars[i]) );
    853 }
    854 }
    855
    856 /* create conflict constraint */
    857 SCIP_CALL( SCIPcreateConsLogicor(scip, &conflictcons, consname, nonefixvars, onefixvars,
    859 SCIPdebugPrintCons(scip, conflictcons, NULL);
    861#endif
    862 goto TERMINATE;
    863 }
    864 /*************************** End Conflict ***************************/
    865
    866 /*************************** Start Subscip Solving ***************************/
    867 /* no solution has been found yet and the subproblem is still feasible --> fix all other variables by subscip if
    868 * necessary
    869 */
    870 if( !lperror )
    871 {
    872 SCIP* subscip;
    873 SCIP_VAR** subvars;
    874 SCIP_HASHMAP* varmap;
    875 SCIP_Bool valid;
    876
    877 /* check whether there is enough time and memory left */
    879
    880 if( !valid )
    881 goto TERMINATE;
    882
    883 /* get all variables */
    884 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
    885
    886 /* create subproblem */
    887 SCIP_CALL( SCIPcreate(&subscip) );
    888
    889 /* allocate temporary memory for subscip variables */
    890 SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
    891
    892 /* create the variable mapping hash map */
    893 SCIP_CALL( SCIPhashmapCreate(&varmap, SCIPblkmem(subscip), nvars) );
    894
    895 SCIP_CALL( SCIPcopyConsCompression(scip, subscip, varmap, NULL, "_clique", NULL, NULL, 0, FALSE, FALSE, FALSE,
    896 TRUE, &valid) );
    897
    898 if( heurdata->copycuts )
    899 {
    900 /* copies all active cuts from cutpool of sourcescip to linear constraints in targetscip */
    901 SCIP_CALL( SCIPcopyCuts(scip, subscip, varmap, NULL, FALSE, NULL) );
    902 }
    903
    904 for( i = 0; i < nvars; i++ )
    905 subvars[i] = (SCIP_VAR*) SCIPhashmapGetImage(varmap, vars[i]);
    906
    907 /* free hash map */
    908 SCIPhashmapFree(&varmap);
    909
    910 /* do not abort subproblem on CTRL-C */
    911 SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
    912
    913#ifdef SCIP_DEBUG
    914 /* for debugging, enable full output */
    915 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) );
    916 SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 100000000) );
    917#else
    918 /* disable statistic timing inside sub SCIP and output to console */
    919 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
    920 SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
    921#endif
    922
    923 /* set limits for the subproblem */
    924 SCIP_CALL( SCIPcopyLimits(scip, subscip) );
    925 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/stallnodes", nstallnodes) );
    926 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", heurdata->maxnodes) );
    927
    928 /* speed up sub-SCIP by not checking dual LP feasibility */
    929 SCIP_CALL( SCIPsetBoolParam(subscip, "lp/checkdualfeas", FALSE) );
    930
    931 /* forbid call of heuristics and separators solving sub-CIPs */
    932 SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );
    933
    934 /* disable cutting plane separation */
    936
    937 /* disable expensive presolving */
    939
    940 /* use inference branching */
    941 if( SCIPfindBranchrule(subscip, "inference") != NULL && !SCIPisParamFixed(subscip, "branching/inference/priority") )
    942 {
    943 SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
    944 }
    945
    946 /* if there is already a solution, add an objective cutoff */
    947 if( SCIPgetNSols(scip) > 0 )
    948 {
    949 SCIP_Real upperbound;
    950 SCIP_Real minimprove;
    951 SCIP_Real cutoffbound;
    952
    953 minimprove = heurdata->minimprove;
    955
    956 upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);
    957
    958 if( !SCIPisInfinity(scip, -1.0 * lowerbound) )
    959 {
    960 cutoffbound = (1-minimprove) * SCIPgetUpperbound(scip) + minimprove * lowerbound;
    961 }
    962 else
    963 {
    964 if( SCIPgetUpperbound ( scip ) >= 0 )
    965 cutoffbound = (1 - minimprove) * SCIPgetUpperbound(scip);
    966 else
    967 cutoffbound = (1 + minimprove) * SCIPgetUpperbound(scip);
    968 }
    969 cutoffbound = MIN(upperbound, cutoffbound);
    970 SCIP_CALL( SCIPsetObjlimit(subscip, cutoffbound) );
    971 SCIPdebugMsg(scip, "setting objlimit for subscip to %g\n", cutoffbound);
    972 }
    973
    974 SCIPdebugMsg(scip, "starting solving clique-submip at time %g\n", SCIPgetSolvingTime(scip));
    975
    976 /* solve the subproblem */
    977 /* Errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
    978 * Hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
    979 */
    980 SCIP_CALL_ABORT( SCIPpresolve(subscip) );
    981
    982 SCIPdebugMsg(scip, "clique 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));
    983
    984 /* after presolving, we should have at least reached a certain fixing rate over ALL variables (including continuous)
    985 * to ensure that not only the MIP but also the LP relaxation is easy enough
    986 */
    987 if( ((nvars - SCIPgetNVars(subscip)) / (SCIP_Real)nvars) >= heurdata->minmipfixingrate )
    988 {
    989 SCIP_Bool success;
    990
    991 SCIPdebugMsg(scip, "solving subproblem: nstallnodes=%" SCIP_LONGINT_FORMAT ", maxnodes=%" SCIP_LONGINT_FORMAT "\n", nstallnodes, heurdata->maxnodes);
    992
    993 SCIP_CALL_ABORT( SCIPsolve(subscip) );
    995
    996 SCIPdebugMsg(scip, "ending solving clique-submip at time %g, status = %d\n", SCIPgetSolvingTime(scip), SCIPgetStatus(subscip));
    997
    998 /* check, whether a solution was found; due to numerics, it might happen that not all solutions are feasible ->
    999 * try all solutions until one was accepted
    1000 */
    1001 SCIP_CALL( SCIPtranslateSubSols(scip, subscip, heur, subvars, &success, NULL) );
    1002 if( success )
    1003 *result = SCIP_FOUNDSOL;
    1004
    1005#ifndef NOCONFLICT
    1006 /* if subscip was infeasible, add a conflict */
    1007 if( SCIPgetStatus(subscip) == SCIP_STATUS_INFEASIBLE )
    1008 {
    1009 /* create own conflict */
    1010 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "conf%" SCIP_LONGINT_FORMAT "", SCIPgetNNodes(scip));
    1011
    1012 /* get variables for the conflict */
    1013 for( i = 0; i < nonefixvars; ++i )
    1014 {
    1015 /* if the variable was fixed to 1 by the heuristic, get its negated variable */
    1016 if( onefixvals[i] )
    1017 {
    1018 SCIP_CALL( SCIPgetNegatedVar(scip, onefixvars[i], &onefixvars[i]) );
    1019 }
    1020 }
    1021
    1022 /* create conflict constraint */
    1023 SCIP_CALL( SCIPcreateConsLogicor(scip, &conflictcons, consname, nonefixvars, onefixvars,
    1026 SCIPdebugPrintCons(scip, conflictcons, NULL);
    1027 SCIP_CALL( SCIPreleaseCons(scip, &conflictcons) );
    1028 }
    1029#endif
    1030 }
    1031
    1032#ifdef SCIP_DEBUG
    1033 SCIP_CALL( SCIPprintStatistics(subscip, NULL) );
    1034#endif
    1035
    1036 /* free subproblem */
    1037 SCIPfreeBufferArray(scip, &subvars);
    1038 SCIP_CALL( SCIPfree(&subscip) );
    1039 }
    1040
    1041 /*************************** End Subscip Solving ***************************/
    1042
    1043 TERMINATE:
    1044
    1045 /* reset the conflict analysis */
    1046 if( !SCIPisParamFixed(scip, "conflict/enable") )
    1047 {
    1048 SCIP_CALL( SCIPsetBoolParam(scip, "conflict/enable", enabledconflicts) );
    1049 }
    1050
    1051 /* free conflict variables */
    1052 SCIPfreeBufferArrayNull(scip, &onefixvals);
    1053 SCIPfreeBufferArrayNull(scip, &onefixvars);
    1054
    1055 /* end probing */
    1056 if( SCIPinProbing(scip) )
    1057 {
    1059 }
    1060
    1061 return SCIP_OKAY;
    1062}
    1063
    1064/*
    1065 * primal heuristic specific interface methods
    1066 */
    1067
    1068/** creates the clique primal heuristic and includes it in SCIP */
    1070 SCIP* scip /**< SCIP data structure */
    1071 )
    1072{
    1073 SCIP_HEURDATA* heurdata;
    1074 SCIP_HEUR* heur;
    1075
    1076 /* create clique primal heuristic data */
    1077 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    1078
    1079 /* include primal heuristic */
    1082 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecClique, heurdata) );
    1083
    1084 assert(heur != NULL);
    1085
    1086 /* primal heuristic is safe to use in exact solving mode */
    1087 SCIPheurMarkExact(heur);
    1088
    1089 /* set non-NULL pointers to callback methods */
    1090 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyClique) );
    1091 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeClique) );
    1092 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitClique) );
    1093
    1094 /* add clique primal heuristic parameters */
    1095
    1096 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minintfixingrate",
    1097 "minimum percentage of integer variables that have to be fixable",
    1098 &heurdata->minintfixingrate, FALSE, DEFAULT_MININTFIXINGRATE, 0.0, 1.0, NULL, NULL) );
    1099
    1100 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minmipfixingrate",
    1101 "minimum percentage of fixed variables in the sub-MIP",
    1102 &heurdata->minmipfixingrate, FALSE, DEFAULT_MINMIPFIXINGRATE, 0.0, 1.0, NULL, NULL) );
    1103
    1104 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
    1105 "maximum number of nodes to regard in the subproblem",
    1106 &heurdata->maxnodes, TRUE, DEFAULT_MAXNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
    1107
    1108 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/nodesofs",
    1109 "number of nodes added to the contingent of the total nodes",
    1110 &heurdata->nodesofs, FALSE, DEFAULT_NODESOFS, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
    1111
    1112 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/minnodes",
    1113 "minimum number of nodes required to start the subproblem",
    1114 &heurdata->minnodes, TRUE, DEFAULT_MINNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
    1115
    1116 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesquot",
    1117 "contingent of sub problem nodes in relation to the number of nodes of the original problem",
    1118 &heurdata->nodesquot, FALSE, DEFAULT_NODESQUOT, 0.0, 1.0, NULL, NULL) );
    1119
    1120 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprove",
    1121 "factor by which " HEUR_NAME " heuristic should at least improve the incumbent",
    1122 &heurdata->minimprove, TRUE, DEFAULT_MINIMPROVE, 0.0, 1.0, NULL, NULL) );
    1123
    1124 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxproprounds",
    1125 "maximum number of propagation rounds during probing (-1 infinity)",
    1126 &heurdata->maxproprounds, TRUE, DEFAULT_MAXPROPROUNDS, -1, INT_MAX/4, NULL, NULL) );
    1127
    1128 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/copycuts",
    1129 "should all active cuts from cutpool be copied to constraints in subproblem?",
    1130 &heurdata->copycuts, TRUE, DEFAULT_COPYCUTS, NULL, NULL) );
    1131
    1132 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/uselockfixings",
    1133 "should more variables be fixed based on variable locks if the fixing rate was not reached?",
    1134 &heurdata->uselockfixings, TRUE, DEFAULT_USELOCKFIXINGS, NULL, NULL) );
    1135
    1136 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxbacktracks",
    1137 "maximum number of backtracks during the fixing process",
    1138 &heurdata->maxbacktracks, TRUE, DEFAULT_MAXBACKTRACKS, -1, INT_MAX/4, NULL, NULL) );
    1139
    1140 return SCIP_OKAY;
    1141}
    Constraint handler for logicor constraints (equivalent to set covering, but algorithms are suited fo...
    #define NULL
    Definition: def.h:257
    #define SCIP_MAXSTRLEN
    Definition: def.h:278
    #define SCIP_Longint
    Definition: def.h:150
    #define SCIP_MAXTREEDEPTH
    Definition: def.h:306
    #define SCIP_Shortbool
    Definition: def.h:108
    #define SCIP_Bool
    Definition: def.h:100
    #define MIN(x, y)
    Definition: def.h:233
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define SCIP_CALL_ABORT(x)
    Definition: def.h:343
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:157
    #define SCIP_LONGINT_MAX
    Definition: def.h:151
    #define SCIP_CALL(x)
    Definition: def.h:364
    SCIP_RETCODE SCIPcreateConsLogicor(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    SCIP_RETCODE SCIPtranslateSubSols(SCIP *scip, SCIP *subscip, SCIP_HEUR *heur, SCIP_VAR **subvars, SCIP_Bool *success, int *solindex)
    Definition: scip_copy.c:1438
    SCIP_RETCODE SCIPcopyConsCompression(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, const char *suffix, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int nfixedvars, SCIP_Bool global, SCIP_Bool enablepricing, SCIP_Bool threadsafe, SCIP_Bool passmessagehdlr, SCIP_Bool *valid)
    Definition: scip_copy.c:2962
    SCIP_RETCODE SCIPcheckCopyLimits(SCIP *sourcescip, SCIP_Bool *success)
    Definition: scip_copy.c:3250
    SCIP_RETCODE SCIPcopyCuts(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, int *ncutsadded)
    Definition: scip_copy.c:2114
    SCIP_RETCODE SCIPcopyLimits(SCIP *sourcescip, SCIP *targetscip)
    Definition: scip_copy.c:3293
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:767
    SCIP_RETCODE SCIPfree(SCIP **scip)
    Definition: scip_general.c:402
    SCIP_RETCODE SCIPcreate(SCIP **scip)
    Definition: scip_general.c:370
    SCIP_STATUS SCIPgetStatus(SCIP *scip)
    Definition: scip_general.c:562
    int SCIPgetNContVars(SCIP *scip)
    Definition: scip_prob.c:2569
    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
    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
    SCIP_RETCODE SCIPaddConsNode(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode)
    Definition: scip_prob.c:3901
    SCIP_RETCODE SCIPaddConflict(SCIP *scip, SCIP_NODE *node, SCIP_CONS **cons, SCIP_NODE *validnode, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
    Definition: scip_prob.c:3806
    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 SCIPincludeHeurClique(SCIP *scip)
    Definition: heur_clique.c:1069
    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_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    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
    SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
    Definition: scip_heur.c:199
    const char * SCIPheurGetName(SCIP_HEUR *heur)
    Definition: heur.c:1467
    void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
    Definition: heur.c:1378
    SCIP_RETCODE 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_Bool SCIPallColsInLP(SCIP *scip)
    Definition: scip_lp.c:655
    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 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_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:514
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1250
    SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
    Definition: scip_sol.c:2351
    int SCIPgetNSols(SCIP *scip)
    Definition: scip_sol.c:2887
    SCIP_RETCODE SCIProundSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool *success)
    Definition: scip_sol.c:3128
    SCIP_RETCODE SCIPtrySol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
    Definition: scip_sol.c:4017
    SCIP_RETCODE SCIPlinkLPSol(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1293
    SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1890
    SCIP_RETCODE SCIPpresolve(SCIP *scip)
    Definition: scip_solve.c:2425
    SCIP_RETCODE SCIPsolve(SCIP *scip)
    Definition: scip_solve.c:2611
    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_Real SCIPgetSolvingTime(SCIP *scip)
    Definition: scip_timing.c:378
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPsumepsilon(SCIP *scip)
    SCIP_NODE * SCIPgetFocusNode(SCIP *scip)
    Definition: scip_tree.c:72
    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_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24300
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23932
    SCIP_CLIQUE ** SCIPgetCliques(SCIP *scip)
    Definition: scip_var.c:9566
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23299
    SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
    Definition: scip_var.c:2166
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24266
    int SCIPgetNCliques(SCIP *scip)
    Definition: scip_var.c:9512
    void SCIPenableVarHistory(SCIP *scip)
    Definition: scip_var.c:11083
    void SCIPsort(int *perm, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
    Definition: misc.c:5581
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    #define DEFAULT_MININTFIXINGRATE
    Definition: heur_clique.c:88
    #define DEFAULT_NODESQUOT
    Definition: heur_clique.c:95
    #define DEFAULT_NODESOFS
    Definition: heur_clique.c:94
    #define DEFAULT_COPYCUTS
    Definition: heur_clique.c:98
    #define DEFAULT_MAXNODES
    Definition: heur_clique.c:87
    #define HEUR_TIMING
    Definition: heur_clique.c:84
    #define DEFAULT_MINNODES
    Definition: heur_clique.c:93
    static SCIP_DECL_SORTINDCOMP(compCliquesSize)
    Definition: heur_clique.c:136
    #define HEUR_FREQOFS
    Definition: heur_clique.c:82
    #define HEUR_DESC
    Definition: heur_clique.c:78
    static SCIP_DECL_HEURCOPY(heurCopyClique)
    Definition: heur_clique.c:518
    #define HEUR_DISPCHAR
    Definition: heur_clique.c:79
    #define HEUR_MAXDEPTH
    Definition: heur_clique.c:83
    #define HEUR_PRIORITY
    Definition: heur_clique.c:80
    static SCIP_DECL_HEURINIT(heurInitClique)
    Definition: heur_clique.c:555
    #define DEFAULT_MINIMPROVE
    Definition: heur_clique.c:91
    #define HEUR_NAME
    Definition: heur_clique.c:77
    #define DEFAULT_MINMIPFIXINGRATE
    Definition: heur_clique.c:89
    #define DEFAULT_MAXBACKTRACKS
    Definition: heur_clique.c:97
    static SCIP_RETCODE applyCliqueFixings(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_Bool enabledconflicts, SCIP_VAR **onefixvars, SCIP_Shortbool *onefixvals, int *nonefixvars, SCIP_Bool *cutoff)
    Definition: heur_clique.c:171
    static SCIP_DECL_HEUREXEC(heurExecClique)
    Definition: heur_clique.c:575
    static int getCliqueUnfixedVars(SCIP_CLIQUE *clique)
    Definition: heur_clique.c:144
    #define HEUR_FREQ
    Definition: heur_clique.c:81
    #define HEUR_USESSUBSCIP
    Definition: heur_clique.c:85
    #define DEFAULT_USELOCKFIXINGS
    Definition: heur_clique.c:100
    #define DEFAULT_MAXPROPROUNDS
    Definition: heur_clique.c:96
    static SCIP_DECL_HEURFREE(heurFreeClique)
    Definition: heur_clique.c:533
    LNS heuristic using a clique partition to restrict the search neighborhood.
    SCIP_RETCODE SCIPapplyLockFixings(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_Bool *cutoff, SCIP_Bool *allrowsfulfilled)
    Definition: heur_locks.c:194
    locks primal heuristic
    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
    memory allocation routines
    public methods for primal heuristics
    public methods for implications, variable bounds, and cliques
    public methods for message output
    #define SCIPdebug(x)
    Definition: pub_message.h:93
    #define SCIPdebugPrintCons(x, y, z)
    Definition: pub_message.h:102
    public data structures and miscellaneous methods
    methods for sorting joint arrays of various types
    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
    @ SCIP_CONFTYPE_PROPAGATION
    Definition: type_conflict.h:62
    @ SCIP_CONFTYPE_INFEASLP
    Definition: type_conflict.h:63
    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
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_STATUS_INFEASIBLE
    Definition: type_stat.h:44