SCIP

    Solving Constraint Integer Programs

    sepa_flower.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 sepa_flower.c
    26 * @ingroup DEFPLUGINS_SEPA
    27 * @brief flower-inequality separator
    28 * @author Matthias Walter
    29 */
    30
    31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    32
    33#include "scip/sepa_flower.h"
    34#include "scip/cons_and.h"
    35#include "scip/cons_nonlinear.h"
    36#include "scip/struct_scip.h"
    37#include "scip/struct_set.h"
    38#include "scip/set.h"
    39#include "scip/hypergraph.h"
    40
    41
    42#define SEPA_NAME "flower"
    43#define SEPA_DESC "flower cut separator"
    44#define SEPA_PRIORITY 100000
    45#define SEPA_FREQ 1
    46#define SEPA_MAXBOUNDDIST 1.0
    47#define SEPA_USESSUBSCIP FALSE /**< does the separator use a secondary SCIP instance? */
    48#define SEPA_DELAY FALSE /**< should separation method be delayed if other separators found cuts? */
    49
    50#define DEFAULT_MIN_OVERLAPS 1
    51#define DEFAULT_SCAN_AND TRUE
    52#define DEFAULT_SCAN_PRODUCT FALSE
    53#define DEFAULT_MAX_STANDARD 0
    54#define DEFAULT_MAX_ONEFLOWER 10000000
    55#define DEFAULT_MAX_TWOFLOWER 10000000
    56#define DEFAULT_DELAY_STANDARD FALSE
    57#define DEFAULT_MAX_USELESS_ONEFLOWER 1 /**< Number of useless separation rounds after which we stop separating. */
    58#define DEFAULT_MAX_USELESS_TWOFLOWER 1 /**< Number of useless separation rounds after which we stop separating. */
    59
    60/* Define this for quickly testing whether instances are affected at all. */
    61// #define PRINT_HYPERGRAPH_AND_EXIT
    62
    63/* TODO: These old codes shall be removed once the computational comparison with the new ones is published. */
    64// #define USE_OLD_ONEFLOWER_SEPARATION
    65// #define USE_OLD_TWOFLOWER_SEPARATION
    66
    67#ifdef USE_OLD_ONEFLOWER_SEPARATION
    68#define MAXNSEPA_ONEFLOWER_PER_BASE 2 /* Maximum number of inequalities to be separated that have the same base. */
    69#endif /* USE_OLD_ONEFLOWER_SEPARATION */
    70
    71/** data associated with each hypergraph node */
    72struct SCIP_Hypergraph_NodeData
    73{
    74 SCIP_VAR* var; /**< Variable associated with this node. */
    75 SCIP_Real coefscale; /**< Factor to scale a cut's coefficient with; equals 1/ub. */
    76 SCIP_Real solval; /**< Solution value in [0,1]-transformed space. */
    77};
    78
    79/** data associated with each hypergraph edge */
    80struct SCIP_Hypergraph_EdgeData
    81{
    82 SCIP_VAR* var; /**< Variable of the product. */
    83 SCIP_Real coefficient; /**< Coefficient of the product. */
    84 SCIP_Real coefscale; /**< Factor to scale a cut's coefficient with;
    85 ** equals 1/(product of ubs * coefficient). */
    86 SCIP_Real solval; /**< Value of the variable in [0,1]-transformed space. */
    87 SCIP_Real slackval; /**< The slack value of that edge. */
    88};
    89
    90/** data associated with each overlap, i.e., intersection of two edges. */
    91struct SCIP_Hypergraph_OverlapData
    92{
    93 SCIP_Real sumnodecomplements; /**< Sum of 1-z_v for all v in this overlap. */
    94 SCIP_Real minedgecomplement; /**< 1 minus the maximum solution value of any edge incident to this overlap. */
    95 SCIP_HYPERGRAPH_EDGE minedge; /**< An edge for which minedgecomplement is attained. */
    96};
    97
    98
    99/** Separator data. */
    100struct SCIP_SepaData
    101{
    102 int lastrun; /**< Last run for which we constructed a hypergraph. */
    103 SCIP_NODE* lastnode; /**< Last node for which we separated. */
    104 SCIP_Bool scanand; /**< Whether to scan AND constraints when constructing a hypergraph. */
    105 SCIP_Bool scanproduct; /**< Whether to scan product expressions when constructing a hypergraph. */
    106 SCIP_HYPERGRAPH* hypergraph; /**< The hypergraph. */
    107 int nsepacuts; /**< Total number of generated cuts. */
    108
    109 SCIP_Real timehypercreation; /**< Total time spent on constructing hypergraphs. */
    110 SCIP_Real timehyperoverlaps; /**< Total time spent on computing hypergraphs' overlaps. */
    111 SCIP_Real timepreparation; /**< Time spent on joint preparation for all separation algorithms. */
    112 int nsepastandard; /**< Total number of generated standard relaxation inequalities. */
    113 SCIP_Real timesepaoneflower; /**< Total time spent on separation problem for 1-flower inequalities. */
    114 int nsepaoneflower; /**< Total number of generated 1-flower inequalities. */
    115 SCIP_Real timesepatwoflower; /**< Total time spent on separation problem for 1-flower inequalities. */
    116 int nsepatwoflower; /**< Total number of generated 2-flower inequalities. */
    117
    118 int minnoverlaps; /**< Minimum number of overlaps needed to actually try separation. */
    119 int maxstandard; /**< Maximum number of standard relaxation inequalities per round. */
    120 int maxoneflower; /**< Maximum number of 1-flower inequalities per round. */
    121 int maxtwoflower; /**< Maximum number of 2-flower inequalities per round. */
    122 SCIP_Bool delaystandard; /**< Whether to only generate standard inequalities if also flower. */
    123 int maxuselessoneflower;/**< Number of useless separation rounds after which we stop separating. */
    124 int maxuselesstwoflower;/**< Number of useless separation rounds after which we stop separating. */
    125 int nuselessoneflower; /**< Number of recent useless separation rounds for 1-flowers. */
    126 int nuselesstwoflower; /**< Number of recent useless separation rounds for 2-flowers. */
    127};
    128
    129/*
    130 * Local methods
    131 */
    132
    133/** @brief constructs the hypergraph from transformed problem */
    134static
    136 SCIP* scip, /**< SCIP data structure. */
    137 SCIP_SEPADATA* sepadata /**< Sepadata. */
    138 )
    139{
    140 SCIP_CLOCK* clock;
    141 int nvars;
    142 SCIP_HASHMAP* varsnodes = NULL;
    143 SCIP_HYPERGRAPH_VERTEX* vertices = NULL;
    144 int nvertices;
    145 int memvertices = 32;
    146 SCIP_CONSHDLR* conshdlr;
    147
    148 assert(scip);
    149 assert(sepadata);
    150 assert(sepadata->hypergraph == NULL);
    151
    152 SCIPdebugMsg(scip, "scanning constraints to construct hypergraph.\n");
    153
    154 SCIP_CALL( SCIPcreateClock(scip, &clock) );
    155 SCIP_CALL( SCIPstartClock(scip, clock) );
    156
    157 nvars = SCIPgetNVars(scip);
    158 if( nvars == 0 )
    159 ++nvars;
    160 SCIP_CALL( SCIPhypergraphCreate(&sepadata->hypergraph, SCIPblkmem(scip), nvars, nvars, nvars, 4,
    162 SCIP_HYPERGRAPH* hypergraph = sepadata->hypergraph;
    163
    164 /* Create map from variables to nodes and vertex array. */
    166 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &vertices, memvertices) );
    167
    168 if( sepadata->scanand )
    169 {
    170 /* Scan AND constraints. */
    171 conshdlr = SCIPfindConshdlr(scip, "and");
    172 if( conshdlr != NULL )
    173 {
    174 SCIP_CONS** conss;
    175 int nconss;
    176
    177 conss = SCIPconshdlrGetConss(conshdlr);
    178 nconss = SCIPconshdlrGetNConss(conshdlr);
    179 SCIPdebugMsg(scip, " processing %d AND constraints.\n", nconss);
    180 for( int i = 0; i < nconss; ++i )
    181 {
    182 SCIP_CONS* cons;
    183 SCIP_VAR** vars;
    185 SCIP_HYPERGRAPH_EDGEDATA* edgedata = NULL;
    186
    187 /* Get number of variables. */
    188 cons = conss[i];
    189 nvertices = SCIPgetNVarsAnd(scip, cons);
    190 if( nvertices > memvertices )
    191 {
    192 int newcapacity;
    193
    194 newcapacity = SCIPcalcMemGrowSize(scip, nvertices);
    195 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &vertices, memvertices, newcapacity) );
    196 memvertices = newcapacity;
    197 }
    198
    199 vars = SCIPgetVarsAnd(scip, cons);
    200 for( int j = 0; j < nvertices; ++j )
    201 {
    202 SCIP_HYPERGRAPH_VERTEX v = SCIPhashmapGetImageInt(varsnodes, vars[j]);
    203 if( v == INT_MAX )
    204 {
    205 SCIP_HYPERGRAPH_VERTEXDATA* vertexdata = NULL;
    206 SCIP_CALL( SCIPhypergraphAddVertex(sepadata->hypergraph, &v, &vertexdata) );
    207 vertexdata->var = vars[j];
    208 SCIP_CALL( SCIPhashmapInsertInt(varsnodes, vars[j], v) );
    209 }
    210 vertices[j] = v;
    211 }
    212 SCIP_CALL( SCIPhypergraphAddEdge(sepadata->hypergraph, nvertices, vertices, &edge, &edgedata) );
    213 edgedata->var = SCIPgetResultantAnd(scip, cons);
    214 edgedata->coefficient = 1.0;
    215 }
    216 }
    217 }
    218
    219 if( sepadata->scanproduct )
    220 {
    221 /* Scan nonlinear constraints for product expressions. */
    222 conshdlr = SCIPfindConshdlr(scip, "nonlinear");
    223 if( conshdlr != NULL )
    224 {
    225 int nconss;
    226 SCIP_CONS** conss;
    227 SCIP_EXPRITER* it = NULL;
    228
    229 nconss = SCIPconshdlrGetNConss(conshdlr);
    230 conss = SCIPconshdlrGetConss(conshdlr);
    231 assert( conss != NULL || (nconss == 0) );
    232 SCIPdebugMsg(scip, " processing %d nonlinear constraints.\n", nconss);
    233
    234 /* Prepare iteration such that we visit every expression only once. */
    238
    239 for( int c = 0; c < nconss; ++c )
    240 {
    241 SCIP_EXPR* expr;
    242
    243 /* Iterate through all expressions of the nonlinear constraint that we haven't seen so far. */
    244 expr = SCIPgetExprNonlinear(conss[c]);
    245 for( expr = SCIPexpriterRestartDFS(it, expr); !SCIPexpriterIsEnd(it); expr = SCIPexpriterGetNext(it) ) /*lint !e441 *//*lint !e440 */
    246 {
    247 if( SCIPisExprProduct(scip, expr) )
    248 {
    249 SCIP_VAR* exprvar;
    250 SCIP_EXPR** children;
    251 int j;
    252
    253 exprvar = SCIPgetExprAuxVarNonlinear(expr);
    254 if( exprvar == NULL )
    255 continue;
    256
    257 children = SCIPexprGetChildren(expr);
    258 nvertices = SCIPexprGetNChildren(expr);
    259
    260 if( nvertices > memvertices )
    261 {
    262 int newcapacity;
    263
    264 newcapacity = SCIPcalcMemGrowSize(scip, nvertices);
    265 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &vertices, memvertices, newcapacity) );
    266 memvertices = newcapacity;
    267 }
    268
    269 for( j = 0; j < nvertices; ++j )
    270 {
    271 SCIP_VAR* auxvar;
    273
    274 auxvar = SCIPgetExprAuxVarNonlinear(children[j]);
    275 if( auxvar == NULL || SCIPisLT(scip, SCIPvarGetLbGlobal(auxvar), 0.0) )
    276 break;
    277 v = SCIPhashmapGetImageInt(varsnodes, auxvar);
    278 if( v == INT_MAX )
    279 {
    280 SCIP_HYPERGRAPH_VERTEXDATA* vertexdata = NULL;
    281 SCIP_CALL( SCIPhypergraphAddVertex(sepadata->hypergraph, &v, &vertexdata) );
    282 vertexdata->var = auxvar;
    283 SCIP_CALL( SCIPhashmapInsertInt(varsnodes, auxvar, v) );
    284 }
    285 vertices[j] = v;
    286 }
    287 if( j == nvertices )
    288 {
    289 /* If the lower bound is nonnegative, then we can consider its relaxed domain [0, ub]. */
    290 SCIP_HYPERGRAPH_EDGEDATA* edgedata = NULL;
    292 SCIP_CALL( SCIPhypergraphAddEdge(sepadata->hypergraph, nvertices, vertices, &edge, &edgedata) );
    293 edgedata->var = exprvar;
    294 edgedata->coefficient = SCIPgetCoefExprProduct(expr);
    295 }
    296 }
    297 }
    298 }
    299
    300 SCIPfreeExpriter(&it);
    301 }
    302 }
    303
    304 SCIPfreeBlockMemoryArray(scip, &vertices, memvertices);
    305 SCIPhashmapFree(&varsnodes);
    306
    307 /* Compute each node's incident edges. */
    309
    310 assert( SCIPhypergraphIsValid(hypergraph, stdout) );
    311
    312 SCIP_Real time = SCIPgetClockTime(scip, clock);
    313 sepadata->timehypercreation += time;
    314
    315 /* Find all pair-wise intersections of edges (of size at least 2). */
    317
    318 sepadata->timehyperoverlaps += SCIPgetClockTime(scip, clock) - time;
    319 SCIP_CALL( SCIPfreeClock(scip, &clock) );
    320
    321 assert( SCIPhypergraphIsValid(hypergraph, stdout) );
    322
    323 SCIPdebugMsg(scip, "the hypergraph has %d proper overlaps.\n", SCIPhypergraphGetNOverlaps(hypergraph));
    324
    326
    327#ifdef PRINT_HYPERGRAPH_AND_EXIT
    328 SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "The hypergraph has %d vertices, %d edges and %d overlaps and was "
    329 "computed in %f+%f=%f seconds.\n", SCIPhypergraphGetNVertices(hypergraph), SCIPhypergraphGetNEdges(hypergraph),
    330 SCIPhypergraphGetNOverlaps(hypergraph), sepadata->timehypercreation, sepadata->timehyperoverlaps,
    331 sepadata->timehypercreation + sepadata->timehyperoverlaps);
    332 return SCIP_ERROR;
    333#else
    334 return SCIP_OKAY;
    335#endif /* PRINT_HYPERGRAPH_AND_EXIT */
    336}
    337
    338/* @brief prepare the separation for all cutting plane types by storing relevant data with the hypergraph */
    339static
    341 SCIP* scip, /**< SCIP data structure. */
    342 SCIP_SEPA* sepa, /**< Separator. */
    343 SCIP_SOL* sol /**< Solution to be separated. */
    344 )
    345{
    346 SCIP_SEPADATA* sepadata;
    347 int nedges;
    348 int noverlaps;
    349 SCIP_Real feastol;
    350 SCIP_CLOCK* clock = NULL;
    351
    352 assert(scip);
    353 assert(sepa);
    354
    355 feastol = SCIPfeastol(scip);
    356 sepadata = SCIPsepaGetData(sepa);
    357 assert(sepadata);
    358 if( sepadata->hypergraph == NULL)
    359 return SCIP_OKAY;
    360
    361 SCIP_CALL( SCIPcreateClock(scip, &clock) );
    362 SCIP_CALL( SCIPstartClock(scip, clock) );
    363
    364 SCIPdebugMsg(scip, "separating a solution of value %g...\n", sol == NULL ? SCIPgetLPObjval(scip) : SCIPsolGetOrigObj(sol));
    365
    366 /* We extract the solution values for the hypergraph's vertices. */
    367 for( SCIP_HYPERGRAPH_VERTEX vertex = 0; vertex < SCIPhypergraphGetNVertices(sepadata->hypergraph); ++vertex )
    368 {
    369 SCIP_HYPERGRAPH_VERTEXDATA* vertexdata;
    370 SCIP_Real value;
    371 SCIP_Real ub;
    372
    373 vertexdata = SCIPhypergraphVertexData(sepadata->hypergraph, vertex);
    374 assert( SCIPisGE(scip, SCIPvarGetLbLocal(vertexdata->var), 0.0) );
    375 value = SCIPgetSolVal(scip, sol, vertexdata->var);
    376 ub = SCIPvarGetUbLocal(vertexdata->var);
    377
    378 /* Compute the scaling factor for scaling the domain [lb,ub] to [0,1]. */
    379 vertexdata->coefscale = 1.0 / MAX(ub, feastol);
    380 vertexdata->solval = value * vertexdata->coefscale;
    381 }
    382
    383 /* We extract the solution values for the hypergraph's edges. */
    384 nedges = SCIPhypergraphGetNEdges(sepadata->hypergraph);
    385 for( SCIP_HYPERGRAPH_EDGE edge = 0; edge < nedges; ++edge )
    386 {
    387 SCIP_HYPERGRAPH_EDGEDATA* edgedata;
    388 SCIP_Real ubprod = 1.0;
    389 int size;
    390 SCIP_HYPERGRAPH_VERTEX* vertices;
    391
    392 edgedata = SCIPhypergraphEdgeData(sepadata->hypergraph, edge);
    393 size = SCIPhypergraphEdgeSize(sepadata->hypergraph, edge);
    394 vertices = SCIPhypergraphEdgeVertices(sepadata->hypergraph, edge);
    395 for( int i = 0; i < size; ++i )
    396 ubprod /= SCIPhypergraphVertexData(sepadata->hypergraph, vertices[i])->coefscale;
    397 SCIP_Real value = SCIPgetSolVal(scip, sol, edgedata->var);
    398
    399 /* Compute the scaling factor for scaling the domain [0, product of ubs * edge-coefficient ] to [0,1]. */
    400 edgedata->coefscale = 1.0 / (edgedata->coefficient * ubprod);
    401 edgedata->coefscale = MIN(edgedata->coefscale, 1.0 / feastol );
    402 edgedata->solval = value * edgedata->coefscale;
    403 edgedata->slackval = edgedata->solval - 1.0;
    404 for( int i = 0; i < size; ++i )
    405 edgedata->slackval += 1.0 - SCIPhypergraphVertexData(sepadata->hypergraph, vertices[i])->solval;
    406 }
    407
    408 /* Initialize overlap's sumnodecomplements to \sum_{v in o} (1-z_v).
    409 * Together with minedgecomplement, which is the minimum value of 1-z_e over all incident edges e,
    410 * the difference sumnodecomplements - minedgecomplement represents the violation increase if the sum of (1-z_v)
    411 * is replaced by (1-z_e) in k-flower inequalities.
    412 */
    413 noverlaps = SCIPhypergraphGetNOverlaps(sepadata->hypergraph);
    414 for( SCIP_HYPERGRAPH_OVERLAP overlap = 0; overlap < noverlaps; ++overlap )
    415 {
    416 SCIP_HYPERGRAPH_OVERLAPDATA* overlapdata;
    417 int nvertices;
    418 SCIP_HYPERGRAPH_VERTEX* vertices;
    419
    420 overlapdata = SCIPhypergraphOverlapData(sepadata->hypergraph, overlap);
    421 overlapdata->minedgecomplement = 2.0;
    422 overlapdata->sumnodecomplements = 0.0;
    423 nvertices = SCIPhypergraphOverlapSize(sepadata->hypergraph, overlap);
    424 vertices = SCIPhypergraphOverlapVertices(sepadata->hypergraph, overlap);
    425 for( int i = 0; i < nvertices; ++i )
    426 {
    427 SCIP_HYPERGRAPH_VERTEXDATA* vertexdata;
    428
    429 vertexdata = SCIPhypergraphVertexData(sepadata->hypergraph, vertices[i]);
    430 overlapdata->sumnodecomplements += 1.0 - vertexdata->solval;
    431 }
    432 }
    433
    434 /* Iterate over all edge-overlap incidences to compute each overlap's maximum-value edge.
    435 * Note that the initial value of minedgecomplement is guaranteed to be larger than 1 - z_e for any incident edge e,
    436 * so it will be updated in the loop below. */
    437 for( SCIP_HYPERGRAPH_EDGE edge = 0; edge < SCIPhypergraphGetNEdges(sepadata->hypergraph); ++edge )
    438 {
    439 SCIP_HYPERGRAPH_EDGEDATA* edgedata;
    440 int beyond;
    441
    442 edgedata = SCIPhypergraphEdgeData(sepadata->hypergraph, edge);
    443 beyond = SCIPhypergraphEdgesOverlapsBeyond(sepadata->hypergraph, edge);
    444 for( int i = SCIPhypergraphEdgesOverlapsFirst(sepadata->hypergraph, edge); i < beyond; ++i )
    445 {
    447 SCIP_HYPERGRAPH_OVERLAPDATA* overlapdata;
    448 SCIP_Real edgecomplement;
    449
    450 overlap = SCIPhypergraphEdgesOverlapsGetAtIndex(sepadata->hypergraph, i);
    451 overlapdata = SCIPhypergraphOverlapData(sepadata->hypergraph, overlap);
    452 edgecomplement = 1.0 - edgedata->solval;
    453 if( edgecomplement < overlapdata->minedgecomplement )
    454 {
    455 overlapdata->minedgecomplement = edgecomplement;
    456 overlapdata->minedge = edge;
    457 }
    458 }
    459 }
    460
    461 sepadata->timepreparation += SCIPgetClockTime(scip, clock);
    462 SCIP_CALL( SCIPfreeClock(scip, &clock) );
    463
    464 return SCIP_OKAY;
    465}
    466
    467/**
    468 * @brief add a generated cut row to the cut pool (for the root node) or as a row (otherwise)
    469 */
    470static
    472 SCIP* scip, /**< SCIP datastructure. */
    473 SCIP_SOL* sol, /**< Solution. */
    474 SCIP_ROW* row, /**< Cutting plane. */
    475 int* pnumseparated, /**< Pointer to store number of separated cuts. */
    476 SCIP_RESULT* presult, /**< Pointer to store result. */
    477 SCIP_Bool* padded /**< Pointer for storing whether it was added. */
    478 )
    479{
    480 assert(scip);
    481 assert(row);
    482 assert(pnumseparated);
    483 assert(presult);
    484
    485 if( SCIPisCutEfficacious(scip, sol, row) )
    486 {
    487 if( SCIPgetDepth(scip) == 0 )
    488 {
    490 }
    491 else
    492 {
    493 SCIP_Bool infeasible;
    494 SCIP_CALL( SCIPaddRow(scip, row, FALSE, &infeasible) );
    495 if( infeasible )
    496 *presult = SCIP_CUTOFF;
    497 }
    498 if( *presult != SCIP_CUTOFF )
    499 *presult = SCIP_SEPARATED;
    500 (*pnumseparated)++;
    501 if( padded )
    502 *padded = TRUE;
    503 }
    504 else if( padded )
    505 *padded = FALSE;
    506
    507 return SCIP_OKAY;
    508}
    509
    510/**
    511 * @brief separate missing inequalities from the standard relaxation
    512 */
    513static
    515 SCIP* scip, /**< SCIP datastructure. */
    516 SCIP_SEPA* sepa, /**< Separator. */
    517 SCIP_SOL* sol, /**< Solution to be separated. */
    518 int maxnsepa, /**< Maximum number of separated inequalities. */
    519 SCIP_RESULT* presult /**< Pointer to store result. */
    520 )
    521{
    522 SCIP_SEPADATA* sepadata;
    523 SCIP_CLOCK* clock = NULL;
    524 int nseparated = 0;
    525
    526 assert(scip);
    527 assert(sepa);
    528 assert(presult);
    529
    530 sepadata = SCIPsepaGetData(sepa);
    531 assert(sepadata);
    532
    533 if( sepadata->hypergraph == NULL)
    534 return SCIP_OKAY;
    535
    536#ifdef SCIP_DEBUG
    537 SCIPdebugMessage(" ...standard relaxation inequalities: ");
    538 fflush(stdout);
    539#endif
    540
    541 SCIP_CALL( SCIPcreateClock(scip, &clock) );
    542 SCIP_CALL( SCIPstartClock(scip, clock) );
    543
    544 for( SCIP_HYPERGRAPH_EDGE edge = 0; edge < SCIPhypergraphGetNEdges(sepadata->hypergraph) && *presult != SCIP_CUTOFF
    545 && nseparated < maxnsepa; ++edge )
    546 {
    547 SCIP_HYPERGRAPH_EDGEDATA* edgedata;
    548 SCIP_HYPERGRAPH_VERTEX* vertices;
    549 int size;
    550
    551 edgedata = SCIPhypergraphEdgeData(sepadata->hypergraph, edge);
    552 vertices = SCIPhypergraphEdgeVertices(sepadata->hypergraph, edge);
    553 size = SCIPhypergraphEdgeSize(sepadata->hypergraph, edge);
    554 for( int i = 0; i < size && *presult != SCIP_CUTOFF && nseparated < maxnsepa; ++i )
    555 {
    556 SCIP_HYPERGRAPH_VERTEXDATA* vertexdata;
    557
    558 vertexdata = SCIPhypergraphVertexData(sepadata->hypergraph, vertices[i]);
    559 if( SCIPisEfficacious(scip, edgedata->solval - vertexdata->solval) )
    560 {
    561 SCIP_VAR* vars[2];
    562 SCIP_Real coefs[2];
    563 char name[SCIP_MAXSTRLEN];
    564 SCIP_ROW* row = NULL;
    565
    566 /* 0 <= z_v - z_e */
    567
    568 vars[0] = vertexdata->var;
    569 vars[1] = edgedata->var;
    570 coefs[0] = 1.0 * vertexdata->coefscale;
    571 coefs[1] = -1.0 * edgedata->coefscale;
    572 SCIPsnprintf(name, SCIP_MAXSTRLEN, "flower_%05d_standard", ++sepadata->nsepacuts); /*lint !e534 */
    574 FALSE, TRUE) );
    575 SCIP_CALL( SCIPaddVarsToRow( scip, row, 2, vars, coefs) );
    576
    577 SCIP_CALL( addCut(scip, sol, row, &nseparated, presult, NULL) );
    578 SCIP_CALL( SCIPreleaseRow(scip, &row) );
    579 }
    580 }
    581 }
    582
    583 sepadata->nsepastandard += nseparated;
    584
    585#ifdef SCIP_DEBUG
    586 printf("found %d in %.3fs.\n", nseparated, SCIPgetClockTime(scip, clock));
    587 fflush(stdout);
    588#endif
    589
    590 SCIP_CALL( SCIPfreeClock(scip, &clock) );
    591
    592 return SCIP_OKAY;
    593}
    594
    595#ifdef USE_OLD_ONEFLOWER_SEPARATION
    596
    597/* Separate 1-flower inequalities. */
    598static
    599SCIP_RETCODE separateOneFlowerOld(
    600 SCIP* scip, /**< SCIP data structure. */
    601 SCIP_SEPA* sepa, /**< Separator. */
    602 SCIP_SOL* sol, /**< Solution to be separated. */
    603 int maxnsepa, /**< Maximum number of separated inequalities. */
    604 SCIP_RESULT* presult /**< Pointer to store result. */
    605 )
    606{
    607 SCIP_SEPADATA* sepadata;
    608 SCIP_HYPERGRAPH* hypergraph;
    609 SCIP_CLOCK* clock = NULL;
    610 int nseparated = 0;
    612
    613 assert(scip);
    614 assert(sepa);
    615 assert(presult);
    616
    617 sepadata = SCIPsepaGetData(sepa);
    618 assert(sepadata);
    619
    620 hypergraph = sepadata->hypergraph;
    621 if( hypergraph == NULL )
    622 return SCIP_OKAY;
    623
    624#ifdef SCIP_DEBUG
    625 SCIPdebugMessage(" ...flower inequalities with 1 neighbor: ");
    626 fflush(stdout);
    627#endif
    628
    629 SCIP_CALL( SCIPcreateClock(scip, &clock) );
    630 SCIP_CALL( SCIPstartClock(scip, clock) );
    631
    632 SCIP_CALL( SCIPhypergraphIterInit(hypergraph, &iter) );
    633 for( SCIP_HYPERGRAPH_EDGE base = 0; base < SCIPhypergraphGetNEdges(hypergraph) && *presult != SCIP_CUTOFF
    634 && nseparated < maxnsepa; ++base )
    635 {
    636 SCIP_HYPERGRAPH_EDGEDATA* basedata;
    637 SCIP_HYPERGRAPH_VERTEX* basevertices;
    638 int nbasevertices;
    639 int nbaseseparated = 0; /* Number of cuts separated for this base edge. */
    640
    641 basedata = SCIPhypergraphEdgeData(hypergraph, base);
    642
    643 /* If the slack value is at least 1 then the inequality can never be violated. */
    644 if( SCIPisFeasGE(scip, basedata->slackval, 1.0) )
    645 continue;
    646
    647 basevertices = SCIPhypergraphEdgeVertices(hypergraph, base);
    648 nbasevertices = SCIPhypergraphEdgeSize(hypergraph, base);
    649 for( SCIPhypergraphIterStart(hypergraph, &iter, base, 2, TRUE, FALSE);
    650 SCIPhypergraphIterValid(&iter); SCIPhypergraphIterNext(hypergraph, &iter) )
    651 {
    652 SCIP_HYPERGRAPH_EDGEDATA* adjacentdata;
    653 SCIP_Real gain;
    654
    655 /* The standard inequality has slack stdslack: x_e - 1 + \sum_{v \in e} (1-x_v).
    656 * The 1-flower with base e and neighbor f has slack: x_e - 1 + \sum_{v \in e \setminus f} (1-x_v) + 1-x_f.
    657 * The gain (difference standard - 1-flower) is thus: \sum_{v \in e \cap f} (1-x_v) - 1 + x_f
    658 * If gain > stdslack then the 1-flower inequality has negative slack.
    659 */
    660
    661 adjacentdata = SCIPhypergraphEdgeData(hypergraph, iter.adjacent);
    662 gain = adjacentdata->solval - 1.0;
    663 for( int i = 0; i < iter.ncommonvertices; ++i )
    664 {
    665 gain += 1.0 - SCIPhypergraphVertexData(hypergraph, iter.commonvertices[i])->solval;
    666 }
    667
    668 if( SCIPisEfficacious(scip, gain - basedata->slackval) )
    669 {
    670 SCIP_ROW* row = NULL;
    671 char name[SCIP_MAXSTRLEN];
    672
    673 SCIPsnprintf(name, SCIP_MAXSTRLEN, "flower_%05d_1flower", ++sepadata->nsepacuts);
    674 SCIP_CALL( SCIPcreateRowSepa(scip, &row, sepa, name, 0, NULL, NULL, iter.ncommonvertices - nbasevertices,
    677 SCIP_CALL( SCIPaddVarToRow(scip, row, basedata->var, 1.0 * basedata->coefscale ) );
    678 SCIP_CALL( SCIPaddVarToRow(scip, row, adjacentdata->var, -1.0 * adjacentdata->coefscale) );
    679 for( int i = 0; i < nbasevertices; ++i )
    680 {
    681 SCIP_HYPERGRAPH_VERTEXDATA* vertexdata;
    682
    683 vertexdata = SCIPhypergraphVertexData(hypergraph, basevertices[i]);
    684 SCIP_CALL( SCIPaddVarToRow(scip, row, vertexdata->var , -1.0 * vertexdata->coefscale) );
    685 }
    686 for( int i = 0; i < iter.ncommonvertices; ++i )
    687 {
    688 SCIP_HYPERGRAPH_VERTEXDATA* vertexdata;
    689
    690 vertexdata = SCIPhypergraphVertexData(hypergraph, iter.commonvertices[i]);
    691 SCIP_CALL( SCIPaddVarToRow(scip, row, vertexdata->var , +1.0 * vertexdata->coefscale ) );
    692 }
    694 SCIP_CALL( addCut(scip, sol, row, &nseparated, presult, NULL) );
    695 SCIP_CALL( SCIPreleaseRow(scip, &row) );
    696
    697 if( nbaseseparated > MAXNSEPA_ONEFLOWER_PER_BASE )
    698 break;
    699 }
    700 }
    701 }
    702
    703 SCIPhypergraphIterClear(hypergraph, &iter);
    704 sepadata->nsepaoneflower += nseparated;
    705
    706#ifdef SCIP_DEBUG
    707 printf("found %d in %.3fs.\n", nseparated, SCIPgetClockTime(scip, clock));
    708 fflush(stdout);
    709#endif
    710
    711 sepadata->timesepaoneflower += SCIPgetClockTime(scip, clock);
    712 SCIP_CALL( SCIPfreeClock(scip, &clock) );
    713
    714 return SCIP_OKAY;
    715}
    716
    717#else /* !USE_OLD_ONEFLOWER_SEPARATION */
    718
    719/* Separate 1-flower inequalities. */
    720static
    722 SCIP* scip, /**< SCIP data structure. */
    723 SCIP_SEPA* sepa, /**< Separator. */
    724 SCIP_SOL* sol, /**< Solution to be separated. */
    725 int maxnsepa, /**< Maximum number of separated inequalities. */
    726 SCIP_RESULT* presult /**< Pointer to store result. */
    727 )
    728{
    729 SCIP_SEPADATA* sepadata;
    730 SCIP_HYPERGRAPH* hypergraph;
    731 SCIP_CLOCK* clock = NULL;
    732 int nseparated = 0;
    733
    734 assert(scip);
    735 assert(sepa);
    736 assert(presult);
    737
    738 sepadata = SCIPsepaGetData(sepa);
    739 assert(sepadata);
    740
    741 hypergraph = sepadata->hypergraph;
    742 if( hypergraph == NULL)
    743 return SCIP_OKAY;
    744
    745#ifdef SCIP_DEBUG
    746 SCIPdebugMessage(" ...flower inequalities with 1 neighbor: ");
    747 fflush(stdout);
    748#endif
    749
    750 SCIP_CALL( SCIPcreateClock(scip, &clock) );
    751 SCIP_CALL( SCIPstartClock(scip, clock) );
    752
    753 for( SCIP_HYPERGRAPH_EDGE base = 0; (base < SCIPhypergraphGetNEdges(hypergraph)) && (nseparated < maxnsepa); ++base )
    754 {
    755 SCIP_HYPERGRAPH_EDGEDATA* basedata;
    756 int i;
    757 int beyond;
    758 SCIP_Real bestgain = -1.0;
    759 SCIP_HYPERGRAPH_OVERLAP bestoverlap = -1;
    760
    761 basedata = SCIPhypergraphEdgeData(hypergraph, base);
    762 i = SCIPhypergraphEdgesOverlapsFirst(hypergraph, base);
    763 beyond = SCIPhypergraphEdgesOverlapsBeyond(hypergraph, base);
    764
    765 /*
    766 * We need to test if z_base + (1-z_overlap) + sum_{v in base \ overlap} (1-z_v) < 1.
    767 * This is done by minimizing the change (1-z_overlap) - sum_{v in overlap) (1-z)
    768 * w.r.t. the standard inequality over all overlaps that are incident to base.
    769 */
    770
    771 for( ; i < beyond; ++i )
    772 {
    774 SCIP_HYPERGRAPH_OVERLAPDATA* overlapdata;
    775 SCIP_Real gain;
    776
    777 overlap = SCIPhypergraphEdgesOverlapsGetAtIndex(hypergraph, i);
    778 overlapdata = SCIPhypergraphOverlapData(hypergraph, overlap);
    779 gain = overlapdata->sumnodecomplements - overlapdata->minedgecomplement;
    780 if( gain > bestgain )
    781 {
    782 bestgain = gain;
    783 bestoverlap = overlap;
    784 }
    785 }
    786
    787 if( bestgain > 0 && SCIPisEfficacious(scip, bestgain - basedata->slackval) )
    788 {
    789 SCIP_ROW* row = NULL;
    790 char name[SCIP_MAXSTRLEN];
    791 SCIP_HYPERGRAPH_VERTEX* basevertices;
    792 int nbasevertices;
    793 SCIP_HYPERGRAPH_VERTEX* overlapvertices;
    794 int noverlapvertices;
    795 SCIP_HYPERGRAPH_EDGE adjacent;
    796 SCIP_HYPERGRAPH_EDGEDATA* adjacentdata;
    797
    798 basevertices = SCIPhypergraphEdgeVertices(hypergraph, base);
    799 nbasevertices = SCIPhypergraphEdgeSize(hypergraph, base);
    800 overlapvertices = SCIPhypergraphOverlapVertices(hypergraph, bestoverlap);
    801 noverlapvertices = SCIPhypergraphOverlapSize(hypergraph, bestoverlap);
    802 adjacent = SCIPhypergraphOverlapData(hypergraph, bestoverlap)->minedge;
    803 adjacentdata = SCIPhypergraphEdgeData(hypergraph, adjacent);
    804 SCIPsnprintf(name, SCIP_MAXSTRLEN, "flower_%05d_1flower", ++sepadata->nsepacuts); /*lint !e534*/
    805 SCIP_CALL( SCIPcreateRowSepa(scip, &row, sepa, name, 0, NULL, NULL, 1.0 * (noverlapvertices - nbasevertices),
    808 SCIP_CALL( SCIPaddVarToRow(scip, row, basedata->var, 1.0 * basedata->coefscale ) );
    809 SCIP_CALL( SCIPaddVarToRow(scip, row, adjacentdata->var, -1.0 * adjacentdata->coefscale) );
    810 for( i = 0; i < nbasevertices; ++i )
    811 {
    812 SCIP_HYPERGRAPH_VERTEXDATA* vertexdata;
    813
    814 vertexdata = SCIPhypergraphVertexData(hypergraph, basevertices[i]);
    815 SCIP_CALL( SCIPaddVarToRow(scip, row, vertexdata->var , -1.0 * vertexdata->coefscale) );
    816 }
    817 for( i = 0; i < noverlapvertices; ++i )
    818 {
    819 SCIP_HYPERGRAPH_VERTEXDATA* vertexdata;
    820
    821 vertexdata = SCIPhypergraphVertexData(hypergraph, overlapvertices[i]);
    822 SCIP_CALL( SCIPaddVarToRow(scip, row, vertexdata->var , +1.0 * vertexdata->coefscale ) );
    823 }
    825
    826 SCIP_CALL( addCut(scip, sol, row, &nseparated, presult, NULL) );
    827 SCIP_CALL( SCIPreleaseRow(scip, &row) );
    828 }
    829 }
    830
    831 sepadata->nsepaoneflower += nseparated;
    832
    833#ifdef SCIP_DEBUG
    834 printf("found %d in %.3fs.\n", nseparated, SCIPgetClockTime(scip, clock));
    835 fflush(stdout);
    836#endif
    837
    838 sepadata->timesepaoneflower += SCIPgetClockTime(scip, clock);
    839 SCIP_CALL( SCIPfreeClock(scip, &clock) );
    840
    841 return SCIP_OKAY;
    842}
    843
    844#endif /* USE_OLD_ONEFLOWER_SEPARATION */
    845
    846
    847#ifdef USE_OLD_TWOFLOWER_SEPARATION
    848
    849/* Separate 2-flower inequalities. */
    850static
    851SCIP_RETCODE separateTwoFlowerOld(
    852 SCIP* scip, /**< SCIP data structure. */
    853 SCIP_SEPA* sepa, /**< Separator. */
    854 SCIP_SOL* sol, /**< Solution to be separated. */
    855 int maxnsepa, /**< Maximum number of separated inequalities. */
    856 SCIP_RESULT* presult /**< Pointer to store result. */
    857 )
    858{
    859 SCIP_SEPADATA* sepadata;
    860 SCIP_HYPERGRAPH* hypergraph;
    861 SCIP_CLOCK* clock = NULL;
    862 int nedges;
    863 int nseparated = 0;
    864 int* markedvertices = NULL;
    867
    868 assert(scip);
    869 assert(sepa);
    870 assert(presult);
    871
    872 sepadata = SCIPsepaGetData(sepa);
    873 assert(sepadata);
    874
    875 hypergraph = sepadata->hypergraph;
    876 if( hypergraph == NULL)
    877 return SCIP_OKAY;
    878
    879#ifdef SCIP_DEBUG
    880 SCIPdebugMessage(" ...flower inequalities with 2 neighbors: ");
    881 fflush(stdout);
    882#endif
    883
    884 SCIP_CALL( SCIPcreateClock(scip, &clock) );
    885 SCIP_CALL( SCIPstartClock(scip, clock) );
    886
    887 nedges = SCIPhypergraphGetNEdges(hypergraph);
    888 SCIP_CALL( SCIPallocCleanBufferArray(scip, &markedvertices, SCIPhypergraphGetNVertices(hypergraph)) );
    889 SCIP_CALL( SCIPhypergraphIterInit(hypergraph, &iter1) );
    890 SCIP_CALL( SCIPhypergraphIterInit(hypergraph, &iter2) );
    891 for( SCIP_HYPERGRAPH_EDGE base = 0; (base < nedges) && (*presult != SCIP_CUTOFF) && (nseparated < maxnsepa); ++base )
    892 {
    893 SCIP_HYPERGRAPH_EDGEDATA* basedata;
    894 SCIP_HYPERGRAPH_VERTEX* basevertices;
    895 int nbasevertices;
    896 int nbaseseparated = 0;
    897
    898 basedata = SCIPhypergraphEdgeData(hypergraph, base);
    899
    900 /* If the slack value is at least 1 then the inequality can never be violated. */
    901 if( SCIPisFeasGE(scip, basedata->slackval, 1.0) )
    902 continue;
    903
    904 basevertices = SCIPhypergraphEdgeVertices(hypergraph, base);
    905 nbasevertices = SCIPhypergraphEdgeSize(hypergraph, base);
    906 for( SCIPhypergraphIterStart(hypergraph, &iter1, base, 2, FALSE, FALSE); SCIPhypergraphIterValid(&iter1);
    907 SCIPhypergraphIterNext(hypergraph, &iter1) )
    908 {
    909 SCIP_HYPERGRAPH_EDGEDATA* adjacent1data;
    910 SCIP_Real gain1;
    911
    912 adjacent1data = SCIPhypergraphEdgeData(hypergraph, iter1.adjacent);
    913 gain1 = adjacent1data->solval - 1.0;
    914 for( int i = 0; i < iter1.ncommonvertices; ++i )
    915 {
    917
    918 v = iter1.commonvertices[i];
    919 gain1 += 1.0 - SCIPhypergraphVertexData(hypergraph, v)->solval;
    920 markedvertices[v] = 1;
    921 }
    922
    923 for( SCIPhypergraphIterStart(hypergraph, &iter2, base, 2, FALSE, FALSE); SCIPhypergraphIterValid(&iter2);
    924 SCIPhypergraphIterNext(hypergraph, &iter2) )
    925 {
    926 SCIP_Bool disjoint;
    927 SCIP_HYPERGRAPH_EDGEDATA* adjacent2data;
    928 SCIP_Real gain2;
    929
    930 /* Ordering of neighbor edges. */
    931 if( iter2.adjacent <= iter1.adjacent )
    932 continue;
    933
    934 disjoint = TRUE;
    935 for( int i = 0; i < iter2.ncommonvertices; ++i)
    936 {
    937 if( markedvertices[iter2.commonvertices[i]] )
    938 {
    939 disjoint = FALSE;
    940 break;
    941 }
    942 }
    943 if( !disjoint )
    944 continue;
    945
    946 /* The standard inequality has slack: x_e - 1 + \sum_{v \in e} (1-x_v).
    947 * The 2-flower with base e and neighbors f,g has slack:
    948 * x_e - 1 + \sum_{v \in e \setminus (f \cup g)} (1-x_v) + 1-x_f + 1 - x_g.
    949 * The gain (difference standard - 2-flower) is thus: \sum_{v \in e \cap (f \cup g)} (1-x_v) + x_f + x_g - 2
    950 * If gain > stdslack then the 2-flower inequality has negative slack.
    951 */
    952
    953 adjacent2data = SCIPhypergraphEdgeData(hypergraph, iter2.adjacent);
    954 gain2 = gain1 + adjacent2data->solval - 1.0;
    955 for( int j = 0; j < iter2.ncommonvertices; ++j )
    956 {
    958
    959 w = iter2.commonvertices[j];
    960 gain2 += 1.0 - SCIPhypergraphVertexData(hypergraph, w)->solval;
    961 }
    962
    963 if( SCIPisEfficacious(scip, gain2 - basedata->slackval) )
    964 {
    965 SCIP_ROW* row = NULL;
    966 char name[SCIP_MAXSTRLEN];
    967 SCIP_Bool separated;
    968
    969 SCIPsnprintf(name, SCIP_MAXSTRLEN, "flower_%05d_2flower", ++sepadata->nsepacuts);
    970 SCIP_CALL( SCIPcreateRowSepa(scip, &row, sepa, name, 0, NULL, NULL,
    971 iter1.ncommonvertices + iter2.ncommonvertices - nbasevertices - 1.0, SCIPinfinity(scip),
    972 SCIPgetDepth(scip) > 0, FALSE, TRUE) );
    974 SCIP_CALL( SCIPaddVarToRow(scip, row, basedata->var, 1.0 * basedata->coefscale) );
    975 SCIP_CALL( SCIPaddVarToRow(scip, row, adjacent1data->var, -1.0 * adjacent1data->coefscale) );
    976 SCIP_CALL( SCIPaddVarToRow(scip, row, adjacent2data->var, -1.0 * adjacent2data->coefscale) );
    977 for( int i = 0; i < nbasevertices; ++i )
    978 {
    979 SCIP_HYPERGRAPH_VERTEXDATA* vertexdata;
    980
    981 vertexdata = SCIPhypergraphVertexData(hypergraph, basevertices[i]);
    982 SCIP_CALL( SCIPaddVarToRow(scip, row, vertexdata->var, -1.0 * vertexdata->coefscale) );
    983 }
    984 for( int i = 0; i < iter1.ncommonvertices; ++i )
    985 {
    986 SCIP_HYPERGRAPH_VERTEXDATA* vertexdata;
    987
    988 vertexdata = SCIPhypergraphVertexData(hypergraph, iter1.commonvertices[i]);
    989 SCIP_CALL( SCIPaddVarToRow(scip, row, vertexdata->var, +1.0 * vertexdata->coefscale) );
    990 }
    991 for( int j = 0; j < iter2.ncommonvertices; ++j )
    992 {
    993 SCIP_HYPERGRAPH_VERTEXDATA* vertexdata;
    994
    995 vertexdata = SCIPhypergraphVertexData(hypergraph, iter2.commonvertices[j]);
    996 SCIP_CALL( SCIPaddVarToRow(scip, row, vertexdata->var, +1.0 * vertexdata->coefscale) );
    997 }
    999 SCIP_CALL( addCut(scip, sol, row, &nseparated, presult, &separated) );
    1000 if( separated )
    1001 ++nbaseseparated;
    1002 SCIP_CALL( SCIPreleaseRow(scip, &row) );
    1003 if( nbaseseparated > 2 )
    1004 break;
    1005 }
    1006 }
    1007
    1008 for( int i = 0; i < iter1.ncommonvertices; ++i )
    1009 markedvertices[iter1.commonvertices[i]] = 0;
    1010 }
    1011 }
    1012
    1013 SCIPhypergraphIterClear(hypergraph, &iter2);
    1014 SCIPhypergraphIterClear(hypergraph, &iter1);
    1015 SCIPfreeCleanBuffer(scip, &markedvertices );
    1016 sepadata->nsepatwoflower += nseparated;
    1017
    1018#ifdef SCIP_DEBUG
    1019 printf("found %d in %.3fs.\n", nseparated, SCIPgetClockTime(scip, clock));
    1020 fflush(stdout);
    1021#endif
    1022
    1023 sepadata->timesepatwoflower += SCIPgetClockTime(scip, clock);
    1024 SCIP_CALL( SCIPfreeClock(scip, &clock) );
    1025
    1026 return SCIP_OKAY;
    1027}
    1028
    1029#else /* !USE_OLD_TWOFLOWER_SEPARATION */
    1030
    1031/* Separate 2-flower inequalities. */
    1032static
    1034 SCIP* scip, /**< SCIP datastructure. */
    1035 SCIP_SEPA* sepa, /**< Separator. */
    1036 SCIP_SOL* sol, /**< Solution to be separated. */
    1037 int maxnsepa, /**< Maximum number of separated inequalities. */
    1038 SCIP_RESULT* presult /**< Pointer to store result. */
    1039 )
    1040{
    1041 SCIP_SEPADATA* sepadata;
    1042 SCIP_HYPERGRAPH* hypergraph;
    1043 SCIP_CLOCK* clock = NULL;
    1045 int nseparated = 0;
    1046
    1047 assert(scip);
    1048 assert(sepa);
    1049 assert(presult);
    1050
    1051 sepadata = SCIPsepaGetData(sepa);
    1052 assert(sepadata);
    1053
    1054 hypergraph = sepadata->hypergraph;
    1055 if( hypergraph == NULL)
    1056 return SCIP_OKAY;
    1057
    1058#ifdef SCIP_DEBUG
    1059 SCIPdebugMessage(" ...flower inequalities with 2 neighbors: ");
    1060 fflush(stdout);
    1061#endif
    1062
    1063 SCIP_CALL( SCIPcreateClock(scip, &clock) );
    1064 SCIP_CALL( SCIPstartClock(scip, clock) );
    1065
    1066 for( base = 0; (base < SCIPhypergraphGetNEdges(hypergraph)) && (nseparated < maxnsepa); ++base )
    1067 {
    1068 SCIP_HYPERGRAPH_EDGEDATA* basedata;
    1069 int basesize;
    1070 int first;
    1071 int beyond;
    1072 int i1;
    1073 int i2;
    1074 SCIP_HYPERGRAPH_OVERLAP bestoverlap1 = -1;
    1075 SCIP_HYPERGRAPH_OVERLAP bestoverlap2 = -1;
    1076 SCIP_Real bestgain = -1.0;
    1077
    1078 basedata = SCIPhypergraphEdgeData(hypergraph, base);
    1079 basesize = SCIPhypergraphEdgeSize(hypergraph, base);
    1080 first = SCIPhypergraphEdgesOverlapsFirst(hypergraph, base);
    1081 beyond = SCIPhypergraphEdgesOverlapsBeyond(hypergraph, base);
    1082
    1083 /*
    1084 * We need to test if
    1085 * z_base + (1-z_overlap1) + (1-z_overlap2) + sum_{v in base \ (overlap1 \cup overlap2)} (1-z_v) < 1.
    1086 * This is done by minimizing the change (1-z_overlap1) - sum_{v in overlap1) (1-z) and
    1087 * of (1-z_overlap2) - sum_{v in overlap2) (1-z), both w.r.t. the standard inequality over all overlaps that are
    1088 * incident to base. However, this only correctly reflects the changes violation if the two overlaps are disjoint.
    1089 */
    1090
    1091 for( i1 = first; i1 < beyond; ++i1 )
    1092 {
    1093 SCIP_HYPERGRAPH_OVERLAP overlap1;
    1094 SCIP_HYPERGRAPH_OVERLAPDATA* overlap1data;
    1095 SCIP_Real gain1;
    1096 int overlap1size;
    1097
    1098 overlap1 = SCIPhypergraphEdgesOverlapsGetAtIndex(hypergraph, i1);
    1099 overlap1size = SCIPhypergraphOverlapSize(hypergraph, overlap1);
    1100
    1101 /* If |o1| > |e|/2 then for sure |o2| > holds for sure, so we can stop. */
    1102 if( overlap1size > basesize / 2)
    1103 break;
    1104
    1105 overlap1data = SCIPhypergraphOverlapData(hypergraph, overlap1);
    1106 gain1 = overlap1data->sumnodecomplements - overlap1data->minedgecomplement;
    1107
    1108 for( i2 = i1 + 1; i2 < beyond; ++i2 )
    1109 {
    1110 SCIP_HYPERGRAPH_OVERLAP overlap2;
    1111 int overlap2size;
    1112
    1113 overlap2 = SCIPhypergraphEdgesOverlapsGetAtIndex(hypergraph, i2);
    1114 overlap2size = SCIPhypergraphOverlapSize(hypergraph, overlap2);
    1115 if( (overlap1size + overlap2size > basesize)
    1116 || ((overlap1size == overlap2size) && (overlap1 >= overlap2))
    1117 || !SCIPhypergraphOverlapsDisjoint(hypergraph, overlap1, overlap2) )
    1118 {
    1119 continue;
    1120 }
    1121
    1122 SCIP_HYPERGRAPH_OVERLAPDATA* overlap2data;
    1123 SCIP_Real gain2;
    1124 SCIP_Real totalgain;
    1125
    1126 overlap2data = SCIPhypergraphOverlapData(hypergraph, overlap2);
    1127 gain2 = overlap2data->sumnodecomplements - overlap2data->minedgecomplement;
    1128 totalgain = gain1 + gain2;
    1129
    1130 if( totalgain > bestgain )
    1131 {
    1132 bestgain = totalgain;
    1133 bestoverlap1 = overlap1;
    1134 bestoverlap2 = overlap2;
    1135 }
    1136 }
    1137 }
    1138
    1139 if( bestgain > 0 && SCIPisEfficacious(scip, bestgain - basedata->slackval) )
    1140 {
    1141 SCIP_HYPERGRAPH_VERTEX* basevertices;
    1142 int nbasevertices;
    1143 SCIP_HYPERGRAPH_VERTEX* overlap1vertices;
    1144 int noverlap1vertices;
    1145 SCIP_HYPERGRAPH_EDGE adjacent1;
    1146 SCIP_HYPERGRAPH_EDGEDATA* adjacent1data;
    1147 SCIP_HYPERGRAPH_VERTEX* overlap2vertices;
    1148 int noverlap2vertices;
    1149 SCIP_HYPERGRAPH_EDGE adjacent2;
    1150 SCIP_HYPERGRAPH_EDGEDATA* adjacent2data;
    1151 char name[SCIP_MAXSTRLEN];
    1152 SCIP_ROW* row = NULL;
    1153
    1154 basevertices = SCIPhypergraphEdgeVertices(sepadata->hypergraph, base);
    1155 nbasevertices = SCIPhypergraphEdgeSize(sepadata->hypergraph, base);
    1156 overlap1vertices = SCIPhypergraphOverlapVertices(sepadata->hypergraph, bestoverlap1);
    1157 noverlap1vertices = SCIPhypergraphOverlapSize(sepadata->hypergraph, bestoverlap1);
    1158 adjacent1 = SCIPhypergraphOverlapData(sepadata->hypergraph, bestoverlap1)->minedge;
    1159 adjacent1data = SCIPhypergraphEdgeData(sepadata->hypergraph, adjacent1);
    1160 overlap2vertices = SCIPhypergraphOverlapVertices(sepadata->hypergraph, bestoverlap2);
    1161 noverlap2vertices = SCIPhypergraphOverlapSize(sepadata->hypergraph, bestoverlap2);
    1162 adjacent2 = SCIPhypergraphOverlapData(sepadata->hypergraph, bestoverlap2)->minedge;
    1163 adjacent2data = SCIPhypergraphEdgeData(sepadata->hypergraph, adjacent2);
    1164
    1165 SCIPsnprintf(name, SCIP_MAXSTRLEN, "flower_%05d_2flower", ++sepadata->nsepacuts); /*lint !e534*/
    1166 SCIP_CALL( SCIPcreateRowSepa(scip, &row, sepa, name, 0, NULL, NULL,
    1167 noverlap1vertices + noverlap2vertices - nbasevertices - 1.0, SCIPinfinity(scip), SCIPgetDepth(scip) > 0,
    1168 FALSE, TRUE) );
    1170 SCIP_CALL( SCIPaddVarToRow(scip, row, basedata->var, 1.0 * basedata->coefscale ) );
    1171 SCIP_CALL( SCIPaddVarToRow(scip, row, adjacent1data->var, -1.0 * adjacent1data->coefscale) );
    1172 SCIP_CALL( SCIPaddVarToRow(scip, row, adjacent2data->var, -1.0 * adjacent2data->coefscale) );
    1173 for( int i = 0; i < nbasevertices; ++i )
    1174 {
    1176
    1177 data = SCIPhypergraphVertexData(sepadata->hypergraph, basevertices[i]);
    1178 SCIP_CALL( SCIPaddVarToRow(scip, row, data->var , -1.0 * data->coefscale) );
    1179 }
    1180 for( int i = 0; i < noverlap1vertices; ++i )
    1181 {
    1183
    1184 data = SCIPhypergraphVertexData(sepadata->hypergraph, overlap1vertices[i]);
    1185 SCIP_CALL( SCIPaddVarToRow(scip, row, data->var , +1.0 * data->coefscale ) );
    1186 }
    1187 for( int i = 0; i < noverlap2vertices; ++i )
    1188 {
    1190
    1191 data = SCIPhypergraphVertexData(sepadata->hypergraph, overlap2vertices[i]);
    1192 SCIP_CALL( SCIPaddVarToRow(scip, row, data->var , +1.0 * data->coefscale ) );
    1193 }
    1195 SCIP_CALL( addCut(scip, sol, row, &nseparated, presult, NULL) );
    1196 SCIP_CALL( SCIPreleaseRow(scip, &row) );
    1197 }
    1198 }
    1199
    1200 sepadata->nsepatwoflower += nseparated;
    1201
    1202#ifdef SCIP_DEBUG
    1203 printf("found %d in %.3fs.\n", nseparated, SCIPgetClockTime(scip, clock));
    1204 fflush(stdout);
    1205#endif
    1206
    1207 sepadata->timesepatwoflower += SCIPgetClockTime(scip, clock);
    1208 SCIP_CALL( SCIPfreeClock(scip, &clock) );
    1209
    1210 return SCIP_OKAY;
    1211}
    1212
    1213#endif /* USE_OLD_TWOFLOWER_SEPARATION */
    1214
    1215/**
    1216 * @brief Main separation function.
    1217 */
    1218static
    1220 SCIP* scip, /**< SCIP data structure. */
    1221 SCIP_SEPA* sepa, /**< Separator. */
    1222 SCIP_SOL* sol, /**< Solution to be separated (or \c NULL for the LP solution). */
    1223 SCIP_RESULT* result /**< Pointer for storing the result. */
    1224 )
    1225{
    1226 SCIP_SEPADATA* sepadata;
    1227
    1228 assert(scip);
    1229
    1230 *result = SCIP_DIDNOTFIND;
    1231
    1232 /* We do not apply the cuts for subscips. */
    1233 if( SCIPgetSubscipDepth(scip) > 0 )
    1234 return SCIP_OKAY;
    1235
    1236 sepadata = SCIPsepaGetData(sepa);
    1237 assert(sepadata);
    1238
    1239 if( sepadata->lastrun != SCIPgetNRuns(scip) )
    1240 {
    1241 /* If we still have a hypergraph, we delete it. */
    1242 if( sepadata->hypergraph )
    1243 {
    1244 SCIPdebugMsg(scip, "recreating hypergraph.\n");
    1245 SCIP_CALL( SCIPhypergraphFree(&sepadata->hypergraph) );
    1246 }
    1247 else
    1248 SCIPdebugMsg(scip, "creating hypergraph.\n");
    1249
    1250 SCIP_CALL( constructHypergraph(scip, sepadata) );
    1251 assert(sepadata->hypergraph != NULL);
    1252
    1253 /* If the hypergraph is not interesting then we just delete it again. */
    1254 if( SCIPhypergraphGetNOverlaps(sepadata->hypergraph) < sepadata->minnoverlaps )
    1255 {
    1256 SCIPdebugMsg(scip, "deleting hypergraph due to only %d overlaps.\n",
    1257 SCIPhypergraphGetNOverlaps(sepadata->hypergraph));
    1258 SCIP_CALL( SCIPhypergraphFree(&sepadata->hypergraph) );
    1259 assert(sepadata->hypergraph == NULL);
    1260 }
    1261
    1262 sepadata->lastrun = SCIPgetNRuns(scip);
    1263 sepadata->nuselessoneflower = 0;
    1264 sepadata->nuselesstwoflower = 0;
    1265 }
    1266
    1267 if( SCIPgetCurrentNode(scip) != sepadata->lastnode )
    1268 {
    1269 sepadata->lastnode = SCIPgetCurrentNode(scip);
    1270 sepadata->nuselessoneflower = 0;
    1271 sepadata->nuselesstwoflower = 0;
    1272 }
    1273
    1274 if( sepadata->hypergraph
    1275 && ((sepadata->nuselessoneflower <= sepadata->maxuselessoneflower)
    1276 || (sepadata->nuselesstwoflower <= sepadata->maxuselesstwoflower)) )
    1277 {
    1278 *result = SCIP_DIDNOTFIND;
    1279
    1280 SCIP_CALL( prepareSeparation(scip, sepa, sol) );
    1281
    1282 if( sepadata->maxstandard && !sepadata->delaystandard )
    1283 {
    1284 SCIP_CALL( separateStandard(scip, sepa, sol, sepadata->maxstandard, result) );
    1285 if( *result == SCIP_CUTOFF )
    1286 return SCIP_OKAY;
    1287 }
    1288
    1289 if( sepadata->maxoneflower && (sepadata->nuselessoneflower <= sepadata->maxuselessoneflower) )
    1290 {
    1291 int oldnsepaoneflower = sepadata->nsepaoneflower;
    1292#ifdef USE_OLD_ONEFLOWER_SEPARATION
    1293 SCIP_CALL( separateOneFlowerOld(scip, sepa, sol, sepadata->maxoneflower, result) );
    1294#else /* !USE_OLD_ONEFLOWER_SEPARATION */
    1295 SCIP_CALL( separateOneFlower(scip, sepa, sol, sepadata->maxoneflower, result) );
    1296#endif /* USE_OLD_ONEFLOWER_SEPARATION */
    1297 if( sepadata->nsepaoneflower > oldnsepaoneflower ) /* cppcheck-suppress knownConditionTrueFalse */
    1298 sepadata->nuselessoneflower = 0;
    1299 else
    1300 sepadata->nuselessoneflower++;
    1301 if( *result == SCIP_CUTOFF )
    1302 return SCIP_OKAY;
    1303 }
    1304
    1305 if( sepadata->maxtwoflower && (sepadata->nuselesstwoflower <= sepadata->maxuselesstwoflower) )
    1306 {
    1307 int oldnsepatwoflower = sepadata->nsepatwoflower;
    1308#ifdef USE_OLD_TWOFLOWER_SEPARATION
    1309 SCIP_CALL( separateTwoFlowerOld(scip, sepa, sol, sepadata->maxtwoflower, result) );
    1310#else /* !USE_OLD_ONEFLOWER_SEPARATION */
    1311 SCIP_CALL( separateTwoFlower(scip, sepa, sol, sepadata->maxtwoflower, result) );
    1312#endif /* USE_OLD_ONEFLOWER_SEPARATION */
    1313 if( sepadata->nsepatwoflower > oldnsepatwoflower ) /* cppcheck-suppress knownConditionTrueFalse */
    1314 sepadata->nuselesstwoflower = 0;
    1315 else
    1316 sepadata->nuselesstwoflower++;
    1317 if( *result == SCIP_CUTOFF )
    1318 return SCIP_OKAY;
    1319 }
    1320
    1321 if( *result == SCIP_SEPARATED && sepadata->maxstandard && sepadata->delaystandard )
    1322 {
    1323 SCIP_CALL( separateStandard(scip, sepa, sol, sepadata->maxstandard, result) );
    1324 }
    1325 }
    1326
    1327 return SCIP_OKAY;
    1328}
    1329
    1330/*
    1331 * Callback methods of separator.
    1332 */
    1333
    1334/** copy method for separator plugins (called when SCIP copies plugins) */
    1335static
    1336SCIP_DECL_SEPACOPY(sepaCopyFlower)
    1337{ /*lint --e{715}*/
    1338 assert(scip != NULL);
    1339 assert(sepa != NULL);
    1340
    1342
    1343 /* call inclusion method of separator */
    1345
    1346 return SCIP_OKAY;
    1347}
    1348
    1349/** Destructor of separator to free user data (called when SCIP is exiting). */
    1350static
    1351SCIP_DECL_SEPAFREE(sepaFreeFlower)
    1352{ /*lint --e{715}*/
    1353 SCIP_SEPADATA* sepadata;
    1354
    1355 /* Free the separator data. */
    1356 sepadata = SCIPsepaGetData(sepa);
    1357 assert(sepadata);
    1358 assert(sepadata->hypergraph == NULL);
    1359
    1360 SCIPfreeBlockMemory(scip, &sepadata);
    1361 SCIPsepaSetData(sepa, NULL);
    1362
    1363 return SCIP_OKAY;
    1364}
    1365
    1366/** Initialization method of separator (called after problem was transformed). */
    1367static
    1368SCIP_DECL_SEPAINIT(sepaInitFlower)
    1369{ /*lint --e{715}*/
    1370 SCIP_SEPADATA* sepadata;
    1371
    1372 sepadata = SCIPsepaGetData(sepa);
    1373 assert(sepadata);
    1374
    1375 sepadata->timehypercreation = 0.0;
    1376 sepadata->timehyperoverlaps = 0.0;
    1377
    1378 return SCIP_OKAY;
    1379}
    1380
    1381/** solving process deinitialization method of separator (called before branch and bound process data is freed) */
    1382static
    1383SCIP_DECL_SEPAEXITSOL(sepaExitsolFlower)
    1384{
    1385 SCIP_SEPADATA* sepadata;
    1386
    1387 sepadata = SCIPsepaGetData(sepa);
    1388 assert(sepadata);
    1389
    1390 if( SCIPgetSubscipDepth(scip) > 0 )
    1391 return SCIP_OKAY;
    1392
    1393 if( sepadata->hypergraph != NULL )
    1394 {
    1395 SCIP_CALL( SCIPhypergraphFree(&sepadata->hypergraph) );
    1396 }
    1397
    1398 return SCIP_OKAY;
    1399}
    1400
    1401/** LP solution separation method of separator. */
    1402static
    1403SCIP_DECL_SEPAEXECLP(sepaExeclpFlower)
    1404{ /*lint --e{715}*/
    1405
    1406 SCIP_CALL( separate(scip, sepa, NULL, result) );
    1407
    1408 return SCIP_OKAY;
    1409}
    1410
    1411/** arbitrary primal solution separation method of separator */
    1412static
    1413SCIP_DECL_SEPAEXECSOL(sepaExecsolFlower)
    1414{ /*lint --e{715}*/
    1415
    1416 SCIP_CALL( separate(scip, sepa, sol, result) );
    1417
    1418 return SCIP_OKAY;
    1419}
    1420
    1421
    1422/*
    1423 * separator specific interface methods
    1424 */
    1425
    1426/** creates the flower separator and includes it in SCIP */
    1428 SCIP* scip /**< SCIP data structure */
    1429 )
    1430{
    1431 SCIP_SEPADATA* sepadata = NULL;
    1432 SCIP_SEPA* sepa = NULL;
    1433
    1434 /* create flower separator data */
    1435 SCIP_CALL( SCIPallocBlockMemory(scip, &sepadata) );
    1436 sepadata->lastrun = -1;
    1437 sepadata->lastnode = NULL;
    1438 sepadata->hypergraph = NULL;
    1439 sepadata->nsepacuts = 0;
    1440 sepadata->timesepaoneflower = 0.0;
    1441 sepadata->timesepatwoflower = 0.0;
    1442 sepadata->timepreparation = 0.0;
    1443 sepadata->nsepastandard = 0;
    1444 sepadata->nsepaoneflower = 0;
    1445 sepadata->nsepatwoflower = 0;
    1446 sepadata->nuselessoneflower = 0;
    1447 sepadata->nuselesstwoflower = 0;
    1448
    1449 /* include separator */
    1451 SEPA_USESSUBSCIP, SEPA_DELAY, sepaExeclpFlower, sepaExecsolFlower, sepadata) );
    1452
    1453 assert(sepa != NULL);
    1454
    1455 /* set non fundamental callbacks via setter functions */
    1456 SCIP_CALL( SCIPsetSepaCopy(scip, sepa, sepaCopyFlower) );
    1457 SCIP_CALL( SCIPsetSepaFree(scip, sepa, sepaFreeFlower) );
    1458 SCIP_CALL( SCIPsetSepaInit(scip, sepa, sepaInitFlower) );
    1459 SCIP_CALL( SCIPsetSepaExitsol(scip, sepa, sepaExitsolFlower) );
    1460
    1461 /* add flower separator parameters */
    1462 SCIP_CALL( SCIPaddBoolParam(scip, "separating/flower/scanand",
    1463 "Whether to scan AND constraints when constructing hypergraph", &sepadata->scanand, FALSE, DEFAULT_SCAN_AND, 0,
    1464 0) );
    1465 SCIP_CALL( SCIPaddBoolParam(scip, "separating/flower/scanproduct",
    1466 "Whether to scan product expressions when constructing hypergraph", &sepadata->scanproduct, FALSE,
    1467 DEFAULT_SCAN_PRODUCT, 0, 0) );
    1468 SCIP_CALL( SCIPaddIntParam(scip, "separating/flower/maxstandard",
    1469 "Maximum number of standard relaxation inequalities per cut round", &sepadata->maxstandard, FALSE,
    1470 DEFAULT_MAX_STANDARD, 0, INT_MAX, 0, 0) );
    1471 SCIP_CALL( SCIPaddIntParam(scip, "separating/flower/maxoneflower",
    1472 "Maximum number of 1-flower inequalities per cut round", &sepadata->maxoneflower, FALSE, DEFAULT_MAX_ONEFLOWER,
    1473 0, INT_MAX, 0, 0) );
    1474 SCIP_CALL( SCIPaddIntParam(scip, "separating/flower/maxtwoflower",
    1475 "Maximum number of 2-flower inequalities per cut round", &sepadata->maxtwoflower, FALSE, DEFAULT_MAX_TWOFLOWER,
    1476 0, INT_MAX, 0, 0) );
    1477 SCIP_CALL( SCIPaddIntParam(scip, "separating/flower/minnoverlaps",
    1478 "Minimum number of overlaps necessary to try separation", &sepadata->minnoverlaps, FALSE, DEFAULT_MIN_OVERLAPS,
    1479 0, INT_MAX, 0, 0) );
    1480 SCIP_CALL( SCIPaddBoolParam(scip, "separating/flower/delaystandard",
    1481 "Whether to only generate standard inequalities if also flowers were generated", &sepadata->delaystandard,
    1482 FALSE, DEFAULT_DELAY_STANDARD, 0, 0) );
    1483 SCIP_CALL( SCIPaddIntParam(scip, "separating/flower/maxuselessoneflower",
    1484 "Number of useless separation rounds after which we stop separating 1-flowers", &sepadata->maxuselessoneflower,
    1485 FALSE, DEFAULT_MAX_USELESS_ONEFLOWER, 0, INT_MAX, 0, 0) );
    1486 SCIP_CALL( SCIPaddIntParam(scip, "separating/flower/maxuselesstwoflower",
    1487 "Number of useless separation rounds after which we stop separating 2-flowers", &sepadata->maxuselesstwoflower,
    1488 FALSE, DEFAULT_MAX_USELESS_TWOFLOWER, 0, INT_MAX, 0, 0) );
    1489
    1490 return SCIP_OKAY;
    1491}
    SCIP_VAR * w
    Definition: circlepacking.c:67
    Constraint handler for AND constraints, .
    constraint handler for nonlinear constraints specified by algebraic expressions
    #define NULL
    Definition: def.h:257
    #define SCIP_MAXSTRLEN
    Definition: def.h:278
    #define SCIP_Bool
    Definition: def.h:100
    #define MIN(x, y)
    Definition: def.h:233
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define MAX(x, y)
    Definition: def.h:229
    #define SCIP_CALL(x)
    Definition: def.h:364
    SCIP_VAR * SCIPgetResultantAnd(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_and.c:5238
    int SCIPgetNVarsAnd(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_and.c:5199
    SCIP_VAR * SCIPgetExprAuxVarNonlinear(SCIP_EXPR *expr)
    SCIP_EXPR * SCIPgetExprNonlinear(SCIP_CONS *cons)
    SCIP_VAR ** SCIPgetVarsAnd(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_and.c:5218
    int SCIPgetSubscipDepth(SCIP *scip)
    Definition: scip_copy.c:2589
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
    Definition: misc.c:3095
    int SCIPhashmapGetImageInt(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3304
    SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
    Definition: misc.c:3061
    SCIP_RETCODE SCIPhashmapInsertInt(SCIP_HASHMAP *hashmap, void *origin, int image)
    Definition: misc.c:3179
    SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
    Definition: scip_message.c:88
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    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 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
    int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4782
    SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
    Definition: scip_cons.c:940
    SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4739
    SCIP_RETCODE SCIPaddPoolCut(SCIP *scip, SCIP_ROW *row)
    Definition: scip_cut.c:336
    SCIP_Bool SCIPisCutEfficacious(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
    Definition: scip_cut.c:117
    SCIP_Bool SCIPisEfficacious(SCIP *scip, SCIP_Real efficacy)
    Definition: scip_cut.c:135
    SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
    Definition: scip_cut.c:225
    int SCIPexprGetNChildren(SCIP_EXPR *expr)
    Definition: expr.c:3872
    SCIP_Bool SCIPisExprProduct(SCIP *scip, SCIP_EXPR *expr)
    Definition: scip_expr.c:1490
    SCIP_Bool SCIPexpriterIsEnd(SCIP_EXPRITER *iterator)
    Definition: expriter.c:969
    SCIP_Real SCIPgetCoefExprProduct(SCIP_EXPR *expr)
    void SCIPexpriterSetStagesDFS(SCIP_EXPRITER *iterator, SCIP_EXPRITER_STAGE stopstages)
    Definition: expriter.c:664
    SCIP_EXPR * SCIPexpriterRestartDFS(SCIP_EXPRITER *iterator, SCIP_EXPR *expr)
    Definition: expriter.c:630
    SCIP_RETCODE SCIPcreateExpriter(SCIP *scip, SCIP_EXPRITER **iterator)
    Definition: scip_expr.c:2362
    SCIP_EXPR * SCIPexpriterGetNext(SCIP_EXPRITER *iterator)
    Definition: expriter.c:858
    SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
    Definition: expr.c:3882
    void SCIPfreeExpriter(SCIP_EXPRITER **iterator)
    Definition: scip_expr.c:2376
    SCIP_RETCODE SCIPexpriterInit(SCIP_EXPRITER *iterator, SCIP_EXPR *expr, SCIP_EXPRITER_TYPE type, SCIP_Bool allowrevisit)
    Definition: expriter.c:501
    SCIP_Real SCIPgetLPObjval(SCIP *scip)
    Definition: scip_lp.c:253
    #define SCIPallocCleanBufferArray(scip, ptr, num)
    Definition: scip_mem.h:142
    #define SCIPfreeBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:110
    BMS_BLKMEM * SCIPblkmem(SCIP *scip)
    Definition: scip_mem.c:57
    int SCIPcalcMemGrowSize(SCIP *scip, int num)
    Definition: scip_mem.c:139
    #define SCIPfreeCleanBuffer(scip, ptr)
    Definition: scip_mem.h:144
    #define SCIPallocBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:93
    #define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
    Definition: scip_mem.h:99
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    SCIP_RETCODE SCIPcacheRowExtensions(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:1581
    SCIP_RETCODE SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:1604
    SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_lp.c:1646
    SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
    Definition: scip_lp.c:1508
    SCIP_RETCODE SCIPcreateEmptyRowSepa(SCIP *scip, SCIP_ROW **row, SCIP_SEPA *sepa, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
    Definition: scip_lp.c:1429
    SCIP_RETCODE SCIPaddVarsToRow(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
    Definition: scip_lp.c:1672
    SCIP_RETCODE SCIPcreateRowSepa(SCIP *scip, SCIP_ROW **row, SCIP_SEPA *sepa, const char *name, int len, SCIP_COL **cols, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
    Definition: scip_lp.c:1301
    SCIP_RETCODE SCIPincludeSepaBasic(SCIP *scip, SCIP_SEPA **sepa, const char *name, const char *desc, int priority, int freq, SCIP_Real maxbounddist, SCIP_Bool usessubscip, SCIP_Bool delay, SCIP_DECL_SEPAEXECLP((*sepaexeclp)), SCIP_DECL_SEPAEXECSOL((*sepaexecsol)), SCIP_SEPADATA *sepadata)
    Definition: scip_sepa.c:115
    const char * SCIPsepaGetName(SCIP_SEPA *sepa)
    Definition: sepa.c:746
    SCIP_RETCODE SCIPsetSepaFree(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAFREE((*sepafree)))
    Definition: scip_sepa.c:173
    SCIP_RETCODE SCIPsetSepaExitsol(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAEXITSOL((*sepaexitsol)))
    Definition: scip_sepa.c:237
    SCIP_SEPADATA * SCIPsepaGetData(SCIP_SEPA *sepa)
    Definition: sepa.c:636
    void SCIPsepaSetData(SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata)
    Definition: sepa.c:646
    SCIP_RETCODE SCIPsetSepaCopy(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPACOPY((*sepacopy)))
    Definition: scip_sepa.c:157
    SCIP_RETCODE SCIPsetSepaInit(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAINIT((*sepainit)))
    Definition: scip_sepa.c:189
    SCIP_Real SCIPsolGetOrigObj(SCIP_SOL *sol)
    Definition: sol.c:4185
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1763
    int SCIPgetNRuns(SCIP *scip)
    SCIP_RETCODE SCIPcreateClock(SCIP *scip, SCIP_CLOCK **clck)
    Definition: scip_timing.c:76
    SCIP_RETCODE SCIPfreeClock(SCIP *scip, SCIP_CLOCK **clck)
    Definition: scip_timing.c:127
    SCIP_Real SCIPgetClockTime(SCIP *scip, SCIP_CLOCK *clck)
    Definition: scip_timing.c:319
    SCIP_RETCODE SCIPstartClock(SCIP *scip, SCIP_CLOCK *clck)
    Definition: scip_timing.c:161
    SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPfeastol(SCIP *scip)
    SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    int SCIPgetDepth(SCIP *scip)
    Definition: scip_tree.c:672
    SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
    Definition: scip_tree.c:91
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24300
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24266
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24152
    SCIP_RETCODE SCIPincludeSepaFlower(SCIP *scip)
    Definition: sepa_flower.c:1427
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    void SCIPhypergraphIterStart(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_ITER *iterator, SCIP_HYPERGRAPH_EDGE base, unsigned int minoverlapsize, SCIP_Bool onlylater, SCIP_Bool findoverlaps)
    initializes the iterator to the first adjacent edge of base
    Definition: hypergraph.c:1506
    int SCIPhypergraphEdgesOverlapsBeyond(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_EDGE edge)
    returns an index beyond the last overlap incident to edge
    Definition: hypergraph.c:1995
    void SCIPhypergraphIterNext(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_ITER *iterator)
    initializes the iterator to the first adjacent edge of base
    Definition: hypergraph.c:1547
    SCIP_RETCODE SCIPhypergraphFree(SCIP_HYPERGRAPH **phypergraph)
    frees a hypergraph
    Definition: hypergraph.c:281
    SCIP_RETCODE SCIPhypergraphAddEdge(SCIP_HYPERGRAPH *hypergraph, int nvertices, SCIP_HYPERGRAPH_VERTEX *vertices, SCIP_HYPERGRAPH_EDGE *pedge, SCIP_HYPERGRAPH_EDGEDATA **pedgedata)
    adds a new edge to the hypergraph
    Definition: hypergraph.c:416
    void SCIPhypergraphIterClear(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_ITER *iterator)
    frees a hypergraph iterator's internal memory
    Definition: hypergraph.c:1494
    SCIP_Bool SCIPhypergraphIterValid(SCIP_HYPERGRAPH_ITER *iterator)
    returns whether the iterator is valid
    Definition: hypergraph.c:1537
    int SCIPhypergraphGetNEdges(SCIP_HYPERGRAPH *hypergraph)
    returns the number of edges
    Definition: hypergraph.c:1774
    SCIP_RETCODE SCIPhypergraphComputeVerticesEdges(SCIP_HYPERGRAPH *hypergraph)
    computes each vertex' list of incident edges
    Definition: hypergraph.c:811
    SCIP_HYPERGRAPH_OVERLAPDATA * SCIPhypergraphOverlapData(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_OVERLAP overlap)
    returns additional data of overlap
    Definition: hypergraph.c:1838
    SCIP_RETCODE SCIPhypergraphAddVertex(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_VERTEX *pvertex, SCIP_HYPERGRAPH_VERTEXDATA **pvertexdata)
    adds a new vertex to the hypergraph
    Definition: hypergraph.c:386
    int SCIPhypergraphEdgeSize(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_EDGE edge)
    returns the number of vertices of edge
    Definition: hypergraph.c:1850
    SCIP_Bool SCIPhypergraphOverlapsDisjoint(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_OVERLAP overlap1, SCIP_HYPERGRAPH_OVERLAP overlap2)
    returns whether overlaps overlap1 and overlap2 are disjoint
    Definition: hypergraph.c:1187
    SCIP_Bool SCIPhypergraphIsValid(SCIP_HYPERGRAPH *hypergraph, FILE *file)
    asserts that the hypergraph data structures are valid
    Definition: hypergraph.c:1221
    SCIP_HYPERGRAPH_VERTEX * SCIPhypergraphEdgeVertices(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_EDGE edge)
    returns the array of vertices of edge
    Definition: hypergraph.c:1867
    int SCIPhypergraphEdgesOverlapsFirst(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_EDGE edge)
    returns an index for the first overlap incident to edge
    Definition: hypergraph.c:1982
    SCIP_HYPERGRAPH_VERTEXDATA * SCIPhypergraphVertexData(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_VERTEX vertex)
    returns additional data of vertex
    Definition: hypergraph.c:1814
    SCIP_RETCODE SCIPhypergraphComputeOverlapsEdges(SCIP_HYPERGRAPH *hypergraph)
    computes all overlaps' lists of incident edges
    Definition: hypergraph.c:990
    SCIP_RETCODE SCIPhypergraphComputeOverlaps(SCIP_HYPERGRAPH *hypergraph, SCIP_DECL_HYPERGRAPH_OVERLAP((*handler)), void *userdata)
    computes all overlaps and stores overlaps' vertices and all edges' overlaps
    Definition: hypergraph.c:587
    int SCIPhypergraphGetNVertices(SCIP_HYPERGRAPH *hypergraph)
    returns the number of vertices
    Definition: hypergraph.c:1764
    SCIP_HYPERGRAPH_OVERLAP SCIPhypergraphEdgesOverlapsGetAtIndex(SCIP_HYPERGRAPH *hypergraph, int idx)
    returns the overlap corresponding to idx that is incident to an edge
    Definition: hypergraph.c:2013
    SCIP_RETCODE SCIPhypergraphIterInit(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_ITER *iterator)
    initializes a hypergraph iterator's internal memory
    Definition: hypergraph.c:1469
    SCIP_HYPERGRAPH_VERTEX * SCIPhypergraphOverlapVertices(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_OVERLAP overlap)
    returns the array of sorted vertices of overlap
    Definition: hypergraph.c:1969
    int SCIPhypergraphOverlapSize(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_OVERLAP overlap)
    returns the number of vertices of overlap
    Definition: hypergraph.c:1951
    int SCIPhypergraphGetNOverlaps(SCIP_HYPERGRAPH *hypergraph)
    returns the number of overlaps
    Definition: hypergraph.c:1794
    SCIP_HYPERGRAPH_EDGEDATA * SCIPhypergraphEdgeData(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_EDGE edge)
    returns additional data of edge
    Definition: hypergraph.c:1826
    SCIP_RETCODE SCIPhypergraphCreate(SCIP_HYPERGRAPH **phypergraph, BMS_BLKMEM *blkmem, int memvertices, int memedges, int memoverlaps, int memedgesvertices, size_t sizevertexdata, size_t sizeedgedata, size_t sizeoverlapdata)
    creates a hypergraph
    Definition: hypergraph.c:210
    Internal methods for dealing with hypergraphs.
    void SCIPmessagePrintInfo(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
    Definition: message.c:594
    #define SCIPdebugMessage
    Definition: pub_message.h:96
    static SCIP_DECL_SEPACOPY(sepaCopyFlower)
    Definition: sepa_flower.c:1336
    #define SEPA_PRIORITY
    Definition: sepa_flower.c:44
    #define SEPA_DELAY
    Definition: sepa_flower.c:48
    #define DEFAULT_MIN_OVERLAPS
    Definition: sepa_flower.c:50
    static SCIP_RETCODE separateStandard(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, int maxnsepa, SCIP_RESULT *presult)
    separate missing inequalities from the standard relaxation
    Definition: sepa_flower.c:514
    static SCIP_RETCODE addCut(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *row, int *pnumseparated, SCIP_RESULT *presult, SCIP_Bool *padded)
    add a generated cut row to the cut pool (for the root node) or as a row (otherwise)
    Definition: sepa_flower.c:471
    static SCIP_RETCODE separateTwoFlower(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, int maxnsepa, SCIP_RESULT *presult)
    Definition: sepa_flower.c:1033
    static SCIP_DECL_SEPAEXITSOL(sepaExitsolFlower)
    Definition: sepa_flower.c:1383
    #define DEFAULT_SCAN_PRODUCT
    Definition: sepa_flower.c:52
    #define DEFAULT_MAX_USELESS_TWOFLOWER
    Definition: sepa_flower.c:58
    #define SEPA_DESC
    Definition: sepa_flower.c:43
    static SCIP_RETCODE separateOneFlower(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, int maxnsepa, SCIP_RESULT *presult)
    Definition: sepa_flower.c:721
    static SCIP_DECL_SEPAFREE(sepaFreeFlower)
    Definition: sepa_flower.c:1351
    #define DEFAULT_MAX_USELESS_ONEFLOWER
    Definition: sepa_flower.c:57
    static SCIP_DECL_SEPAEXECLP(sepaExeclpFlower)
    Definition: sepa_flower.c:1403
    #define DEFAULT_DELAY_STANDARD
    Definition: sepa_flower.c:56
    #define SEPA_USESSUBSCIP
    Definition: sepa_flower.c:47
    static SCIP_DECL_SEPAEXECSOL(sepaExecsolFlower)
    Definition: sepa_flower.c:1413
    #define DEFAULT_MAX_ONEFLOWER
    Definition: sepa_flower.c:54
    static SCIP_DECL_SEPAINIT(sepaInitFlower)
    Definition: sepa_flower.c:1368
    static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
    Main separation function.
    Definition: sepa_flower.c:1219
    #define SEPA_MAXBOUNDDIST
    Definition: sepa_flower.c:46
    static SCIP_RETCODE prepareSeparation(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol)
    Definition: sepa_flower.c:340
    #define SEPA_FREQ
    Definition: sepa_flower.c:45
    #define SEPA_NAME
    Definition: sepa_flower.c:42
    #define DEFAULT_MAX_STANDARD
    Definition: sepa_flower.c:53
    #define DEFAULT_SCAN_AND
    Definition: sepa_flower.c:51
    #define DEFAULT_MAX_TWOFLOWER
    Definition: sepa_flower.c:55
    static SCIP_RETCODE constructHypergraph(SCIP *scip, SCIP_SEPADATA *sepadata)
    constructs the hypergraph from transformed problem
    Definition: sepa_flower.c:135
    flower-inequality separator
    internal methods for global SCIP settings
    SCIP_HYPERGRAPH_EDGE adjacent
    SCIP_HYPERGRAPH_VERTEX * commonvertices
    SCIP main data structure.
    datastructures for global SCIP settings
    @ SCIP_EXPRITER_DFS
    Definition: type_expr.h:718
    #define SCIP_EXPRITER_ENTEREXPR
    Definition: type_expr.h:694
    int SCIP_HYPERGRAPH_EDGE
    int SCIP_HYPERGRAPH_OVERLAP
    struct SCIP_Hypergraph_OverlapData SCIP_HYPERGRAPH_OVERLAPDATA
    struct SCIP_Hypergraph_NodeData SCIP_HYPERGRAPH_VERTEXDATA
    int SCIP_HYPERGRAPH_VERTEX
    struct SCIP_Hypergraph_EdgeData SCIP_HYPERGRAPH_EDGEDATA
    @ SCIP_CUTOFF
    Definition: type_result.h:48
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_SEPARATED
    Definition: type_result.h:49
    enum SCIP_Result SCIP_RESULT
    Definition: type_result.h:61
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    @ SCIP_ERROR
    Definition: type_retcode.h:43
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    struct SCIP_SepaData SCIP_SEPADATA
    Definition: type_sepa.h:52