SCIP Doxygen Documentation
Loading...
Searching...
No Matches
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);
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
158 if( nvars == 0 )
159 ++nvars;
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 {
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{
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);
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{
523 SCIP_CLOCK* clock = NULL;
524 int nseparated = 0;
525
526 assert(scip);
527 assert(sepa);
528 assert(presult);
529
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{
608 SCIP_HYPERGRAPH* hypergraph;
609 SCIP_CLOCK* clock = NULL;
610 int nseparated = 0;
612
613 assert(scip);
614 assert(sepa);
615 assert(presult);
616
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{
730 SCIP_HYPERGRAPH* hypergraph;
731 SCIP_CLOCK* clock = NULL;
732 int nseparated = 0;
733
734 assert(scip);
735 assert(sepa);
736 assert(presult);
737
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{
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
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{
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);
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{
1227
1228 assert(scip);
1229
1231
1232 /* We do not apply the cuts for subscips. */
1233 if( SCIPgetSubscipDepth(scip) > 0 )
1234 return SCIP_OKAY;
1235
1236 sepadata = SCIPsepaGetData(sepa);
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
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",
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 {
1279
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}*/
1354
1355 /* Free the separator data. */
1356 sepadata = SCIPsepaGetData(sepa);
1358 assert(sepadata->hypergraph == NULL);
1359
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}*/
1371
1372 sepadata = SCIPsepaGetData(sepa);
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{
1386
1387 sepadata = SCIPsepaGetData(sepa);
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{
1432 SCIP_SEPA* sepa = NULL;
1433
1434 /* create flower separator data */
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
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)
#define SCIPdebugMsg
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
SCIP_RETCODE SCIPsetSepaFree(SCIP *scip, SCIP_SEPA *sepa,)
Definition scip_sepa.c:173
const char * SCIPsepaGetName(SCIP_SEPA *sepa)
Definition sepa.c:746
SCIP_RETCODE SCIPsetSepaInit(SCIP *scip, SCIP_SEPA *sepa,)
Definition scip_sepa.c:189
SCIP_RETCODE SCIPsetSepaExitsol(SCIP *scip, SCIP_SEPA *sepa,)
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,)
Definition scip_sepa.c:157
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)
SCIP_Real SCIPgetClockTime(SCIP *scip, SCIP_CLOCK *clck)
SCIP_RETCODE SCIPstartClock(SCIP *scip, SCIP_CLOCK *clck)
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)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition misc.c:10827
return SCIP_OKAY
int c
static SCIP_SOL * sol
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
SCIP_VAR * var
static SCIP_VAR ** vars
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
int SCIPhypergraphEdgesOverlapsBeyond(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_EDGE edge)
returns an index beyond the last overlap incident to edge
void SCIPhypergraphIterNext(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_ITER *iterator)
initializes the iterator to the first adjacent edge of base
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
SCIP_Bool SCIPhypergraphIterValid(SCIP_HYPERGRAPH_ITER *iterator)
returns whether the iterator is valid
int SCIPhypergraphGetNEdges(SCIP_HYPERGRAPH *hypergraph)
returns the number of edges
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
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
SCIP_Bool SCIPhypergraphOverlapsDisjoint(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_OVERLAP overlap1, SCIP_HYPERGRAPH_OVERLAP overlap2)
returns whether overlaps overlap1 and overlap2 are disjoint
SCIP_Bool SCIPhypergraphIsValid(SCIP_HYPERGRAPH *hypergraph, FILE *file)
asserts that the hypergraph data structures are valid
SCIP_HYPERGRAPH_VERTEX * SCIPhypergraphEdgeVertices(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_EDGE edge)
returns the array of vertices of edge
int SCIPhypergraphEdgesOverlapsFirst(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_EDGE edge)
returns an index for the first overlap incident to edge
SCIP_HYPERGRAPH_VERTEXDATA * SCIPhypergraphVertexData(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_VERTEX vertex)
returns additional data of vertex
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
SCIP_HYPERGRAPH_OVERLAP SCIPhypergraphEdgesOverlapsGetAtIndex(SCIP_HYPERGRAPH *hypergraph, int idx)
returns the overlap corresponding to idx that is incident to an edge
SCIP_RETCODE SCIPhypergraphIterInit(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_ITER *iterator)
initializes a hypergraph iterator's internal memory
SCIP_HYPERGRAPH_VERTEX * SCIPhypergraphOverlapVertices(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_OVERLAP overlap)
returns the array of sorted vertices of overlap
int SCIPhypergraphOverlapSize(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_OVERLAP overlap)
returns the number of vertices of overlap
int SCIPhypergraphGetNOverlaps(SCIP_HYPERGRAPH *hypergraph)
returns the number of overlaps
SCIP_HYPERGRAPH_EDGEDATA * SCIPhypergraphEdgeData(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_EDGE edge)
returns additional data of edge
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
#define SEPA_PRIORITY
#define SEPA_DELAY
#define SEPA_DESC
#define SEPA_USESSUBSCIP
#define SEPA_MAXBOUNDDIST
#define SEPA_FREQ
#define SEPA_NAME
#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
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)
static SCIP_RETCODE separateTwoFlower(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, int maxnsepa, SCIP_RESULT *presult)
#define DEFAULT_SCAN_PRODUCT
Definition sepa_flower.c:52
#define DEFAULT_MAX_USELESS_TWOFLOWER
Definition sepa_flower.c:58
static SCIP_RETCODE separateOneFlower(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, int maxnsepa, SCIP_RESULT *presult)
#define DEFAULT_MAX_USELESS_ONEFLOWER
Definition sepa_flower.c:57
#define DEFAULT_DELAY_STANDARD
Definition sepa_flower.c:56
#define DEFAULT_MAX_ONEFLOWER
Definition sepa_flower.c:54
static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
Main separation function.
static SCIP_RETCODE prepareSeparation(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol)
#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
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
struct SCIP_Clock SCIP_CLOCK
Definition type_clock.h:49
struct SCIP_Cons SCIP_CONS
Definition type_cons.h:63
struct SCIP_Conshdlr SCIP_CONSHDLR
Definition type_cons.h:62
struct SCIP_Expr SCIP_EXPR
Definition type_expr.h:55
struct SCIP_ExprIter SCIP_EXPRITER
Definition type_expr.h:722
@ 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 SCIP_HYPERGRAPH
struct SCIP_Hypergraph_Iter SCIP_HYPERGRAPH_ITER
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
struct SCIP_Row SCIP_ROW
Definition type_lp.h:105
struct SCIP_HashMap SCIP_HASHMAP
Definition type_misc.h:106
@ 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_INVALIDCALL
@ SCIP_ERROR
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
struct SCIP_SepaData SCIP_SEPADATA
Definition type_sepa.h:52
#define SCIP_DECL_SEPAEXECSOL(x)
Definition type_sepa.h:166
#define SCIP_DECL_SEPAEXECLP(x)
Definition type_sepa.h:136
#define SCIP_DECL_SEPAFREE(x)
Definition type_sepa.h:69
#define SCIP_DECL_SEPAEXITSOL(x)
Definition type_sepa.h:107
struct SCIP_Sepa SCIP_SEPA
Definition type_sepa.h:51
#define SCIP_DECL_SEPACOPY(x)
Definition type_sepa.h:61
#define SCIP_DECL_SEPAINIT(x)
Definition type_sepa.h:77
struct SCIP_Sol SCIP_SOL
Definition type_sol.h:57
struct SCIP_Node SCIP_NODE
Definition type_tree.h:63
struct SCIP_Var SCIP_VAR
Definition type_var.h:166