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