Scippy

SCIP

Solving Constraint Integer Programs

hypergraph.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 hypergraph.c
26 * @ingroup OTHER_CFILES
27 * @brief internal methods for dealing with hypergraphs
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/hypergraph.h"
36#include "scip/misc.h"
37#include "scip/pub_message.h" /* For SCIPdebugMessage */
38
39#ifndef NDEBUG
41#endif
42
43/** @brief enlarges vertex arrays to have capacity for at least \p required vertices */
44static
46 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
47 int required /**< Required vertex capacity. */
48 )
49{
50 assert(hypergraph);
51 assert(required >= 0);
52
53 if( hypergraph->memvertices < required )
54 {
55 int newcapacity;
56 newcapacity = MAX(256, hypergraph->memvertices);
57 while( newcapacity < required )
58 newcapacity *= 2;
59
60 assert( hypergraph->memvertices >= 0 );
62 hypergraph->memvertices * hypergraph->sizevertexdata / sizeof(*(hypergraph->verticesdata)),
63 newcapacity * hypergraph->sizevertexdata / sizeof(*(hypergraph->verticesdata))) ); /*lint --e{737}*/
64 hypergraph->memvertices = newcapacity;
65 SCIPdebugMessage("ensuring memory for %d vertices.\n", newcapacity);
66 }
67
68 return SCIP_OKAY;
69}
70
71/** @brief enlarges edge arrays to have capacity for at least \p required edges */
72static
74 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
75 int required /**< Required edge capacity. */
76 )
77{
78 assert(hypergraph);
79 assert(required >= 0);
80
81 if( hypergraph->memedges < required )
82 {
83 int newcapacity;
84 newcapacity = MAX(256, hypergraph->memedges);
85 while( newcapacity < required )
86 newcapacity *= 2;
87
88 assert( hypergraph->memedges >= 0 );
89 SCIP_ALLOC( BMSreallocBlockMemoryArray(hypergraph->blkmem, &hypergraph->edgesdata,
90 hypergraph->memedges * hypergraph->sizeedgedata / sizeof(*(hypergraph->edgesdata)),
91 newcapacity * hypergraph->sizeedgedata / sizeof(*(hypergraph->edgesdata))) ); /*lint --e{737}*/
92
93 if( hypergraph->edgesverticesbeg )
94 {
96 hypergraph->memedges + 1, newcapacity + 1) );
97 }
98 else
99 {
100 assert(hypergraph->memedges == 0);
101 SCIP_ALLOC( BMSallocBlockMemoryArray(hypergraph->blkmem, &hypergraph->edgesverticesbeg, newcapacity + 1) );
102 hypergraph->edgesverticesbeg[0] = 0;
103 }
104 hypergraph->memedges = newcapacity;
105 SCIPdebugMessage("ensuring memory for %d edges.\n", newcapacity);
106 }
107
108 return SCIP_OKAY;
109}
110
111/** @brief enlarges arrays for incident vertex/edge pairs to have capacity for at least \p required */
112static
114 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
115 int required /**< Required incident vertex/edge capacity. */
116 )
117{
118 assert(hypergraph);
119 assert(required >= 0);
120
121 if( hypergraph->memedgesvertices < required )
122 {
123 int newcapacity;
124 newcapacity = MAX(256, hypergraph->memedgesvertices);
125 while( newcapacity < required )
126 newcapacity *= 2;
127
129 hypergraph->memedgesvertices, newcapacity) );
130 hypergraph->memedgesvertices = newcapacity;
131 SCIPdebugMessage("ensuring memory for %d vertex/edge pairs.\n", newcapacity);
132 }
133
134 return SCIP_OKAY;
135}
136
137/** @brief enlarges overlap arrays to have capacity for at least \p required overlaps */
138static
140 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
141 int required /**< Required overlap capacity. */
142 )
143{
144 assert(hypergraph);
145 assert(required >= 0);
146
147 if( hypergraph->memoverlaps < required )
148 {
149 int newcapacity;
150 newcapacity = MAX(256, hypergraph->memoverlaps);
151 while( newcapacity < required )
152 newcapacity *= 2;
153
154 if( hypergraph->overlapsverticesbeg )
155 {
157 hypergraph->memoverlaps + 1, newcapacity + 1) );
158 }
159 else
160 {
161 assert(hypergraph->memoverlaps == 0);
162 SCIP_ALLOC( BMSallocBlockMemoryArray(hypergraph->blkmem, &hypergraph->overlapsverticesbeg, newcapacity + 1) );
163 }
164 if( hypergraph->overlapsdata )
165 {
166 assert( hypergraph->memoverlaps >= 0 );
167 SCIP_ALLOC( BMSreallocBlockMemoryArray(hypergraph->blkmem, &hypergraph->overlapsdata,
168 hypergraph->memoverlaps * hypergraph->sizeoverlapdata / sizeof(*(hypergraph->overlapsdata)),
169 newcapacity * hypergraph->sizeoverlapdata / sizeof(*(hypergraph->overlapsdata))) ); /*lint --e{737}*/
170 }
171 else
172 {
173 SCIP_ALLOC( BMSallocBlockMemoryArray(hypergraph->blkmem, &hypergraph->overlapsdata,
174 newcapacity * hypergraph->sizeoverlapdata / sizeof(*(hypergraph->overlapsdata))) ); /*lint --e{737}*/
175 }
176 hypergraph->memoverlaps = newcapacity;
177 SCIPdebugMessage("ensuring memory for %d overlaps.\n", newcapacity);
178 }
179
180 return SCIP_OKAY;
181}
182
183/** @brief enlarges overlapVertices array to have capacity for at least \p required overlaps' vertices */
184static
186 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
187 int required /**< Required overlapVertices capacity. */
188 )
189{
190 assert(hypergraph);
191 assert(required >= 0);
192
193 if( hypergraph->memoverlapsvertices < required )
194 {
195 int newcapacity;
196 newcapacity = MAX(256, hypergraph->memoverlapsvertices);
197 while( newcapacity < required )
198 newcapacity *= 2;
199
201 hypergraph->memoverlapsvertices, newcapacity) );
202 hypergraph->memoverlapsvertices = newcapacity;
203 SCIPdebugMessage("ensuring memory for %d overlaps' vertices.\n", newcapacity);
204 }
205
206 return SCIP_OKAY;
207}
208
209/** @brief creates a hypergraph */
211 SCIP_HYPERGRAPH** phypergraph, /**< Pointer for storing the hypergraph. */
212 BMS_BLKMEM* blkmem, /**< Block memory for storage. */
213 int memvertices, /**< Upper bound on expected number of vertices. */
214 int memedges, /**< Upper bound on expected number of edges. */
215 int memoverlaps, /**< Upper bound on expected number of overlaps. */
216 int memedgesvertices, /**< Upper bound on expected average size of edges. */
217 size_t sizevertexdata, /**< Size (in bytes) of additional vertex data. */
218 size_t sizeedgedata, /**< Size (in bytes) of additional edge data. */
219 size_t sizeoverlapdata /**< Size (in bytes) of additional overlap data. */
220 )
221{
222 SCIP_HYPERGRAPH* hypergraph;
223
224 assert(phypergraph);
225 assert(blkmem);
226
227 assert(memvertices >= 0);
228 assert(memedges >= 0);
229 assert(memoverlaps >= 0);
230 assert(memedgesvertices > 0);
231
232 SCIP_ALLOC( BMSallocBlockMemory(blkmem, phypergraph) );
233 hypergraph = *phypergraph;
234 hypergraph->blkmem = blkmem;
235 hypergraph->memvertices = 0;
236 hypergraph->memedges = 0;
237 hypergraph->memoverlaps = 0;
238 hypergraph->memedgesvertices = 0;
239 hypergraph->memverticesedges = 0;
240 hypergraph->memverticesedgesbeg = 0;
241 hypergraph->memoverlapsvertices = 0;
242 hypergraph->memedgesoverlaps = 0;
243 hypergraph->memedgesoverlapsbeg = 0;
244 hypergraph->sizevertexdata = sizevertexdata;
245 hypergraph->sizeedgedata = sizeedgedata;
246 hypergraph->sizeoverlapdata = sizeoverlapdata;
247
248 hypergraph->verticesdata = NULL;
249 hypergraph->verticesedgesbeg = NULL;
250 SCIP_CALL( ensureNumVertices(hypergraph, memvertices) );
251 hypergraph->edgesdata = NULL;
252 hypergraph->edgesverticesbeg = NULL;
253 SCIP_CALL( ensureNumEdges(hypergraph, memedges) );
254 hypergraph->overlapsdata = NULL;
255 hypergraph->overlapsverticesbeg = NULL;
256 hypergraph->overlapsvertices = NULL;
257 SCIP_CALL( ensureNumOverlaps(hypergraph, memoverlaps) );
258 hypergraph->edgesvertices = NULL;
259 hypergraph->verticesedges = NULL;
260 hypergraph->edgesoverlaps = NULL;
261 hypergraph->edgesoverlapsbeg = NULL;
262 SCIP_CALL( ensureNumEdgesVertices(hypergraph, memedgesvertices * memedges) );
263 hypergraph->overlaphashtable = NULL;
264
265 hypergraph->memoverlapsedgesbeg = 0;
266 hypergraph->overlapsedgesbeg = NULL;
267 hypergraph->memoverlapsedges = 0;
268 hypergraph->overlapsedges = NULL;
269
270 hypergraph->memverticesoverlapsbeg = 0;
271 hypergraph->verticesoverlapsbeg = NULL;
272 hypergraph->memverticesoverlaps = 0;
273 hypergraph->verticesoverlaps = NULL;
274
275 SCIP_CALL( SCIPhypergraphClear(hypergraph) );
276
277 return SCIP_OKAY;
278}
279
280/** @brief frees a hypergraph */
282 SCIP_HYPERGRAPH** phypergraph /**< Pointer to the hypergraph. */
283 )
284{
285 SCIP_HYPERGRAPH* hypergraph;
286
287 assert(phypergraph);
288
289 hypergraph = *phypergraph;
290 if( hypergraph == NULL )
291 return SCIP_OKAY;
292
293 BMSfreeBlockMemoryArray(hypergraph->blkmem, &hypergraph->verticesdata,
294 hypergraph->memvertices * hypergraph->sizevertexdata / sizeof(*hypergraph->verticesdata) );
295 BMSfreeBlockMemoryArray(hypergraph->blkmem, &hypergraph->edgesdata,
296 hypergraph->memedges * hypergraph->sizeedgedata / sizeof(*hypergraph->edgesdata));
297 if( hypergraph->edgesverticesbeg )
298 BMSfreeBlockMemoryArray(hypergraph->blkmem, &hypergraph->edgesverticesbeg, hypergraph->memedges + 1);
299 if( hypergraph->edgesvertices )
300 BMSfreeBlockMemoryArray(hypergraph->blkmem, &hypergraph->edgesvertices, hypergraph->memedgesvertices);
301
302 if( hypergraph->hasvertexedges )
303 {
304 if( hypergraph->verticesedges )
305 BMSfreeBlockMemoryArray(hypergraph->blkmem, &hypergraph->verticesedges, hypergraph->memverticesedges);
306 if( hypergraph->verticesedgesbeg )
307 BMSfreeBlockMemoryArray(hypergraph->blkmem, &hypergraph->verticesedgesbeg, hypergraph->memvertices + 1);
308 }
309
310 if( hypergraph->overlapsdata )
311 {
312 BMSfreeBlockMemoryArray(hypergraph->blkmem, &hypergraph->overlapsdata,
313 hypergraph->memoverlaps * hypergraph->sizeoverlapdata / sizeof(*hypergraph->overlapsdata));
314 }
315
316 if( hypergraph->overlapsverticesbeg )
317 BMSfreeBlockMemoryArray(hypergraph->blkmem, &hypergraph->overlapsverticesbeg, hypergraph->memoverlaps + 1);
318
319 if( hypergraph->hasoverlaps )
320 {
321 if( hypergraph->overlapsvertices )
322 BMSfreeBlockMemoryArray(hypergraph->blkmem, &hypergraph->overlapsvertices, hypergraph->memoverlapsvertices);
323 if( hypergraph->overlaphashtable )
325 if( hypergraph->edgesoverlapsbeg )
326 {
327 BMSfreeBlockMemoryArray(hypergraph->blkmem, &hypergraph->edgesoverlapsbeg,
328 hypergraph->memedgesoverlapsbeg + 1);
329 }
330 if( hypergraph->edgesoverlaps )
331 BMSfreeBlockMemoryArray(hypergraph->blkmem, &hypergraph->edgesoverlaps, hypergraph->memedgesoverlaps);
332 }
333
334 if( hypergraph->hasoverlapsedges )
335 {
336 if( hypergraph->overlapsedges )
337 BMSfreeBlockMemoryArray(hypergraph->blkmem, &hypergraph->overlapsedges, hypergraph->memoverlapsedges);
338 if( hypergraph->overlapsedgesbeg )
339 {
340 BMSfreeBlockMemoryArray(hypergraph->blkmem, &hypergraph->overlapsedgesbeg,
341 hypergraph->memoverlapsedgesbeg + 1);
342 }
343 }
344
345 if( hypergraph->hasverticesoverlaps )
346 {
347 BMSfreeBlockMemoryArray(hypergraph->blkmem, &hypergraph->verticesoverlaps, hypergraph->memverticesoverlaps);
348 if( hypergraph->verticesoverlapsbeg )
349 {
350 BMSfreeBlockMemoryArray(hypergraph->blkmem, &hypergraph->verticesoverlapsbeg,
351 hypergraph->memverticesoverlapsbeg + 1);
352 }
353 }
354
355 BMSfreeBlockMemory(hypergraph->blkmem, phypergraph);
356
357 return SCIP_OKAY;
358}
359
360/** @brief clears a hypergraph, deleting all vertices and edges */
362 SCIP_HYPERGRAPH* hypergraph /**< The hypergraph. */
363 )
364{
365 assert(hypergraph);
366
367 hypergraph->nvertices = 0;
368 hypergraph->nedges = 0;
369 hypergraph->noverlaps = 0;
370 if( hypergraph->edgesverticesbeg )
371 hypergraph->edgesverticesbeg[0] = 0;
372 hypergraph->hasvertexedges = FALSE;
373 hypergraph->hasoverlaps = FALSE;
374
375 if( hypergraph->overlaphashtable )
377
378 hypergraph->hasoverlapsedges = FALSE;
379 hypergraph->hasverticesoverlaps = FALSE;
380
381 return SCIP_OKAY;
382}
383
384
385/** @brief adds a new vertex to the hypergraph */
387 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
388 SCIP_HYPERGRAPH_VERTEX* pvertex, /**< Pointer for storing the new vertex. */
389 SCIP_HYPERGRAPH_VERTEXDATA** pvertexdata /**< Pointer for returning the vertex's data (may be \c NULL). */
390 )
391{
392 assert(hypergraph);
393 assert(pvertex);
394
395 SCIP_CALL( ensureNumVertices(hypergraph, hypergraph->nvertices + 1) );
396
397 *pvertex = hypergraph->nvertices;
398 if( pvertexdata != NULL )
399 {
400 assert( hypergraph->nvertices >= 0 );
401 *pvertexdata = (SCIP_HYPERGRAPH_VERTEXDATA*)(hypergraph->verticesdata
402 + hypergraph->nvertices * hypergraph->sizevertexdata / sizeof(*(hypergraph->verticesdata)) ); /*lint --e{737}*/
403 }
404
405 hypergraph->nvertices++;
406 hypergraph->hasvertexedges = FALSE;
407
408 return SCIP_OKAY;
409}
410
411/**
412 * @brief adds a new edge to the hypergraph
413 *
414 * Does not update the vertices' or overlaps' lists of incident edges.
415 */
417 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
418 int nvertices, /**< Number of vertices of this edge. */
419 SCIP_HYPERGRAPH_VERTEX* vertices, /**< Array with vertices. */
420 SCIP_HYPERGRAPH_EDGE* pedge, /**< Pointer for storing the new edge. */
421 SCIP_HYPERGRAPH_EDGEDATA** pedgedata /**< Pointer for returning the edge's data (may be \c NULL). */
422 )
423{
424 int first;
425 int beyond;
426
427 assert(hypergraph);
428 assert(nvertices > 0);
429 assert(vertices);
430 assert(pedge);
431
432 SCIP_CALL( ensureNumEdges(hypergraph, hypergraph->nedges + 1) );
433 first = hypergraph->edgesverticesbeg[hypergraph->nedges];
434 beyond = first + nvertices;
435 SCIP_CALL( ensureNumEdgesVertices(hypergraph, beyond) );
436 hypergraph->edgesverticesbeg[hypergraph->nedges + 1] = beyond;
437 for( int i = 0; i < nvertices; ++i )
438 hypergraph->edgesvertices[first + i] = vertices[i];
439 SCIPsortInt(&hypergraph->edgesvertices[first], nvertices);
440
441 *pedge = hypergraph->nedges;
442 if( pedgedata != NULL )
443 {
444 assert( hypergraph->nedges >= 0 );
445 *pedgedata = (SCIP_HYPERGRAPH_EDGEDATA*)(hypergraph->edgesdata +
446 hypergraph->nedges * hypergraph->sizeedgedata / sizeof(*(hypergraph->edgesdata))); /*lint --e{737}*/
447 }
448 hypergraph->nedges++;
449 hypergraph->hasvertexedges = FALSE;
450
451 return SCIP_OKAY;
452}
453
454/** @brief get-key function for overlap hashtable */
455static
456SCIP_DECL_HASHGETKEY(overlapHashGetKey)
457{ /*lint --e{715}*/
458 return elem;
459}
460
461/** @brief equality function for overlap hashtable */
462static
463SCIP_DECL_HASHKEYEQ(overlapHashKeyEqPtr)
464{
465 size_t o1;
466 size_t o2;
467 SCIP_HYPERGRAPH* hypergraph;
468 int begin1;
469 int beyond1;
470 int begin2;
471 int beyond2;
472 int i2;
473
474 o1 = (size_t)key1 - 1;
475 o2 = (size_t)key2 - 1;
476 hypergraph = (SCIP_HYPERGRAPH*) userptr;
477 begin1 = hypergraph->overlapsverticesbeg[o1];
478 beyond1 = hypergraph->overlapsverticesbeg[o1 + 1];
479 begin2 = hypergraph->overlapsverticesbeg[o2];
480 beyond2 = hypergraph->overlapsverticesbeg[o2 + 1];
481
482 if( beyond1 - begin1 != beyond2 - begin2 )
483 return FALSE;
484
485 i2 = begin2;
486 for( int i1 = begin1; i1 < beyond1; ++i1 )
487 {
488 if( hypergraph->overlapsvertices[i1] != hypergraph->overlapsvertices[i2] )
489 return FALSE;
490 ++i2;
491 }
492
493 return TRUE;
494}
495
496/** @brief hash function for overlap hashtable */
497static
498SCIP_DECL_HASHKEYVAL(overlapHashKeyValPtr)
499{
500 size_t o;
501 SCIP_HYPERGRAPH* hypergraph;
502 int begin;
503 int beyond;
504 int i;
505 uint32_t hash;
506
507 o = (size_t)key - 1;
508 hypergraph = (SCIP_HYPERGRAPH*) userptr;
509 begin = hypergraph->overlapsverticesbeg[o];
510 beyond = hypergraph->overlapsverticesbeg[o + 1];
511
512 assert(beyond > begin);
513
514 hash = (uint32_t) (beyond - begin);
515 for( i = begin + 2; i < beyond; i += 3 )
516 {
517 hash = SCIPhashFour(hash, hypergraph->overlapsvertices[i - 2], hypergraph->overlapsvertices[i - 1],
518 hypergraph->overlapsvertices[i]);
519 }
520 if( i - 1 < beyond )
521 hash = SCIPhashThree(hash, hypergraph->overlapsvertices[i - 2], hypergraph->overlapsvertices[i - 1]);
522 else if( i - 2 < beyond )
523 hash = SCIPhashTwo(hash, hypergraph->overlapsvertices[i - 2]);
524
525 return hash;
526}
527
528/** @brief finds an overlap specified by a sorted vertex set, potentially adding it */
529static
531 SCIP_HYPERGRAPH* hypergraph, /**< Hypergraph. */
532 int nvertices, /**< Number of vertices. */
533 int* vertices, /**< Sorted array of vertices. */
534 int* poverlap, /**< Pointer for storing the overlap. */
535 SCIP_Bool add, /**< Whether a missing overlap set should be added. */
536 SCIP_Bool* padded /**< Whether a missing overlap set was added. */
537 )
538{
539 int first;
540 int beyond;
541 void* element;
542 size_t nextoverlap;
543
544 assert(hypergraph);
545 assert(nvertices > 0);
546 assert(vertices);
547 assert(poverlap);
548
549 /* In order to find a set of vertices we need to add it to the overlaps' vertex storage. */
550
551 SCIP_CALL( ensureNumOverlaps(hypergraph, hypergraph->noverlaps + 1) );
552 first = hypergraph->overlapsverticesbeg[hypergraph->noverlaps];
553 beyond = first + nvertices;
554 SCIP_CALL( ensureNumOverlapsVertices(hypergraph, beyond) );
555 for( int i = 0; i < nvertices; ++i )
556 hypergraph->overlapsvertices[first + i] = vertices[i];
557 hypergraph->overlapsverticesbeg[hypergraph->noverlaps + 1] = beyond;
558
559 nextoverlap = (size_t) hypergraph->noverlaps + 1UL; /*lint !e571 */
560 element = SCIPhashtableRetrieve(hypergraph->overlaphashtable, (void*) nextoverlap);
561 if( element != NULL )
562 {
563 *poverlap = (size_t)element - 1; /*lint !e712*/
564 if( padded )
565 *padded = FALSE;
566 }
567 else if( add )
568 {
569 SCIP_CALL_ABORT( SCIPhashtableInsert(hypergraph->overlaphashtable, (void*) nextoverlap) );
570
571 *poverlap = hypergraph->noverlaps;
572 hypergraph->noverlaps++;
573 if( padded )
574 *padded = TRUE;
575 }
576 else
577 *poverlap = -1;
578
579 return SCIP_OKAY;
580}
581
582/**
583 * @brief computes all overlaps and stores overlaps' vertices and all edges' overlaps
584 *
585 * Requires \ref SCIPhypergraphHasVertexEdges to be \c TRUE which results from \ref SCIPhypergraphComputeVerticesEdges.
586 */
588 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
589 SCIP_DECL_HYPERGRAPH_OVERLAP((*handler)), /**< Function to be called once the overlap is found. */
590 void* userdata /**< Pointer passed to \p handler. */
591 )
592{
593 int memCommonVertices = 32;
594 int* commonVertices = NULL;
595 int numCommonVertices;
596 int memEdgeOverlapPairs;
597 int numEdgeOverlapPairs = 0;
598 SCIP_Longint* edgeOverlapPairs = NULL;
599 int o;
600 int lastEdge;
601
602 assert(hypergraph);
603
604 if( !hypergraph->hasvertexedges )
605 return SCIP_ERROR;
606
607 if( hypergraph->hasoverlaps )
608 return SCIP_OKAY;
609
610 hypergraph->noverlaps = 0;
611 hypergraph->overlapsverticesbeg[0] = 0;
612
613 hypergraph->hasoverlaps = TRUE;
614 assert(hypergraph->overlaphashtable == NULL);
615 SCIP_CALL( SCIPhashtableCreate(&hypergraph->overlaphashtable, hypergraph->blkmem, 4 * hypergraph->nedges + 4,
616 overlapHashGetKey, overlapHashKeyEqPtr, overlapHashKeyValPtr, hypergraph) );
617
618 /* Allocate memory for the vertices in common to two edges. */
619 SCIP_ALLOC( BMSallocBlockMemoryArray(hypergraph->blkmem, &commonVertices, memCommonVertices) );
620
621 /* Allocate memory for an array consisting of pairs (e,o) where o is an overlap incident to edge e. */
622 memEdgeOverlapPairs = 2 * (hypergraph->nedges + hypergraph->noverlaps) + 2;
623 SCIP_ALLOC( BMSallocBlockMemoryArray(hypergraph->blkmem, &edgeOverlapPairs, memEdgeOverlapPairs) );
624
625 /* We iterate over all edges e. */
626 for( SCIP_HYPERGRAPH_EDGE e = 0; e < hypergraph->nedges; ++e )
627 {
628 int eBeyond;
629 int eSize;
630
631 eBeyond = hypergraph->edgesverticesbeg[e + 1];
632 eSize = eBeyond - hypergraph->edgesverticesbeg[e];
633 if( eSize > memCommonVertices )
634 {
635 int newcapacity;
636 newcapacity = memCommonVertices;
637 while( memCommonVertices < eSize )
638 memCommonVertices *= 2;
639 SCIP_ALLOC( BMSreallocBlockMemoryArray(hypergraph->blkmem, &commonVertices, newcapacity, memCommonVertices) );
640 }
641
642 /* We iterate over all vertices v of e and then over all edges f incident to v to avoid scanning all pairs
643 * of edges because most of them will be disjoint. */
644 for( int i = 0; i < eSize; ++i )
645 {
647 int vFirst, vBeyond;
648
649 v = hypergraph->edgesvertices[hypergraph->edgesverticesbeg[e] + i];
650 vFirst = hypergraph->verticesedgesbeg[v];
651 vBeyond = hypergraph->verticesedgesbeg[v + 1];
652 for( int j = vFirst; j < vBeyond; ++j )
653 {
655 int fBeyond;
656 int ie;
657 int je;
658 int u;
659 int w;
660
661 f = hypergraph->verticesedges[j];
662
663 /* Avoid considering (e,f) and (f,e). */
664 if( f <= e )
665 continue;
666
667 /* We now traverse the sorted lists of vertices of e and f simultaneously to find common vertices. */
668 fBeyond = hypergraph->edgesverticesbeg[f + 1];
669 numCommonVertices = 0;
670 ie = hypergraph->edgesverticesbeg[e];
671 je = hypergraph->edgesverticesbeg[f];
672 while( ie < eBeyond && je < fBeyond )
673 {
674 u = hypergraph->edgesvertices[ie];
675 w = hypergraph->edgesvertices[je];
676 if( u < w )
677 ++ie;
678 else if( u > w )
679 ++je;
680 else
681 {
682 /* Vertex u = w is part of e and of f. */
683 if( numCommonVertices == 0 && u != v )
684 {
685 /* v is not the minimum vertex in e \cap f, so we skip f since we have considered it already
686 * for a smaller v. */
687 break;
688 }
689 commonVertices[numCommonVertices++] = u;
690 ++ie;
691 ++je;
692 }
693 }
694
695 /* We only consider overlap sets that are not just vertices. */
696 if( numCommonVertices >= 2 )
697 {
698 int overlap;
699 SCIP_Bool added;
700 uint64_t ebits;
701 uint64_t fbits;
702 uint64_t obits;
703 uint64_t ocardinalitybits;
704
705 /* Find out if that overlap (as a set) already exists. */
706 SCIP_CALL( findOverlap(hypergraph, numCommonVertices, commonVertices, &overlap, TRUE, &added) );
707 if( handler != NULL )
708 {
709 SCIP_CALL( handler(hypergraph, overlap, SCIPhypergraphOverlapData(hypergraph, overlap), e, f, added,
710 userdata) );
711 }
712
713 if( numEdgeOverlapPairs >= memEdgeOverlapPairs - 1 )
714 {
715 SCIP_ALLOC( BMSreallocBlockMemoryArray(hypergraph->blkmem, &edgeOverlapPairs, memEdgeOverlapPairs,
716 2 * memEdgeOverlapPairs) ); /*lint !e647 */
717 memEdgeOverlapPairs *= 2;
718 }
719
720 /* For the pair (overlap,e) we store (e << 40) | (|overlap| << 24) | overlap and sort by it to find
721 * duplicates and the get overlaps incident to e in order of increasing cardinality. */
722 assert(overlap >= 0);
723 assert(numCommonVertices >= 0);
724 assert(e >= 0);
725 assert(f >= 0);
726 obits = (uint64_t) overlap; /*lint !e571*/
727 ocardinalitybits = ((uint64_t) numCommonVertices) << 24; /*lint !e571*/
728 ebits = ((uint64_t) e) << 40; /*lint !e571*/
729 ebits |= ocardinalitybits | obits;
730 fbits = ((uint64_t) f) << 40; /*lint !e571*/
731 fbits |= ocardinalitybits | obits;
732 edgeOverlapPairs[numEdgeOverlapPairs] = (long long) ebits;
733 edgeOverlapPairs[numEdgeOverlapPairs + 1] = (long long) fbits;
734 numEdgeOverlapPairs += 2;
735 }
736 }
737 }
738 }
739
740 SCIPdebugMessage("found %d edge-overlap incidences, including possible duplicates.\n", numEdgeOverlapPairs);
741 SCIPsortLong(edgeOverlapPairs, numEdgeOverlapPairs);
742
743 o = -1; /* Last pair written. */
744 for( int i = 0; i < numEdgeOverlapPairs; ++i)
745 {
746 if( o < 0 || edgeOverlapPairs[i] != edgeOverlapPairs[o] )
747 edgeOverlapPairs[++o] = edgeOverlapPairs[i];
748 }
749
750 numEdgeOverlapPairs = o + 1;
751 SCIPdebugMessage("found %d unique edge-overlap incidences.\n", numEdgeOverlapPairs);
752
753 /* Compute edges' incident overlaps. */
754 if( hypergraph->memedgesoverlapsbeg == 0 || hypergraph->memedgesoverlapsbeg < hypergraph->nedges )
755 {
756 int newcapacity;
757
758 newcapacity = MAX(256, hypergraph->memedgesoverlapsbeg);
759 while( newcapacity < hypergraph->nedges )
760 newcapacity *= 2;
761 if( hypergraph->edgesoverlapsbeg )
762 {
764 hypergraph->memedgesoverlapsbeg + 1, newcapacity + 1) );
765 }
766 else
767 {
768 assert(hypergraph->memedgesoverlapsbeg == 0);
769 SCIP_ALLOC( BMSallocBlockMemoryArray(hypergraph->blkmem, &hypergraph->edgesoverlapsbeg, newcapacity + 1) );
770 }
771 hypergraph->memedgesoverlapsbeg = newcapacity;
772 }
773
774 if( hypergraph->memedgesoverlaps < numEdgeOverlapPairs )
775 {
776 int newcapacity;
777
778 newcapacity = MAX(256, hypergraph->memedgesoverlaps);
779 while( newcapacity < numEdgeOverlapPairs )
780 newcapacity *= 2;
782 hypergraph->memedgesoverlaps, newcapacity) );
783 hypergraph->memedgesoverlaps = newcapacity;
784 }
785
786 lastEdge = -1;
787 for( int i = 0; i < numEdgeOverlapPairs; ++i )
788 {
789 uint64_t bits;
790 int edge;
791 int overlap;
792
793 bits = (uint64_t) edgeOverlapPairs[i];
794 edge = (int) (bits >> 40); /*lint !e704 */
795 overlap = bits & ((1L << 24) - 1L); /*lint !e712 */
796
797 while( lastEdge < edge )
798 hypergraph->edgesoverlapsbeg[++lastEdge] = i;
799 hypergraph->edgesoverlaps[i] = overlap;
800 }
801 while( lastEdge < hypergraph->nedges )
802 hypergraph->edgesoverlapsbeg[++lastEdge] = numEdgeOverlapPairs;
803
804 BMSfreeBlockMemoryArray(hypergraph->blkmem, &edgeOverlapPairs, memEdgeOverlapPairs);
805 BMSfreeBlockMemoryArray(hypergraph->blkmem, &commonVertices, memCommonVertices);
806
807 return SCIP_OKAY;
808}
809
810/** @brief computes each vertex' list of incident edges */
812 SCIP_HYPERGRAPH* hypergraph /**< The hypergraph. */
813 )
814{
815 int nincidences;
816
817 assert(hypergraph);
818
819 if( hypergraph->hasvertexedges )
820 return SCIP_OKAY;
821
822 if( hypergraph->memverticesedgesbeg == 0 || hypergraph->memverticesedgesbeg < hypergraph->nvertices )
823 {
824 int newcapacity = MAX(256, hypergraph->memvertices);
825 while( newcapacity < hypergraph->nvertices )
826 newcapacity *= 2;
827
828 if( hypergraph->verticesedgesbeg )
829 {
831 hypergraph->memverticesedgesbeg + 1, newcapacity + 1) );
832 }
833 else
834 {
835 assert(hypergraph->memverticesedgesbeg == 0);
836 SCIP_ALLOC( BMSallocBlockMemoryArray(hypergraph->blkmem, &hypergraph->verticesedgesbeg, newcapacity + 1) );
837 }
838 hypergraph->memverticesedgesbeg = newcapacity;
839 SCIPdebugMessage("ensuring memory for %d vertices' edges slice.\n", newcapacity);
840 }
841
842 /* We know the total number of vertex-edge incidences from the edges. */
843 nincidences = hypergraph->edgesverticesbeg[hypergraph->nedges];
844 if( hypergraph->memverticesedges < nincidences )
845 {
846 int newcapacity;
847
848 newcapacity = MAX(256, hypergraph->memverticesedges);
849 while( newcapacity < nincidences )
850 newcapacity *= 2;
851
853 hypergraph->memverticesedges, newcapacity) );
854 hypergraph->memverticesedges = newcapacity;
855 SCIPdebugMessage("ensuring memory for %d vertices' edges.\n", newcapacity);
856 }
857
858 /* We initialize beg[v] = 0. */
859 for( SCIP_HYPERGRAPH_VERTEX v = 0; v < hypergraph->nvertices; ++v)
860 hypergraph->verticesedgesbeg[v] = 0;
861
862 /* We traverse through all incidences (using the edges' vertex arrays) and count the degree deg(v) in beg[v]. */
863 for( int i = 0; i < nincidences; ++i)
864 hypergraph->verticesedgesbeg[hypergraph->edgesvertices[i]]++;
865
866 /* This loop sets beg[0] = 0, beg[1] = deg(0), beg[2] = deg(0) + deg(1), beg[v] = deg(0) + ... + deg(v-1). */
867 int current = 0;
868 for( SCIP_HYPERGRAPH_VERTEX v = 0; v < hypergraph->nvertices; ++v )
869 {
870 int temp;
871
872 temp = current;
873 current += hypergraph->verticesedgesbeg[v];
874 hypergraph->verticesedgesbeg[v] = temp;
875 }
876
877 /* We now traverse through all edges e and their incident vertices v, storing e at beg[v], which is incremented. */
878 for( SCIP_HYPERGRAPH_EDGE e = 0; e < hypergraph->nedges; ++e )
879 {
880 int first;
881 int beyond;
882
883 first = hypergraph->edgesverticesbeg[e];
884 beyond = hypergraph->edgesverticesbeg[e + 1];
885 for( int i = first; i < beyond; ++i )
886 {
887 SCIP_HYPERGRAPH_VERTEX v = hypergraph->edgesvertices[i];
888 hypergraph->verticesedges[hypergraph->verticesedgesbeg[v]++] = e;
889 }
890 }
891
892 /* We now revert the incrementation of the beg[v]-values again. */
893 for( SCIP_HYPERGRAPH_VERTEX v = hypergraph->nvertices; v > 0; --v )
894 hypergraph->verticesedgesbeg[v] = hypergraph->verticesedgesbeg[v-1];
895 hypergraph->verticesedgesbeg[0] = 0;
896 hypergraph->hasvertexedges = TRUE;
897
898 return SCIP_OKAY;
899}
900
901/**
902 * @brief finds the overlap corresponding to vertex set \p vertices; returns -1 if it is not found
903 *
904 * Requires \ref SCIPhypergraphHasOverlaps to be \c TRUE which results from \ref SCIPhypergraphComputeOverlaps.
905 */
907 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
908 int nvertices, /**< Number of vertices. */
909 SCIP_HYPERGRAPH_VERTEX* vertices, /**< Sorted array of vertices. */
910 SCIP_HYPERGRAPH_OVERLAP* poverlap /**< Pointer for storing the overlap. */
911 )
912{
913 assert(hypergraph);
914 assert(nvertices > 0);
915 assert(vertices);
916 assert(poverlap);
917 assert(hypergraph->hasoverlaps);
918
919 SCIP_CALL( findOverlap(hypergraph, nvertices, vertices, poverlap, FALSE, NULL) );
920
921 return SCIP_OKAY;
922}
923
924/**
925 * @brief finds the overlap or singleton vertex corresponding to the intersection of edges \p first and \p second
926 *
927 * Requires \ref SCIPhypergraphHasOverlaps to be \c TRUE which results from \ref SCIPhypergraphComputeOverlaps.
928 */
930 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
931 SCIP_HYPERGRAPH_EDGE first, /**< First edge to intersect. */
932 SCIP_HYPERGRAPH_EDGE second, /**< Second edge to intersect. */
933 SCIP_HYPERGRAPH_OVERLAP* poverlap, /**< Pointer for storing the overlap. */
934 SCIP_HYPERGRAPH_VERTEX* pvertex /**< Pointer for storing the vertex. */
935 )
936{
937 int* commonVertices = NULL;
938 int memCommonVertices;
939 int firstBeyond;
940 int secondBeyond;
941 int numCommonVertices = 0;
942 int i;
943 int j;
944
945 assert(hypergraph);
946 assert(first >= 0 && first < hypergraph->nedges);
947 assert(second >= 0 && second < hypergraph->nedges);
948 assert(poverlap);
949 assert(hypergraph->hasoverlaps);
950
951 memCommonVertices = SCIPhypergraphEdgeSize(hypergraph, first);
952 SCIP_ALLOC( BMSallocBlockMemoryArray(hypergraph->blkmem, &commonVertices, memCommonVertices) );
953 firstBeyond = hypergraph->edgesverticesbeg[first + 1];
954 secondBeyond = hypergraph->edgesverticesbeg[second + 1];
955 i = hypergraph->edgesverticesbeg[first];
956 j = hypergraph->edgesverticesbeg[second];
957 while( i < firstBeyond && j < secondBeyond )
958 {
959 int u;
960 int w;
961
962 u = hypergraph->edgesvertices[i];
963 w = hypergraph->edgesvertices[j];
964 if( u < w )
965 ++i;
966 else if( u > w )
967 ++j;
968 else
969 {
970 commonVertices[numCommonVertices++] = u;
971 ++i;
972 ++j;
973 }
974 }
975
976 SCIP_CALL( findOverlap(hypergraph, numCommonVertices, commonVertices, poverlap, FALSE, NULL) );
977 if( (*poverlap) < 0 && pvertex != NULL )
978 *pvertex = numCommonVertices > 0 ? commonVertices[0] : -1;
979
980 BMSfreeBlockMemoryArray(hypergraph->blkmem, &commonVertices, memCommonVertices);
981
982 return SCIP_OKAY;
983}
984
985/**
986 * @brief computes all overlaps' lists of incident edges
987 *
988 * Requires \ref SCIPhypergraphHasOverlaps to be \c TRUE which results from \ref SCIPhypergraphComputeOverlaps.
989 */
991 SCIP_HYPERGRAPH* hypergraph /**< The hypergraph. */
992 )
993{
994 int nincidences;
995 int current;
996
997 assert(hypergraph);
998 assert(hypergraph->hasoverlaps);
999
1000 if( hypergraph->hasoverlapsedges )
1001 return SCIP_OKAY;
1002
1003 if( hypergraph->memoverlapsedgesbeg < hypergraph->noverlaps + 1 )
1004 {
1005 int newcapacity;
1006
1007 newcapacity = MAX(256, hypergraph->memoverlapsedgesbeg);
1008 while( newcapacity < hypergraph->noverlaps )
1009 newcapacity *= 2;
1010
1011 if( hypergraph->overlapsedgesbeg )
1012 {
1014 hypergraph->memoverlapsedgesbeg + 1, newcapacity + 1) );
1015 }
1016 else
1017 {
1018 assert(hypergraph->memoverlapsedgesbeg == 0);
1019 SCIP_ALLOC( BMSallocBlockMemoryArray(hypergraph->blkmem, &hypergraph->overlapsedgesbeg, newcapacity + 1) );
1020 }
1021 hypergraph->memoverlapsedgesbeg = newcapacity;
1022 SCIPdebugMessage("ensuring memory for %d overlaps' edges slice.\n", newcapacity);
1023 }
1024
1025 /* We know the total number of overlap-edge incidences from the edges. */
1026 nincidences = hypergraph->edgesoverlapsbeg[hypergraph->nedges];
1027 if( hypergraph->memoverlapsedges < nincidences )
1028 {
1029 int newcapacity;
1030
1031 newcapacity = MAX(256, hypergraph->memoverlaps);
1032 while( newcapacity < nincidences )
1033 newcapacity *= 2;
1034
1035 SCIP_ALLOC( BMSreallocBlockMemoryArray(hypergraph->blkmem, &hypergraph->overlapsedges,
1036 hypergraph->memoverlapsedges, newcapacity) );
1037 hypergraph->memoverlapsedges = newcapacity;
1038 SCIPdebugMessage("ensuring memory for %d overlaps' edges.\n", newcapacity);
1039 }
1040
1041 /* We initialize beg[v] = 0. */
1042 for( SCIP_HYPERGRAPH_OVERLAP o = 0; o < hypergraph->noverlaps; ++o )
1043 hypergraph->overlapsedgesbeg[o] = 0;
1044
1045 /* We traverse through all incidences (using the edges' overlap arrays) and count the degree deg(o) in beg[o],
1046 * where deg(o) shall denote the number of edges incident to overlap o. */
1047 for( int i = 0; i < nincidences; ++i )
1048 hypergraph->overlapsedgesbeg[hypergraph->edgesoverlaps[i]]++;
1049
1050 /* This loop sets beg[0] = 0, beg[1] = deg(0), beg[2] = deg(0) + deg(1), beg[o] = deg(0) + ... + deg(o-1) */
1051 current = 0;
1052 for( SCIP_HYPERGRAPH_OVERLAP o = 0; o < hypergraph->noverlaps; ++o )
1053 {
1054 int temp;
1055
1056 temp = current;
1057 current += hypergraph->overlapsedgesbeg[o];
1058 hypergraph->overlapsedgesbeg[o] = temp;
1059 }
1060
1061 /* We now traverse through all edges e and their incident overlaps o, storing e at beg[o], which is incremented. */
1062 for( SCIP_HYPERGRAPH_EDGE e = 0; e < hypergraph->nedges; ++e )
1063 {
1064 int first;
1065 int beyond;
1066
1067 first = hypergraph->edgesoverlapsbeg[e];
1068 beyond = hypergraph->edgesoverlapsbeg[e + 1];
1069 for( int i = first; i < beyond; ++i )
1070 {
1071 SCIP_HYPERGRAPH_OVERLAP o = hypergraph->edgesoverlaps[i];
1072 hypergraph->overlapsedges[hypergraph->overlapsedgesbeg[o]++] = e;
1073 }
1074 }
1075
1076 /* We now revert the incrementation of the beg[o]-values again. */
1077 for( SCIP_HYPERGRAPH_OVERLAP o = hypergraph->noverlaps; o > 0; --o )
1078 hypergraph->overlapsedgesbeg[o] = hypergraph->overlapsedgesbeg[o-1];
1079 hypergraph->overlapsedgesbeg[0] = 0;
1080 hypergraph->hasoverlapsedges = TRUE;
1081
1082 return SCIP_OKAY;
1083}
1084
1085
1086/**
1087 * @brief computes all vertices' lists of incident overlaps
1088 *
1089 * Requires \ref SCIPhypergraphHasOverlaps.
1090 */
1092 SCIP_HYPERGRAPH* hypergraph /**< The hypergraph. */
1093 )
1094{
1095 int nincidences;
1096 int current;
1097
1098 assert(hypergraph);
1099 assert(hypergraph->hasoverlaps);
1100
1101 if( hypergraph->hasverticesoverlaps )
1102 return SCIP_OKAY;
1103
1104 if( hypergraph->memverticesoverlapsbeg < hypergraph->nvertices )
1105 {
1106 int newcapacity;
1107
1108 newcapacity = MAX(256, hypergraph->memverticesoverlapsbeg);
1109 while( newcapacity < hypergraph->nvertices )
1110 newcapacity *= 2;
1111
1112 if( hypergraph->verticesoverlapsbeg )
1113 {
1115 hypergraph->memverticesoverlapsbeg, newcapacity) );
1116 }
1117 else
1118 {
1119 assert(hypergraph->memverticesoverlapsbeg == 0);
1120 SCIP_ALLOC( BMSallocBlockMemoryArray(hypergraph->blkmem, &hypergraph->verticesoverlapsbeg, newcapacity) );
1121 }
1122 hypergraph->memverticesoverlapsbeg = newcapacity;
1123 SCIPdebugMessage("ensuring memory for %d vertices' overlaps slice.\n", newcapacity);
1124 }
1125
1126 /* We know the total number of vertex-overlap incidences from the over. */
1127 nincidences = hypergraph->overlapsverticesbeg[hypergraph->noverlaps];
1128 if( hypergraph->memverticesoverlaps < nincidences )
1129 {
1130 int newcapacity;
1131
1132 newcapacity = MAX(256, hypergraph->memverticesoverlaps);
1133 while( newcapacity < nincidences )
1134 newcapacity *= 2;
1135
1137 hypergraph->memverticesoverlaps, newcapacity) );
1138 hypergraph->memverticesoverlaps = newcapacity;
1139 SCIPdebugMessage("ensuring memory for %d vertices' overlaps.\n", newcapacity);
1140 }
1141
1142 /* We initialize beg[v] = 0. */
1143 for( SCIP_HYPERGRAPH_VERTEX v = 0; v < hypergraph->nvertices; ++v )
1144 hypergraph->verticesoverlapsbeg[v] = 0;
1145
1146 /* We traverse through all incidences (using the overlaps' vertex arrays) and count the degree deg(v) in beg[v],
1147 * where deg(v) shall denote the number of overlaps incident to vertex v. */
1148 for( int i = 0; i < nincidences; ++i )
1149 hypergraph->verticesoverlapsbeg[hypergraph->overlapsvertices[i]]++;
1150
1151 /* This loop sets beg[0] = 0, beg[1] = deg(0), beg[2] = deg(0) + deg(1), beg[v] = deg(0) + ... + deg(v-1) */
1152 current = 0;
1153 for( SCIP_HYPERGRAPH_VERTEX v = 0; v < hypergraph->nvertices; ++v )
1154 {
1155 int temp;
1156
1157 temp = current;
1158 current += hypergraph->verticesoverlapsbeg[v];
1159 hypergraph->verticesoverlapsbeg[v] = temp;
1160 }
1161
1162 /* We traverse through all overlaps o and their incident vertices v, storing o at beg[v], which is incremented. */
1163 for( SCIP_HYPERGRAPH_OVERLAP o = 0; o < hypergraph->noverlaps; ++o )
1164 {
1165 int first;
1166 int beyond;
1167
1168 first = hypergraph->overlapsverticesbeg[o];
1169 beyond = hypergraph->overlapsverticesbeg[o + 1];
1170 for( int i = first; i < beyond; ++i )
1171 {
1172 SCIP_HYPERGRAPH_VERTEX v = hypergraph->overlapsvertices[i];
1173 hypergraph->verticesoverlaps[hypergraph->verticesoverlapsbeg[v]++] = o;
1174 }
1175 }
1176
1177 /* We now revert the incrementation of the beg[o]-values again. */
1178 for( SCIP_HYPERGRAPH_VERTEX v = hypergraph->nvertices; v > 0; --v )
1179 hypergraph->verticesoverlapsbeg[v] = hypergraph->verticesoverlapsbeg[v-1];
1180 hypergraph->verticesoverlapsbeg[0] = 0;
1181 hypergraph->hasverticesoverlaps = TRUE;
1182
1183 return SCIP_OKAY;
1184}
1185
1186/** @brief returns whether overlaps \p overlap1 and \p overlap2 are disjoint */
1188 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
1189 SCIP_HYPERGRAPH_OVERLAP overlap1, /**< First overlap. */
1190 SCIP_HYPERGRAPH_OVERLAP overlap2 /**< Second overlap. */
1191 )
1192{
1193 int size1;
1194 SCIP_HYPERGRAPH_VERTEX* vertices1;
1195 int size2;
1196 SCIP_HYPERGRAPH_VERTEX* vertices2;
1197 int i = 0;
1198 int j = 0;
1199
1200 assert(hypergraph);
1201
1202 /* We loop over the vertices in parallel because they are sorted. */
1203 size1 = SCIPhypergraphOverlapSize(hypergraph, overlap1);
1204 vertices1 = SCIPhypergraphOverlapVertices(hypergraph, overlap1);
1205 size2 = SCIPhypergraphOverlapSize(hypergraph, overlap2);
1206 vertices2 = SCIPhypergraphOverlapVertices(hypergraph, overlap2);
1207 while( i < size1 && j < size2 )
1208 {
1209 if( vertices1[i] < vertices2[j] )
1210 ++i;
1211 else if( vertices1[i] > vertices2[j] )
1212 ++j;
1213 else
1214 return FALSE;
1215 }
1216
1217 return TRUE;
1218}
1219
1220/** @brief asserts that the hypergraph data structures are valid */
1222 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
1223 FILE* file /**< A file stream to print problems to (can be \c NULL). */
1224 )
1225{
1226 SCIP_Bool valid = TRUE;
1227
1228 assert(hypergraph);
1229
1230 if( SCIPhypergraphHasVertexEdges(hypergraph) )
1231 {
1232 int nincidences;
1233 long long* incidences1 = NULL;
1234 long long* incidences2 = NULL;
1235 int i1 = 0;
1236 int i2 = 0;
1237
1238 nincidences = SCIPhypergraphGetNIncidences(hypergraph);
1239 SCIP_ALLOC_ABORT( BMSallocBlockMemoryArray(hypergraph->blkmem, &incidences1, nincidences) );
1240 SCIP_ALLOC_ABORT( BMSallocBlockMemoryArray(hypergraph->blkmem, &incidences2, nincidences) );
1241 for( SCIP_HYPERGRAPH_EDGE e = 0; e < SCIPhypergraphGetNEdges(hypergraph); ++e )
1242 {
1243 int esize = SCIPhypergraphEdgeSize(hypergraph, e);
1244 for( int i = 0; i < esize; ++i )
1245 {
1247 long long pair = v + (long long) SCIPhypergraphGetNVertices(hypergraph) * (long long) e;
1248 incidences1[i1++] = pair;
1249 }
1250 }
1251
1252 if ( i1 != nincidences )
1253 {
1254 valid = FALSE;
1255 if( file )
1256 {
1257 fprintf(file, "SCIPhypergraphIsValid detected inconsistency: "
1258 "number of incidences is claimed to be %d but counting via edges yields %d!\n", nincidences, i1);
1259 fflush(file);
1260 }
1261 }
1262
1263 for( SCIP_HYPERGRAPH_VERTEX v = 0; v < SCIPhypergraphGetNVertices(hypergraph); ++v )
1264 {
1265 int first = SCIPhypergraphVertexEdgesFirst(hypergraph, v);
1266 int beyond = SCIPhypergraphVertexEdgesBeyond(hypergraph, v);
1267 for( int j = first; j < beyond; ++j )
1268 {
1270 long long pair = v + (long long) SCIPhypergraphGetNVertices(hypergraph) * (long long) e;
1271 incidences2[i2++] = pair;
1272 }
1273 }
1274
1275 if ( i2 != nincidences )
1276 {
1277 valid = FALSE;
1278 if( file )
1279 {
1280 fprintf(file, "SCIPhypergraphIsValid detected inconsistency: "
1281 "number of incidences is claimed to be %d but counting via vertices yields %d!\n", nincidences, i2);
1282 fflush(file);
1283 }
1284 }
1285
1286 if( valid )
1287 {
1288 SCIPsortLong(incidences1, nincidences);
1289 SCIPsortLong(incidences2, nincidences);
1290
1291 for( int i = 0; i < nincidences; ++i )
1292 {
1293 if( incidences1[i] != incidences2[i] )
1294 {
1295 valid = FALSE;
1296 if( file )
1297 {
1298 fprintf(file, "SCIPhypergraphIsValid detected inconsistency: "
1299 "incidence #%d is %lld (via edges) and %lld (via vertices)!\n", i, incidences1[i], incidences2[i]);
1300 fflush(file);
1301 }
1302 }
1303 }
1304 }
1305
1306 BMSfreeBlockMemoryArray(hypergraph->blkmem, &incidences2, nincidences);
1307 BMSfreeBlockMemoryArray(hypergraph->blkmem, &incidences1, nincidences);
1308 }
1309
1310 if( SCIPhypergraphHasVertexEdges(hypergraph) )
1311 {
1312 int nincidences;
1313 long long* incidences1 = NULL;
1314 long long* incidences2 = NULL;
1315 int i1 = 0;
1316 int i2 = 0;
1317
1318 nincidences = SCIPhypergraphGetNIncidences(hypergraph);
1319 SCIP_ALLOC_ABORT( BMSallocBlockMemoryArray(hypergraph->blkmem, &incidences1, nincidences) );
1320 SCIP_ALLOC_ABORT( BMSallocBlockMemoryArray(hypergraph->blkmem, &incidences2, nincidences) );
1321 for( SCIP_HYPERGRAPH_EDGE e = 0; e < SCIPhypergraphGetNEdges(hypergraph); ++e )
1322 {
1323 int esize = SCIPhypergraphEdgeSize(hypergraph, e);
1324 for( int i = 0; i < esize; ++i )
1325 {
1327 long long pair = v + (long long) SCIPhypergraphGetNVertices(hypergraph) * (long long) e;
1328 incidences1[i1++] = pair;
1329 }
1330 }
1331
1332 if ( i1 != nincidences )
1333 {
1334 valid = FALSE;
1335 if( file )
1336 {
1337 fprintf(file, "SCIPhypergraphIsValid detected inconsistency: "
1338 "number of incidences is claimed to be %d but counting via edges yields %d!\n", nincidences, i1);
1339 fflush(file);
1340 }
1341 }
1342
1343 for( SCIP_HYPERGRAPH_VERTEX v = 0; v < SCIPhypergraphGetNVertices(hypergraph); ++v )
1344 {
1345 int first = SCIPhypergraphVertexEdgesFirst(hypergraph, v);
1346 int beyond = SCIPhypergraphVertexEdgesBeyond(hypergraph, v);
1347 for( int j = first; j < beyond; ++j )
1348 {
1350 long long pair = v + (long long) SCIPhypergraphGetNVertices(hypergraph) * (long long) e;
1351 incidences2[i2++] = pair;
1352 }
1353 }
1354
1355 if ( i2 != nincidences )
1356 {
1357 valid = FALSE;
1358 if( file )
1359 {
1360 fprintf(file, "SCIPhypergraphIsValid detected inconsistency: "
1361 "number of incidences is claimed to be %d but counting via vertices yields %d!\n", nincidences, i2);
1362 fflush(file);
1363 }
1364 }
1365
1366 if( valid )
1367 {
1368 SCIPsortLong(incidences1, nincidences);
1369 SCIPsortLong(incidences2, nincidences);
1370
1371 for( int i = 0; i < nincidences; ++i )
1372 {
1373 if( incidences1[i] != incidences2[i] )
1374 {
1375 valid = FALSE;
1376 if( file )
1377 {
1378 fprintf(file, "SCIPhypergraphIsValid detected inconsistency: "
1379 "incidence #%d is %lld (via edges) and %lld (via vertices)!\n", i, incidences1[i], incidences2[i]);
1380 fflush(file);
1381 }
1382 }
1383 }
1384 }
1385
1386 BMSfreeBlockMemoryArray(hypergraph->blkmem, &incidences2, nincidences);
1387 BMSfreeBlockMemoryArray(hypergraph->blkmem, &incidences1, nincidences);
1388 }
1389
1390 if( SCIPhypergraphHasOverlaps(hypergraph) )
1391 {
1392 int n;
1393 SCIP_Bool* marked = NULL;
1394
1395 /* Verify edge-overlap incidences. */
1396 n = SCIPhypergraphGetNVertices(hypergraph);
1397 SCIP_ALLOC_ABORT( BMSallocBlockMemoryArray(hypergraph->blkmem, &marked, n) );
1398 for( SCIP_HYPERGRAPH_VERTEX v = 0; v < n; ++v )
1399 marked[v] = FALSE;
1400 for( SCIP_HYPERGRAPH_EDGE e = 0; e < hypergraph->nedges && valid; ++e )
1401 {
1402 int first;
1403 int beyond;
1404 int esize;
1405 int lastcardinality = 0;
1406
1407 esize = SCIPhypergraphEdgeSize(hypergraph, e);
1408 SCIP_HYPERGRAPH_VERTEX* evertices = SCIPhypergraphEdgeVertices(hypergraph, e);
1409 for( int i = 0; i < esize; ++i )
1410 marked[evertices[i]] = TRUE;
1411 first = SCIPhypergraphEdgesOverlapsFirst(hypergraph, e);
1412 beyond = SCIPhypergraphEdgesOverlapsBeyond(hypergraph, e);
1413 for( int i = first; i < beyond && valid; ++i )
1414 {
1416 int cardinality;
1417
1418 o = SCIPhypergraphEdgesOverlapsGetAtIndex(hypergraph, i);
1419 cardinality = SCIPhypergraphOverlapSize(hypergraph, o);
1420
1421 /* Check if the cardinalities are nontrivial and form a non-decreasing sequences for each edge. */
1422 if (cardinality < 1 || cardinality < lastcardinality)
1423 {
1424 valid = FALSE;
1425 if( file )
1426 {
1427 fprintf(file, "SCIPhypergraphIsValid detected inconsistency: edge e%d = {", e);
1428 for( int k = 0; k < esize; ++k )
1429 fprintf(file, "%sv%d", k ? "," : "", SCIPhypergraphEdgeVertices(hypergraph, e)[k]);
1430 fprintf(file, "} has incidence #%d of [%d,%d) to overlap o%d = {", i, first, beyond, o);
1431 for( int k = 0; k < SCIPhypergraphOverlapSize(hypergraph, o); ++k )
1432 fprintf(file, "%sv%d", k ? "," : "", SCIPhypergraphOverlapVertices(hypergraph, o)[k]);
1433 fprintf(file, "} of cardinality |o%d| = %d, but previous cardinality is %d.\n", o, cardinality,
1434 lastcardinality);
1435 fflush(file);
1436 }
1437 }
1438 lastcardinality = cardinality;
1439
1440 for( int j = 0; j < SCIPhypergraphOverlapSize(hypergraph, o) && valid; ++j )
1441 {
1442 if( !marked[SCIPhypergraphOverlapVertices(hypergraph, o)[j]])
1443 {
1444 valid = FALSE;
1445 if( file )
1446 {
1447 fprintf(file, "SCIPhypergraphIsValid detected inconsistency: edge e%d = {", e);
1448 for( int k = 0; k < esize; ++k )
1449 fprintf(file, "%sv%d", k ? "," : "", SCIPhypergraphEdgeVertices(hypergraph, e)[k]);
1450 fprintf(file, "} has incidence #%d of [%d,%d) to overlap o%d = {", i, first, beyond, o);
1451 for( int k = 0; k < SCIPhypergraphOverlapSize(hypergraph, o); ++k )
1452 fprintf(file, "%sv%d", k ? "," : "", SCIPhypergraphOverlapVertices(hypergraph, o)[k]);
1453 fprintf(file, "} which is not a subset!\n");
1454 fflush(file);
1455 }
1456 }
1457 }
1458 }
1459 for( int i = 0; i < esize; ++i )
1460 marked[evertices[i]] = FALSE;
1461 }
1462 BMSfreeBlockMemoryArray(hypergraph->blkmem, &marked, n);
1463 }
1464
1465 return valid;
1466}
1467
1468/** @brief initializes a hypergraph iterator's internal memory */
1470 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph of this iterator. */
1471 SCIP_HYPERGRAPH_ITER* iterator /**< Iterator to be initialized. */
1472 )
1473{
1474 assert(hypergraph);
1475 assert(iterator);
1476
1477 iterator->base = -1;
1478 iterator->vertexidx = -1;
1479 iterator->minvertex = -1;
1480 iterator->edgeidx = -1;
1481 iterator->adjacent = -1;
1482 iterator->sizecommonvertices = 32;
1483 iterator->commonvertices = NULL;
1484 iterator->minoverlapsize = 2;
1485 iterator->onlylater = FALSE;
1486 iterator->findoverlaps = FALSE;
1487
1488 SCIP_ALLOC( BMSallocBlockMemoryArray(hypergraph->blkmem, &iterator->commonvertices, 32) );
1489
1490 return SCIP_OKAY;
1491}
1492
1493/** @brief frees a hypergraph iterator's internal memory */
1495 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph of this iterator. */
1496 SCIP_HYPERGRAPH_ITER* iterator /**< Iterator to be cleared. */
1497 )
1498{
1499 assert(hypergraph);
1500 assert(iterator);
1501
1502 BMSfreeBlockMemoryArray(hypergraph->blkmem, &iterator->commonvertices, iterator->sizecommonvertices);
1503}
1504
1505/** @brief initializes the iterator to the first adjacent edge of \p base */
1507 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph of this iterator. */
1508 SCIP_HYPERGRAPH_ITER* iterator, /**< Iterator to be initialized. */
1509 SCIP_HYPERGRAPH_EDGE base, /**< Base edge. */
1510 unsigned int minoverlapsize, /**< Minimum size of the overlap. */
1511 SCIP_Bool onlylater, /**< Whether to only consider edges greater than \p base. */
1512 SCIP_Bool findoverlaps /**< Whether to compute the overlap sets. */
1513 )
1514{
1515 assert(hypergraph);
1516 assert(iterator);
1517 assert(base >= 0);
1518 assert(base < hypergraph->nedges);
1519 assert(hypergraph->hasvertexedges);
1520 assert(hypergraph->hasoverlaps || !findoverlaps);
1521
1522 iterator->base = base;
1523 iterator->vertexidx = -1;
1524 iterator->edgeidx = -1;
1525 iterator->minvertex = -1;
1526 iterator->adjacent = -1;
1527 iterator->ncommonvertices = 0;
1528 iterator->overlap = -1;
1529 iterator->minoverlapsize = minoverlapsize;
1530 iterator->onlylater = onlylater;
1531 iterator->findoverlaps = findoverlaps;
1532
1533 SCIPhypergraphIterNext(hypergraph, iterator);
1534}
1535
1536/** @brief returns whether the iterator is valid */
1538 SCIP_HYPERGRAPH_ITER* iterator /**< Iterator. */
1539 )
1540{
1541 assert(iterator);
1542
1543 return iterator->vertexidx != -2;
1544}
1545
1546/** @brief initializes the iterator to the first adjacent edge of \p base */
1548 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph of this iterator. */
1549 SCIP_HYPERGRAPH_ITER* iterator /**< Iterator. */
1550 )
1551{
1552 assert(hypergraph);
1553 assert(iterator);
1554 assert(iterator->base >= 0);
1555 assert(iterator->base < hypergraph->nedges);
1556 assert(iterator->vertexidx == -1 || iterator->vertexidx >= hypergraph->edgesverticesbeg[iterator->base]);
1557 assert(iterator->vertexidx < hypergraph->edgesverticesbeg[iterator->base + 1]);
1558
1559 if( iterator->vertexidx < 0 )
1560 {
1561 /* Freshly initialized iterator. */
1562 iterator->vertexidx = hypergraph->edgesverticesbeg[iterator->base];
1563 if( iterator->vertexidx == hypergraph->edgesverticesbeg[iterator->base + 1] )
1564 {
1565 /* No vertices in this edge. */
1566 iterator->vertexidx = -2;
1567 return;
1568 }
1569
1570 /* Edge index is set to one before the first edge and incremented in next loop. */
1571 iterator->minvertex = hypergraph->edgesvertices[iterator->vertexidx];
1572 iterator->edgeidx = hypergraph->verticesedgesbeg[iterator->minvertex] - 1;
1573 }
1574
1575 while( iterator->vertexidx >= 0 )
1576 {
1577 int i, iend;
1578 int j, jend;
1579
1580 assert(iterator->minvertex >= 0);
1581 assert(iterator->minvertex < hypergraph->nvertices);
1582 assert(iterator->edgeidx >= hypergraph->verticesedgesbeg[iterator->minvertex] - 1);
1583 assert(iterator->edgeidx < hypergraph->verticesedgesbeg[iterator->minvertex + 1]);
1584
1585 /* Go to next edge of vertex. */
1586
1587 iterator->edgeidx++;
1588 if( iterator->edgeidx < hypergraph->verticesedgesbeg[iterator->minvertex + 1] )
1589 {
1590 /* There is a next edge. */
1591 iterator->adjacent = hypergraph->verticesedges[iterator->edgeidx];
1592 }
1593 else
1594 {
1595 /* There is no next edge, so we consider the next vertex. */
1596 iterator->vertexidx++;
1597 if( iterator->vertexidx == hypergraph->edgesverticesbeg[iterator->base + 1] )
1598 {
1599 /* There is no next vertex either. */
1600 iterator->vertexidx = -2;
1601 return;
1602 }
1603
1604 /* Edge index is set to one before the first edge of the next vertex and incremented in the next iteration. */
1605 iterator->minvertex = hypergraph->edgesvertices[iterator->vertexidx];
1606 iterator->edgeidx = hypergraph->verticesedgesbeg[iterator->minvertex] - 1;
1607 continue;
1608 }
1609
1610 /* Skip if we consider the base edge. */
1611 if( iterator->adjacent == iterator->base )
1612 continue;
1613
1614 /* Check for adjacent < base and discard if not desired. */
1615 if( iterator->onlylater && (iterator->adjacent < iterator->base) )
1616 continue;
1617
1618 /* We traverse the common vertices. */
1619 iterator->ncommonvertices = 0;
1620 i = hypergraph->edgesverticesbeg[iterator->base];
1621 iend = hypergraph->edgesverticesbeg[iterator->base + 1];
1622 j = hypergraph->edgesverticesbeg[iterator->adjacent];
1623 jend = hypergraph->edgesverticesbeg[iterator->adjacent + 1];
1624 while( i < iend && j < jend )
1625 {
1626 SCIP_HYPERGRAPH_VERTEX ivertex, jvertex;
1627
1628 ivertex = hypergraph->edgesvertices[i];
1629 jvertex = hypergraph->edgesvertices[j];
1630
1631 if( ivertex < jvertex )
1632 ++i;
1633 else if( ivertex > jvertex )
1634 ++j;
1635 else
1636 {
1637 if( iterator->ncommonvertices == 0 )
1638 {
1639 /* First common vertex must be the iterator vertex. Otherwise we abort. */
1640 if( ivertex != iterator->minvertex )
1641 {
1642 iterator->ncommonvertices = -1;
1643 break;
1644 }
1645 }
1646 if( iterator->ncommonvertices == iterator->sizecommonvertices )
1647 {
1648 int newsize = 2 * iterator->sizecommonvertices;
1650 iterator->sizecommonvertices, newsize) );
1651 iterator->sizecommonvertices = newsize;
1652 }
1653 iterator->commonvertices[iterator->ncommonvertices] = ivertex;
1654 iterator->ncommonvertices++;
1655 ++i;
1656 ++j;
1657 }
1658 }
1659 assert(iterator->ncommonvertices != 0);
1660
1661 if( iterator->ncommonvertices < iterator->minoverlapsize )
1662 {
1663 /* Abort since either ncommonvertices = -1 (minvertex not minimum vertex in intersection)
1664 * or if it was smaller than requested. */
1665 continue;
1666 }
1667
1668 if( iterator->findoverlaps )
1669 {
1670 /* If requested, find corresponding overlap set. */
1671 if( iterator->ncommonvertices >= 2 )
1672 {
1673 SCIP_CALL_ABORT( findOverlap(hypergraph, iterator->ncommonvertices, iterator->commonvertices,
1674 &iterator->overlap, FALSE, NULL) );
1675 }
1676 else
1677 iterator->overlap = -1;
1678 }
1679
1680 break;
1681 }
1682}
1683
1684/** @brief returns the base edge */
1686 SCIP_HYPERGRAPH_ITER* iterator /**< Iterator. */
1687 )
1688{
1689 return iterator->base;
1690}
1691
1692/** @brief returns the current adjacent edge */
1694 SCIP_HYPERGRAPH_ITER* iterator /**< Iterator. */
1695 )
1696{
1697 return iterator->adjacent;
1698}
1699
1700/** @brief returns the minimum vertex in the intersection of the base and the current adjacent edge */
1702 SCIP_HYPERGRAPH_ITER* iterator /**< Iterator. */
1703 )
1704{
1705 return iterator->minvertex;
1706}
1707
1708/**
1709 * @brief returns the overlap for the intersection of the base and the current adjacent edge
1710 *
1711 * If the intersection of the two edges has only one element, then -1 is returned, and if overlap information was not
1712 * requested in \ref SCIPhypergraphIterStart, then -2 is returned.
1713 */
1715 SCIP_HYPERGRAPH_ITER* iterator /**< Iterator. */
1716 )
1717{
1718 return iterator->overlap;
1719}
1720
1721
1722/*
1723 * simple functions implemented as defines
1724 */
1725
1726#ifndef NDEBUG
1727
1728/*
1729 * In debug mode, the following methods are implemented as function calls to ensure type validity.
1730 * In optimized mode, the methods are implemented as defines to improve performance.
1731 * However, we want to have them in the library anyways, so we have to undef the defines.
1732 */
1733
1734#undef SCIPhypergraphNumVertices
1735#undef SCIPhypergraphNumEdges
1736#undef SCIPhypergraphBlkmem
1737#undef SCIPhypergraphNumOverlaps
1738#undef SCIPhypergraphVertexData
1739#undef SCIPhypergraphEdgeData
1740#undef SCIPhypergraphOverlapData
1741#undef SCIPhypergraphEdgeSize
1742#undef SCIPhypergraphEdgeVertices
1743#undef SCIPhypergraphHasVertexEdges
1744#undef SCIPhypergraphVerticesEdgesFirst
1745#undef SCIPhypergraphVerticesEdgesBeyond
1746#undef SCIPhypergraphVerticesEdgesGet
1747#undef SCIPhypergraphHasOverlaps
1748#undef SCIPhypergraphOverlapSize
1749#undef SCIPhypergraphOverlapVertices
1750#undef SCIPhypergraphEdgesOverlapsFirst
1751#undef SCIPhypergraphEdgesOverlapsBeyond
1752#undef SCIPhypergraphEdgesOverlapsGet
1753#undef SCIPhypergraphHasOverlapsEdges
1754#undef SCIPhypergraphOverlapsEdgesFirst
1755#undef SCIPhypergraphOverlapsEdgesBeyond
1756#undef SCIPhypergraphOverlapsEdgesGet
1757#undef SCIPhypergraphHasVerticesOverlaps
1758#undef SCIPhypergraphVerticesOverlapsFirst
1759#undef SCIPhypergraphVerticesOverlapsBeyond
1760#undef SCIPhypergraphVerticesOverlapsGet
1761
1762
1763/** @brief returns the number of vertices */
1765 SCIP_HYPERGRAPH* hypergraph /**< The hypergraph. */
1766 )
1767{
1768 assert(hypergraph);
1769
1770 return hypergraph->nvertices;
1771}
1772
1773/** @brief returns the number of edges */
1775 SCIP_HYPERGRAPH* hypergraph /**< The hypergraph. */
1776 )
1777{
1778 assert(hypergraph);
1779
1780 return hypergraph->nedges;
1781}
1782
1783/** @brief returns the hypergraph's block memory structure */
1785 SCIP_HYPERGRAPH* hypergraph /**< The hypergraph. */
1786 )
1787{
1788 assert(hypergraph != NULL);
1789
1790 return hypergraph->blkmem;
1791}
1792
1793/** @brief returns the number of overlaps */
1795 SCIP_HYPERGRAPH* hypergraph /**< The hypergraph. */
1796 )
1797{
1798 assert(hypergraph);
1799
1800 return hypergraph->noverlaps;
1801}
1802
1803/** @brief returns the number of edge-vertex incidences */
1805 SCIP_HYPERGRAPH* hypergraph /**< The hypergraph. */
1806 )
1807{
1808 assert(hypergraph);
1809
1810 return hypergraph->edgesverticesbeg[hypergraph->nedges];
1811}
1812
1813/** @brief returns additional data of \p vertex */
1815 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
1816 SCIP_HYPERGRAPH_VERTEX vertex /**< A vertex. */
1817 )
1818{
1819 assert(hypergraph != NULL);
1820
1821 return (SCIP_HYPERGRAPH_VERTEXDATA*)(hypergraph->verticesdata
1822 + vertex * hypergraph->sizevertexdata / sizeof(*(hypergraph->verticesdata))); /*lint --e{737}*/
1823}
1824
1825/** @brief returns additional data of \p edge */
1827 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
1828 SCIP_HYPERGRAPH_EDGE edge /**< An edge. */
1829 )
1830{
1831 assert(hypergraph != NULL);
1832
1833 return (SCIP_HYPERGRAPH_EDGEDATA*)(hypergraph->edgesdata
1834 + edge * hypergraph->sizeedgedata / sizeof(*(hypergraph->edgesdata))); /*lint --e{737}*/
1835}
1836
1837/** @brief returns additional data of \p overlap */
1839 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
1840 SCIP_HYPERGRAPH_OVERLAP overlap /**< An overlap. */
1841 )
1842{
1843 assert(hypergraph != NULL);
1844
1845 return (SCIP_HYPERGRAPH_OVERLAPDATA*)(hypergraph->overlapsdata
1846 + overlap * hypergraph->sizeoverlapdata / sizeof(*(hypergraph->overlapsdata))); /*lint --e{737}*/
1847}
1848
1849/** @brief returns the number of vertices of \p edge */
1851 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
1852 SCIP_HYPERGRAPH_EDGE edge /**< An edge. */
1853 )
1854{
1855 assert(hypergraph);
1856 assert(edge >= 0 && edge < hypergraph->nedges);
1857
1858 return hypergraph->edgesverticesbeg[edge + 1] - hypergraph->edgesverticesbeg[edge];
1859}
1860
1861/**
1862 * @brief returns the array of vertices of \p edge
1863 *
1864 * The length of the array is \ref SCIPhypergraphEdgeSize.
1865 */
1866
1868 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
1869 SCIP_HYPERGRAPH_EDGE edge /**< An edge. */
1870 )
1871{
1872 assert(hypergraph);
1873 assert(edge >= 0 && edge < hypergraph->nedges);
1874
1875 return &hypergraph->edgesvertices[hypergraph->edgesverticesbeg[edge]];
1876}
1877
1878/**
1879 * @brief returns whether vertices' incident edges are known.
1880 *
1881 * Use \ref SCIPhypergraphComputeVerticesEdges to compute them.
1882 */
1884 SCIP_HYPERGRAPH* hypergraph /**< The hypergraph. */
1885 )
1886{
1887 assert(hypergraph);
1888
1889 return hypergraph->hasvertexedges;
1890}
1891
1892/** @brief returns an index for the first edge incident to \p vertex */
1894 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
1895 SCIP_HYPERGRAPH_VERTEX vertex /**< A vertex. */
1896 )
1897{
1898 assert(hypergraph);
1899 assert(hypergraph->hasvertexedges);
1900
1901 return hypergraph->verticesedgesbeg[vertex];
1902}
1903
1904/** @brief returns an index beyond the last edge incident to \p vertex */
1906 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
1907 SCIP_HYPERGRAPH_VERTEX vertex /**< A vertex. */
1908 )
1909{
1910 assert(hypergraph);
1911 assert(hypergraph->hasvertexedges);
1912
1913 return hypergraph->verticesedgesbeg[vertex + 1];
1914}
1915
1916/**
1917 * @brief returns the edge corresponding to \p index that is incident to a vertex
1918 *
1919 * See \ref SCIPhypergraphVertexEdgesFirst and \ref SCIPhypergraphVertexEdgesBeyond to obtain such indices for a vertex.
1920 */
1922 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
1923 int idx /**< Index. */
1924 )
1925{
1926 assert(hypergraph);
1927 assert(hypergraph->hasvertexedges);
1928
1929 return hypergraph->verticesedges[idx];
1930}
1931
1932/**
1933 * @brief returns whether edges' overlaps and overlaps' vertices are known.
1934 *
1935 * Use \ref SCIPhypergraphComputeOverlaps to compute them.
1936 */
1938 SCIP_HYPERGRAPH* hypergraph /**< The hypergraph. */
1939 )
1940{
1941 assert(hypergraph);
1942
1943 return hypergraph->hasoverlaps;
1944}
1945
1946/**
1947 * @brief returns the number of vertices of \p overlap
1948 *
1949 * Requires \ref SCIPhypergraphHasOverlaps to be \c TRUE which results from \ref SCIPhypergraphComputeOverlaps.
1950 */
1952 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
1953 SCIP_HYPERGRAPH_OVERLAP overlap /**< Overlap. */
1954 )
1955{
1956 assert(hypergraph);
1957 assert(overlap >= 0 && overlap < hypergraph->noverlaps);
1958 assert(hypergraph->hasoverlaps);
1959
1960 return hypergraph->overlapsverticesbeg[overlap + 1] - hypergraph->overlapsverticesbeg[overlap];
1961}
1962
1963/**
1964 * @brief returns the array of sorted vertices of \p overlap
1965 *
1966 * The length of the array is \ref SCIPhypergraphOverlapSize.
1967 * Requires \ref SCIPhypergraphHasOverlaps to be \c TRUE which results from \ref SCIPhypergraphComputeOverlaps.
1968 */
1970 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
1971 SCIP_HYPERGRAPH_OVERLAP overlap /**< Overlap. */
1972 )
1973{
1974 assert(hypergraph);
1975 assert(overlap >= 0 && overlap < hypergraph->noverlaps);
1976 assert(hypergraph->hasoverlaps);
1977
1978 return &hypergraph->overlapsvertices[hypergraph->overlapsverticesbeg[overlap]];
1979}
1980
1981/** @brief returns an index for the first overlap incident to \p edge */
1983 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
1984 SCIP_HYPERGRAPH_EDGE edge /**< Edge. */
1985 )
1986{
1987 assert(hypergraph);
1988 assert(edge >= 0 && edge < hypergraph->nedges);
1989 assert(hypergraph->hasoverlaps);
1990
1991 return hypergraph->edgesoverlapsbeg[edge];
1992}
1993
1994/** @brief returns an index beyond the last overlap incident to \p edge */
1996 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
1997 SCIP_HYPERGRAPH_EDGE edge /**< Edge. */
1998 )
1999{
2000 assert(hypergraph);
2001 assert(edge >= 0 && edge < hypergraph->nedges);
2002 assert(hypergraph->hasoverlaps);
2003
2004 return hypergraph->edgesoverlapsbeg[edge + 1];
2005}
2006
2007/**
2008 * @brief returns the overlap corresponding to \p idx that is incident to an edge
2009 *
2010 * See \ref SCIPhypergraphEdgesOverlapsFirst and \ref SCIPhypergraphEdgesOverlapsBeyond to obtain such indices for an
2011 * edge.
2012 */
2014 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
2015 int idx /**< Index. */
2016 )
2017{
2018 assert(hypergraph);
2019 assert(hypergraph->hasoverlaps);
2020
2021 return hypergraph->edgesoverlaps[idx];
2022}
2023
2024/**
2025 * @brief returns whether overlaps' incident edges are known.
2026 *
2027 * Use \ref SCIPhypergraphComputeOverlapsEdges to compute them.
2028 */
2030 SCIP_HYPERGRAPH* hypergraph /**< The hypergraph. */
2031 )
2032{
2033 assert(hypergraph);
2034
2035 return hypergraph->hasoverlapsedges;
2036}
2037
2038/** @brief returns an index for the first edge incident to \p overlap */
2040 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
2041 SCIP_HYPERGRAPH_OVERLAP overlap /**< Overlap. */
2042 )
2043{
2044 assert(hypergraph);
2045 assert(hypergraph->hasoverlapsedges);
2046
2047 return hypergraph->overlapsedgesbeg[overlap];
2048}
2049
2050/** @brief returns an index beyond the last edge incident to \p overlap */
2052 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
2053 SCIP_HYPERGRAPH_OVERLAP overlap /**< Overlap. */
2054 )
2055{
2056 assert(hypergraph);
2057 assert(hypergraph->hasoverlapsedges);
2058
2059 return hypergraph->overlapsedgesbeg[overlap + 1];
2060}
2061
2062/**
2063 * @brief returns the edge corresponding to \p idx that is incident to an overlap
2064 *
2065 * See \ref SCIPhypergraphOverlapsEdgesFirst and \ref SCIPhypergraphOverlapsEdgesBeyond to obtain such indices for an
2066 * overlap.
2067 */
2069 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
2070 int idx /**< Index. */
2071 )
2072{
2073 assert(hypergraph);
2074 assert(hypergraph->hasoverlapsedges);
2075
2076 return hypergraph->overlapsedges[idx];
2077}
2078
2079
2080/**
2081 * @brief returns whether vertices' incident overlaps are known
2082 *
2083 * Use \ref SCIPhypergraphComputeOverlaps to compute them.
2084 */
2086 SCIP_HYPERGRAPH* hypergraph /**< The hypergraph. */
2087 )
2088{
2089 assert(hypergraph);
2090
2091 return hypergraph->hasverticesoverlaps;
2092}
2093
2094/** @brief returns an index for the first overlap containing \p vertex */
2096 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
2097 SCIP_HYPERGRAPH_VERTEX vertex /**< A vertex. */
2098 )
2099{
2100 assert(hypergraph);
2101 assert(hypergraph->hasverticesoverlaps);
2102
2103 return hypergraph->verticesoverlapsbeg[vertex];
2104}
2105
2106/** @brief returns an index beyond the last overlap incident to \p vertex */
2108 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
2109 SCIP_HYPERGRAPH_VERTEX vertex /**< A vertex. */
2110 )
2111{
2112 assert(hypergraph);
2113 assert(hypergraph->hasverticesoverlaps);
2114
2115 return hypergraph->verticesoverlapsbeg[vertex + 1];
2116}
2117
2118/**
2119 * @brief returns the overlap corresponding to \p idx that is incident to a vertex
2120 *
2121 * See \ref SCIPhypergraphVertexOverlapsFirst and \ref SCIPhypergraphVertexOverlapsBeyond to obtain such indices for a
2122 * vertex.
2123 */
2125 SCIP_HYPERGRAPH* hypergraph, /**< The hypergraph. */
2126 int idx /**< Index. */
2127 )
2128{
2129 assert(hypergraph);
2130 assert(hypergraph->hasverticesoverlaps);
2131
2132 return hypergraph->verticesoverlaps[idx];
2133}
2134
2135#endif /* NDEBUG */
SCIP_VAR * w
Definition: circlepacking.c:67
#define NULL
Definition: def.h:248
#define SCIP_Longint
Definition: def.h:141
#define SCIP_ALLOC_ABORT(x)
Definition: def.h:345
#define SCIP_Bool
Definition: def.h:91
#define SCIP_ALLOC(x)
Definition: def.h:366
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:220
#define SCIP_CALL_ABORT(x)
Definition: def.h:334
#define SCIP_CALL(x)
Definition: def.h:355
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2348
#define SCIPhashTwo(a, b)
Definition: pub_misc.h:568
#define SCIPhashFour(a, b, c, d)
Definition: pub_misc.h:573
#define SCIPhashThree(a, b, c)
Definition: pub_misc.h:570
SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
Definition: misc.c:2298
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition: misc.c:2596
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2535
void SCIPsortLong(SCIP_Longint *longarray, int len)
void SCIPsortInt(int *intarray, int len)
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
static SCIP_RETCODE ensureNumEdgesVertices(SCIP_HYPERGRAPH *hypergraph, int required)
enlarges arrays for incident vertex/edge pairs to have capacity for at least required
Definition: hypergraph.c:113
SCIP_RETCODE SCIPhypergraphFree(SCIP_HYPERGRAPH **phypergraph)
frees a hypergraph
Definition: hypergraph.c:281
SCIP_HYPERGRAPH_EDGE SCIPhypergraphIterAdjacent(SCIP_HYPERGRAPH_ITER *iterator)
returns the current adjacent edge
Definition: hypergraph.c:1693
SCIP_HYPERGRAPH_EDGE SCIPhypergraphIterBase(SCIP_HYPERGRAPH_ITER *iterator)
returns the base edge
Definition: hypergraph.c:1685
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
static SCIP_DECL_HASHGETKEY(overlapHashGetKey)
get-key function for overlap hashtable
Definition: hypergraph.c:456
SCIP_HYPERGRAPH_OVERLAP SCIPhypergraphIterOverlap(SCIP_HYPERGRAPH_ITER *iterator)
returns the overlap for the intersection of the base and the current adjacent edge
Definition: hypergraph.c:1714
int SCIPhypergraphOverlapsEdgesBeyond(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_OVERLAP overlap)
returns an index beyond the last edge incident to overlap
Definition: hypergraph.c:2051
void SCIPhypergraphIterClear(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_ITER *iterator)
frees a hypergraph iterator's internal memory
Definition: hypergraph.c:1494
SCIP_HYPERGRAPH_EDGE SCIPhypergraphVertexEdgesGetAtIndex(SCIP_HYPERGRAPH *hypergraph, int idx)
returns the edge corresponding to index that is incident to a vertex
Definition: hypergraph.c:1921
int SCIPhypergraphVertexEdgesBeyond(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_VERTEX vertex)
returns an index beyond the last edge incident to vertex
Definition: hypergraph.c:1905
static SCIP_DECL_HASHKEYEQ(overlapHashKeyEqPtr)
equality function for overlap hashtable
Definition: hypergraph.c:463
SCIP_RETCODE SCIPhypergraphIntersectEdges(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_EDGE first, SCIP_HYPERGRAPH_EDGE second, SCIP_HYPERGRAPH_OVERLAP *poverlap, SCIP_HYPERGRAPH_VERTEX *pvertex)
finds the overlap or singleton vertex corresponding to the intersection of edges first and second
Definition: hypergraph.c:929
static SCIP_RETCODE ensureNumVertices(SCIP_HYPERGRAPH *hypergraph, int required)
enlarges vertex arrays to have capacity for at least required vertices
Definition: hypergraph.c:45
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
int SCIPhypergraphVertexOverlapsBeyond(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_VERTEX vertex)
returns an index beyond the last overlap incident to vertex
Definition: hypergraph.c:2107
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
static SCIP_RETCODE ensureNumOverlaps(SCIP_HYPERGRAPH *hypergraph, int required)
enlarges overlap arrays to have capacity for at least required overlaps
Definition: hypergraph.c:139
SCIP_Bool SCIPhypergraphHasOverlapsEdges(SCIP_HYPERGRAPH *hypergraph)
returns whether overlaps' incident edges are known.
Definition: hypergraph.c:2029
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_RETCODE SCIPhypergraphOverlapFind(SCIP_HYPERGRAPH *hypergraph, int nvertices, SCIP_HYPERGRAPH_VERTEX *vertices, SCIP_HYPERGRAPH_OVERLAP *poverlap)
finds the overlap corresponding to vertex set vertices; returns -1 if it is not found
Definition: hypergraph.c:906
static SCIP_RETCODE ensureNumEdges(SCIP_HYPERGRAPH *hypergraph, int required)
enlarges edge arrays to have capacity for at least required edges
Definition: hypergraph.c:73
SCIP_RETCODE SCIPhypergraphClear(SCIP_HYPERGRAPH *hypergraph)
clears a hypergraph, deleting all vertices and edges
Definition: hypergraph.c:361
SCIP_Bool SCIPhypergraphHasOverlaps(SCIP_HYPERGRAPH *hypergraph)
returns whether edges' overlaps and overlaps' vertices are known.
Definition: hypergraph.c:1937
SCIP_Bool SCIPhypergraphHasVertexOverlaps(SCIP_HYPERGRAPH *hypergraph)
returns whether vertices' incident overlaps are known
Definition: hypergraph.c:2085
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
int SCIPhypergraphOverlapsEdgesFirst(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_OVERLAP overlap)
returns an index for the first edge incident to overlap
Definition: hypergraph.c:2039
static SCIP_DECL_HASHKEYVAL(overlapHashKeyValPtr)
hash function for overlap hashtable
Definition: hypergraph.c:498
SCIP_HYPERGRAPH_VERTEX SCIPhypergraphIterMinVertex(SCIP_HYPERGRAPH_ITER *iterator)
returns the minimum vertex in the intersection of the base and the current adjacent edge
Definition: hypergraph.c:1701
SCIP_HYPERGRAPH_VERTEXDATA * SCIPhypergraphVertexData(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_VERTEX vertex)
returns additional data of vertex
Definition: hypergraph.c:1814
SCIP_HYPERGRAPH_OVERLAP SCIPhypergraphVertexOverlapsGetAtIndex(SCIP_HYPERGRAPH *hypergraph, int idx)
returns the overlap corresponding to idx that is incident to a vertex
Definition: hypergraph.c:2124
int SCIPhypergraphVertexOverlapsFirst(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_VERTEX vertex)
returns an index for the first overlap containing vertex
Definition: hypergraph.c:2095
SCIP_RETCODE SCIPhypergraphComputeOverlapsEdges(SCIP_HYPERGRAPH *hypergraph)
computes all overlaps' lists of incident edges
Definition: hypergraph.c:990
SCIP_HYPERGRAPH_OVERLAP SCIPhypergraphOverlapsEdgesGetAtIndex(SCIP_HYPERGRAPH *hypergraph, int idx)
returns the edge corresponding to idx that is incident to an overlap
Definition: hypergraph.c:2068
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
SCIP_RETCODE SCIPhypergraphComputeVerticesOverlaps(SCIP_HYPERGRAPH *hypergraph)
computes all vertices' lists of incident overlaps
Definition: hypergraph.c:1091
int SCIPhypergraphGetNIncidences(SCIP_HYPERGRAPH *hypergraph)
returns the number of edge-vertex incidences
Definition: hypergraph.c:1804
SCIP_Bool SCIPhypergraphHasVertexEdges(SCIP_HYPERGRAPH *hypergraph)
returns whether vertices' incident edges are known.
Definition: hypergraph.c:1883
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
static SCIP_RETCODE findOverlap(SCIP_HYPERGRAPH *hypergraph, int nvertices, int *vertices, int *poverlap, SCIP_Bool add, SCIP_Bool *padded)
finds an overlap specified by a sorted vertex set, potentially adding it
Definition: hypergraph.c:530
int SCIPhypergraphVertexEdgesFirst(SCIP_HYPERGRAPH *hypergraph, SCIP_HYPERGRAPH_VERTEX vertex)
returns an index for the first edge incident to vertex
Definition: hypergraph.c:1893
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
static SCIP_RETCODE ensureNumOverlapsVertices(SCIP_HYPERGRAPH *hypergraph, int required)
enlarges overlapVertices array to have capacity for at least required overlaps' vertices
Definition: hypergraph.c:185
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
BMS_BLKMEM * SCIPhypergraphBlkmem(SCIP_HYPERGRAPH *hypergraph)
returns the hypergraph's block memory structure
Definition: hypergraph.c:1784
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.
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:465
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:451
#define BMSallocBlockMemoryArray(mem, ptr, num)
Definition: memory.h:454
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:467
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:458
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:437
internal miscellaneous methods
public methods for message output
#define SCIPdebugMessage
Definition: pub_message.h:96
unsigned int minoverlapsize
SCIP_HYPERGRAPH_EDGE base
SCIP_HYPERGRAPH_OVERLAP overlap
SCIP_HYPERGRAPH_EDGE adjacent
SCIP_HYPERGRAPH_VERTEX * commonvertices
unsigned int onlylater
unsigned int findoverlaps
SCIP_HYPERGRAPH_VERTEX minvertex
SCIP_Bool hasverticesoverlaps
SCIP_HYPERGRAPH_EDGE * edgesvertices
SCIP_HYPERGRAPH_OVERLAP * verticesoverlaps
SCIP_HYPERGRAPH_VERTEX * verticesedges
SCIP_Bool hasoverlapsedges
SCIP_HYPERGRAPH_OVERLAP * edgesoverlaps
BMS_BLKMEM * blkmem
SCIP_HYPERGRAPH_VERTEX * overlapsvertices
SCIP_Bool hasvertexedges
SCIP_HYPERGRAPH_EDGE * overlapsedges
SCIP_HASHTABLE * overlaphashtable
datastructures hypergraphs
int SCIP_HYPERGRAPH_EDGE
int SCIP_HYPERGRAPH_OVERLAP
struct SCIP_Hypergraph_OverlapData SCIP_HYPERGRAPH_OVERLAPDATA
struct SCIP_Hypergraph_NodeData SCIP_HYPERGRAPH_VERTEXDATA
#define SCIP_DECL_HYPERGRAPH_OVERLAP(x)
int SCIP_HYPERGRAPH_VERTEX
struct SCIP_Hypergraph_EdgeData SCIP_HYPERGRAPH_EDGEDATA
@ SCIP_OKAY
Definition: type_retcode.h:42
@ SCIP_ERROR
Definition: type_retcode.h:43
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63