Scippy

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