OpenRadioss 2025.1.11
OpenRadioss project
Loading...
Searching...
No Matches
gbisect.c
Go to the documentation of this file.
1/*****************************************************************************
2/
3/ SPACE (SPArse Cholesky Elimination) Library: gbisect.c
4/
5/ author J"urgen Schulze, University of Paderborn
6/ created 00dec29
7/
8/ This file contains functions dealing with the graph bisection object
9/
10******************************************************************************
11
12Data type: struct gbisect
13 graph_t *G; pointer to graph that will be partitioned
14 int *color; color of node (GRAY, BLACK, or WHITE)
15 int cwght[3]; weights of GRAY, BLACK, WHITE partitions
16Comments:
17 o Structure used to compute the bisection of a graph. Structure does not
18 own graph object => it will not be freed.
19Methods in lib/gbisect.c:
20- Gbisect = newGbisect(graph_t *G);
21 o Initial: cwght[GRAY] = cwght[BLACK] = cwght[WHITE] = 0
22- void freeGbisect(gbisect_t *Gbisect);
23- void printGbisect(gbisect_t *Gbisect);
24- void checkSeparator(gbisect_t *Gbisect);
25- void constructSeparator(gbisect_t *Gbisect, options_t *options,
26 timings_t *cpus);
27 o constructs a vertex separator by applying the new multilevel approach;
28 it first constructs an initial domain decomposition for Gbisect->G
29 by calling constructDomainDecomposition; the dd is then coarsed by
30 several calls to shrinkDomainDecomposition; the last dd is colored
31 by a call to initialDDSep; this coloring is refined during the
32 uncoarsening phase by several calls to improveDDSep
33 o used options:
34 OPTION_MSGLVL, OPTION_NODE_SELECTION3
35 returned timings:
36 TIME_INITDOMDEC, TIME_COARSEDOMDEC, TIME_INITSEP, TIME_REFINESEP
37- int smoothBy2Layers(gbisect_t *Gbisect, int *bipartvertex, int *pnX,
38 int black, int white);
39 o on start, bipartvertex contains the nodes of the separator; the
40 separator is then paired with eiter the black or the white partition
41 so that the nodes in bipartvertex induce a bipartite graph; this
42 graph is constructed by setupBipartiteGraph; a Dulmage-Mendelsohn
43 decomposition is computed and the separator is smoothed; the
44 vertices of the smoothed separator are returned in bipartvertex
45- void smoothSeparator(gbisect_t *Gbisect, options_t *options);
46 o smoothes a given separator by repeatedly calling smoothBy2Layers
47 o used options: OPTION_MSGLVL
48
49******************************************************************************/
50
51#include <space.h>
52/* #define DEBUG */
53/* #define BE_CAUTIOUS */
54
55
56/*****************************************************************************
57******************************************************************************/
60{ gbisect_t *Gbisect;
61
62 mymalloc(Gbisect, 1, gbisect_t);
63 mymalloc(Gbisect->color, G->nvtx, PORD_INT);
64
65 Gbisect->G = G;
66 Gbisect->cwght[GRAY] = 0;
67 Gbisect->cwght[BLACK] = 0;
68 Gbisect->cwght[WHITE] = 0;
69
70 return(Gbisect);
71}
72
73
74/*****************************************************************************
75******************************************************************************/
76void
78{
79 free(Gbisect->color);
80 free(Gbisect);
81}
82
83
84/*****************************************************************************
85******************************************************************************/
86void
88{ graph_t *G;
89 PORD_INT count, u, v, i, istart, istop;
90
91 G = Gbisect->G;
92 printf("\n#nodes %d, #edges %d, totvwght %d\n", G->nvtx, G->nedges >> 1,
93 G->totvwght);
94 printf("partition weights: S %d, B %d, W %d\n", Gbisect->cwght[GRAY],
95 Gbisect->cwght[BLACK], Gbisect->cwght[WHITE]);
96 for (u = 0; u < G->nvtx; u++)
97 { count = 0;
98 printf("--- adjacency list of node %d (weight %d, color %d)\n", u,
99 G->vwght[u], Gbisect->color[u]);
100 istart = G->xadj[u];
101 istop = G->xadj[u+1];
102 for (i = istart; i < istop; i++)
103 { v = G->adjncy[i];
104 printf("%5d (color %2d)", v, Gbisect->color[v]);
105 if ((++count % 4) == 0)
106 printf("\n");
107 }
108 if ((count % 4) != 0)
109 printf("\n");
110 }
111}
112
113
114/*****************************************************************************
115******************************************************************************/
116void
118{ PORD_INT *xadj, *adjncy, *vwght, *color, *cwght;
119 PORD_INT nvtx, err, checkS, checkB, checkW, a, b, u, v, i, istart, istop;
120
121 nvtx = Gbisect->G->nvtx;
122 xadj = Gbisect->G->xadj;
123 adjncy = Gbisect->G->adjncy;
124 vwght = Gbisect->G->vwght;
125 color = Gbisect->color;
126 cwght = Gbisect->cwght;
127
128 err = FALSE;
129 printf("checking separator of induced subgraph (S %d, B %d, W %d)\n",
130 cwght[GRAY], cwght[BLACK], cwght[WHITE]);
131
132 checkS = checkB = checkW = 0;
133 for (u = 0; u < nvtx; u++)
134 { istart = xadj[u];
135 istop = xadj[u+1];
136 switch(color[u])
137 { case GRAY: /* is it a minimal separator? */
138 checkS += vwght[u];
139 a = b = FALSE;
140 for (i = istart; i < istop; i++)
141 { v = adjncy[i];
142 if (color[v] == WHITE) a = TRUE;
143 if (color[v] == BLACK) b = TRUE;
144 }
145 if (!((a) && (b)))
146 printf("WARNING: not a minimal separator (node %d)\n", u);
147 break;
148 case BLACK: /* is it realy a separator? */
149 checkB += vwght[u];
150 for (i = istart; i < istop; i++)
151 { v = adjncy[i];
152 if (color[v] == WHITE)
153 { printf("ERROR: white node %d adjacent to black node %d\n", u,v);
154 err = TRUE;
155 }
156 }
157 break;
158 case WHITE:
159 checkW += vwght[u];
160 break;
161 default:
162 printf("ERROR: node %d has unrecognized color %d\n", u, color[u]);
163 err = TRUE;
164 }
165 }
166
167 /* check cwght[GRAY], cwght[BLACK], cwght[WHITE] */
168 if ((checkS != cwght[GRAY]) || (checkB != cwght[BLACK])
169 || (checkW != cwght[WHITE]))
170 { printf("ERROR in partitioning: checkS %d (S %d), checkB %d (B %d), "
171 "checkW %d (W %d)\n", checkS, cwght[GRAY], checkB, cwght[BLACK],
172 checkW, cwght[WHITE]);
173 err = TRUE;
174 }
175 if (err) quit();
176}
177
178
179/*****************************************************************************
180******************************************************************************/
181void
183{ domdec_t *dd, *dd2;
184 PORD_INT *color, *cwght, *map, nvtx, u, i;
185
186 nvtx = Gbisect->G->nvtx;
187 color = Gbisect->color;
188 cwght = Gbisect->cwght;
189
190 /* --------------------------------------------------------------
191 map vector identifies vertices of Gbisect->G in domain decomp.
192 -------------------------------------------------------------- */
193 mymalloc(map, nvtx, PORD_INT);
194
195 /* --------------------------------------
196 construct initial domain decomposition
197 -------------------------------------- */
199 dd = constructDomainDecomposition(Gbisect->G, map);
200
201#ifdef BE_CAUTIOUS
203#endif
204
205 if (options[OPTION_MSGLVL] > 2)
206 printf("\t 0. dom.dec.: #nodes %d (#domains %d, weight %d), #edges %d\n",
207 dd->G->nvtx, dd->ndom, dd->domwght, dd->G->nedges >> 1);
209
210 /* ---------------------------------------------------
211 construct sequence of coarser domain decompositions
212 --------------------------------------------------- */
214 i = 0;
215 while ((dd->ndom > MIN_DOMAINS) && (i < MAX_COARSENING_STEPS)
216 && ((dd->G->nedges >> 1) > dd->G->nvtx))
218 dd = dd->next; i++;
219
220#ifdef BE_CAUTIOUS
222#endif
223
224 if (options[OPTION_MSGLVL] > 2)
225 printf("\t %2d. dom.dec.: #nodes %d (#domains %d, weight %d), #edges %d"
226 "\n", i, dd->G->nvtx, dd->ndom, dd->domwght, dd->G->nedges >> 1);
227 }
229
230 /* -----------------------------------------------
231 determine coloring of last domain decomposition
232 ------------------------------------------------ */
234 initialDDSep(dd);
235 if (dd->cwght[GRAY] > 0)
236 improveDDSep(dd);
237
238#ifdef BE_CAUTIOUS
239 checkDDSep(dd);
240#endif
241
242 if (options[OPTION_MSGLVL] > 2)
243 printf("\t %2d. dom.dec. sep.: S %d, B %d, W %d [cost %7.2f]\n",
244 i, dd->cwght[GRAY], dd->cwght[BLACK], dd->cwght[WHITE],
245 F(dd->cwght[GRAY], dd->cwght[BLACK], dd->cwght[WHITE]));
247
248 /* --------------
249 refine coloring
250 --------------- */
251
253 while (dd->prev != NULL)
254 { dd2 = dd->prev;
255 dd2->cwght[GRAY] = dd->cwght[GRAY];
256 dd2->cwght[BLACK] = dd->cwght[BLACK];
257 dd2->cwght[WHITE] = dd->cwght[WHITE];
258 for (u = 0; u < dd2->G->nvtx; u++)
259 dd2->color[u] = dd->color[dd2->map[u]];
261 if (dd2->cwght[GRAY] > 0)
262 improveDDSep(dd2);
263
264#ifdef BE_CAUTIOUS
265 checkDDSep(dd2);
266#endif
267
268 dd = dd2;
269 i--;
270 if (options[OPTION_MSGLVL] > 2)
271 printf("\t %2d. dom.dec. sep.: S %d, B %d, W %d [cost %7.2f]\n",
272 i, dd->cwght[GRAY], dd->cwght[BLACK], dd->cwght[WHITE],
273 F(dd->cwght[GRAY], dd->cwght[BLACK], dd->cwght[WHITE]));
274 }
276
277 /* ---------------------------------
278 copy coloring to subgraph Gbisect
279 --------------------------------- */
280 cwght[GRAY] = dd->cwght[GRAY];
281 cwght[BLACK] = dd->cwght[BLACK];
282 cwght[WHITE] = dd->cwght[WHITE];
283 for (u = 0; u < nvtx; u++)
284 color[u] = dd->color[map[u]];
286 free(map);
287}
288
289
290/*****************************************************************************
291******************************************************************************/
293smoothBy2Layers(gbisect_t *Gbisect, PORD_INT *bipartvertex, PORD_INT *pnX,
294 PORD_INT black, PORD_INT white)
295{ gbipart_t *Gbipart;
296 PORD_INT *xadj, *adjncy, *color, *cwght, *map;
297 PORD_INT *flow, *rc, *matching, *dmflag, dmwght[6];
298 PORD_INT nvtx, smoothed, nX, nX2, nY, x, y, u, i, j, jstart, jstop;
299
300 nvtx = Gbisect->G->nvtx;
301 xadj = Gbisect->G->xadj;
302 adjncy = Gbisect->G->adjncy;
303 color = Gbisect->color;
304 cwght = Gbisect->cwght;
305 nX = *pnX;
306
307 /* ----------------------------------------------------
308 map vector identifies vertices of Gbisect in Gbipart
309 ---------------------------------------------------- */
310 mymalloc(map, nvtx, PORD_INT);
311
312 /* ----------------------------------
313 construct set Y of bipartite graph
314 ---------------------------------- */
315 nY = 0;
316 for (i = 0; i < nX; i++)
317 { x = bipartvertex[i];
318 jstart = xadj[x];
319 jstop = xadj[x+1];
320 for (j = jstart; j < jstop; j++)
321 { y = adjncy[j];
322 if (color[y] == black)
323 { bipartvertex[nX+nY++] = y;
324 color[y] = GRAY;
325 }
326 }
327 }
328 for (i = nX; i < nX+nY; i++)
329 { y = bipartvertex[i];
330 color[y] = black;
331 }
332
333 /* --------------------------------------------
334 compute the Dulmage-Mendelsohn decomposition
335 -------------------------------------------- */
336 Gbipart = setupBipartiteGraph(Gbisect->G, bipartvertex, nX, nY, map);
337
338 mymalloc(dmflag, (nX+nY), PORD_INT);
339 switch(Gbipart->G->type)
340 { case UNWEIGHTED:
341 mymalloc(matching, (nX+nY), PORD_INT);
342 maximumMatching(Gbipart, matching);
343 DMviaMatching(Gbipart, matching, dmflag, dmwght);
344 free(matching);
345 break;
346 case WEIGHTED:
347 mymalloc(flow, Gbipart->G->nedges, PORD_INT);
348 mymalloc(rc, (nX+nY), PORD_INT);
349 maximumFlow(Gbipart, flow, rc);
350 DMviaFlow(Gbipart, flow, rc, dmflag, dmwght);
351 free(flow);
352 free(rc);
353 break;
354 default:
355 fprintf(stderr, "\nError in function smoothSeparator\n"
356 " unrecognized bipartite graph type %d\n", Gbipart->G->type);
357 quit();
358 }
359
360#ifdef DEBUG
361 printf("Dulmage-Mendelsohn decomp. computed\n"
362 "SI %d, SX %d, SR %d, BI %d, BX %d, BR %d\n", dmwght[SI], dmwght[SX],
363 dmwght[SR], dmwght[BI], dmwght[BX], dmwght[BR]);
364#endif
365
366 /* -----------------------------------------------------------------------
367 1st TEST: try to exchange SI with BX, i.e. nodes in SI are moved from
368 the separator into white (white grows), and nodes in BX are moved from
369 black into the separator (black shrinks)
370 ----------------------------------------------------------------------- */
371 smoothed = FALSE;
372 if (F(cwght[GRAY]-dmwght[SI]+dmwght[BX], cwght[black]-dmwght[BX],
373 cwght[white]+dmwght[SI]) + EPS < F(cwght[GRAY], cwght[black],
374 cwght[white]))
375 { smoothed = TRUE;
376
377#ifdef DEBUG
378 printf("exchange SI with BX\n");
379#endif
380
381 cwght[white] += dmwght[SI]; cwght[GRAY] -= dmwght[SI];
382 cwght[black] -= dmwght[BX]; cwght[GRAY] += dmwght[BX];
383 for (i = 0; i < nX+nY; i++)
384 { u = bipartvertex[i];
385 if (dmflag[map[u]] == SI)
386 color[u] = white;
387 if (dmflag[map[u]] == BX)
388 color[u] = GRAY;
389 }
390 }
391
392 /* -----------------------------------------------------------------------
393 2nd TEST: try to exchange SR with BR, i.e. nodes in SR are moved from
394 the separator into white (white grows), and nodes in BR are moved from
395 black into the separator (black shrinks)
396 NOTE: SR is allowed to be exchanged with BR only if SI = BX = 0 or if
397 SI has been exchanged with BX (Adj(SR) is a subset of BX u BR)
398 ----------------------------------------------------------------------- */
399 if ((F(cwght[GRAY]-dmwght[SR]+dmwght[BR], cwght[black]-dmwght[BR],
400 cwght[white]+dmwght[SR]) + EPS < F(cwght[GRAY], cwght[black],
401 cwght[white]))
402 && ((smoothed) || (dmwght[SI] == 0)))
403 { smoothed = TRUE;
404
405#ifdef DEBUG
406 printf("exchange SR with BR\n");
407#endif
408
409 cwght[white] += dmwght[SR]; cwght[GRAY] -= dmwght[SR];
410 cwght[black] -= dmwght[BR]; cwght[GRAY] += dmwght[BR];
411 for (i = 0; i < nX+nY; i++)
412 { u = bipartvertex[i];
413 if (dmflag[map[u]] == SR)
414 color[u] = white;
415 if (dmflag[map[u]] == BR)
416 color[u] = GRAY;
417 }
418 }
419
420 /* -----------------------------------------------------
421 fill bipartvertex with the nodes of the new separator
422 ----------------------------------------------------- */
423 nX2 = 0;
424 for (i = 0; i < nX+nY; i++)
425 { u = bipartvertex[i];
426 if (color[u] == GRAY)
427 bipartvertex[nX2++] = u;
428 }
429 *pnX = nX2;
430
431 /* -------------------------------
432 free working storage and return
433 ------------------------------- */
434 free(map); free(dmflag);
435 freeBipartiteGraph(Gbipart);
436 return(smoothed);
437}
438
439
440/*****************************************************************************
441******************************************************************************/
442void
444{ PORD_INT *xadj, *adjncy, *vwght, *color, *cwght, *bipartvertex;
445 PORD_INT nvtx, nX, nX2, u, x, y, a, b, i, j, jstart, jstop;
446
447 nvtx = Gbisect->G->nvtx;
448 xadj = Gbisect->G->xadj;
449 adjncy = Gbisect->G->adjncy;
450 vwght = Gbisect->G->vwght;
451 color = Gbisect->color;
452 cwght = Gbisect->cwght;
453
454 mymalloc(bipartvertex, nvtx, PORD_INT);
455
456 /* ----------------------------------------------------------
457 extract the separator (store its vertices in bipartvertex)
458 ---------------------------------------------------------- */
459 nX = 0;
460 for (u = 0; u < nvtx; u++)
461 if (color[u] == GRAY)
462 bipartvertex[nX++] = u;
463
464 do
465 { /* ---------------------------------------------------------------
466 minimize the separator (i.e. minimize set X of bipartite graph)
467 --------------------------------------------------------------- */
468 cwght[GRAY] = nX2 = 0;
469 for (i = 0; i < nX; i++)
470 { x = bipartvertex[i];
471 a = b = FALSE;
472 jstart = xadj[x];
473 jstop = xadj[x+1];
474 for (j = jstart; j < jstop; j++)
475 { y = adjncy[j];
476 if (color[y] == WHITE) a = TRUE;
477 if (color[y] == BLACK) b = TRUE;
478 }
479 if ((a) && (!b))
480 { color[x] = WHITE; cwght[WHITE] += vwght[x]; }
481 else if ((!a) && (b))
482 { color[x] = BLACK; cwght[BLACK] += vwght[x]; }
483 else
484 { bipartvertex[nX2++] = x; cwght[GRAY] += vwght[x]; }
485 }
486 nX = nX2;
487
488#ifdef BE_CAUTIOUS
489 checkSeparator(Gbisect);
490#endif
491
492 /* ------------------------------------------------------------------
493 smooth the unweighted/weighted separator
494 first pair it with the larger set; if unsuccessful try the smaller
495 ------------------------------------------------------------------ */
496 if (cwght[BLACK] >= cwght[WHITE])
497 { a = smoothBy2Layers(Gbisect, bipartvertex, &nX, BLACK, WHITE);
498 if (!a)
499 a = smoothBy2Layers(Gbisect, bipartvertex, &nX, WHITE, BLACK);
500 }
501 else
502 { a = smoothBy2Layers(Gbisect, bipartvertex, &nX, WHITE, BLACK);
503 if (!a)
504 a = smoothBy2Layers(Gbisect, bipartvertex, &nX, BLACK, WHITE);
505 }
506 if ((options[OPTION_MSGLVL] > 2) && (a))
507 printf("\t separator smoothed: S %d, B %d, W %d [cost %7.2f]\n",
508 cwght[GRAY], cwght[BLACK], cwght[WHITE],
509 F(cwght[GRAY], cwght[BLACK], cwght[WHITE]));
510 } while (a);
511
512 free(bipartvertex);
513}
514
bool rc
#define TRUE
Definition cblas_test.h:10
#define FALSE
Definition cblas_test.h:14
#define BX
Definition const.h:72
#define TIME_INITDOMDEC
Definition const.h:92
#define SX
Definition const.h:69
#define OPTION_MSGLVL
Definition const.h:83
#define TIME_REFINESEP
Definition const.h:95
#define EPS
Definition const.h:58
#define BLACK
Definition const.h:63
#define WHITE
Definition const.h:64
#define TIME_COARSEDOMDEC
Definition const.h:93
#define SI
Definition const.h:68
#define BI
Definition const.h:71
#define TIME_INITSEP
Definition const.h:94
#define SR
Definition const.h:70
#define OPTION_NODE_SELECTION3
Definition const.h:81
#define WEIGHTED
Definition const.h:20
#define UNWEIGHTED
Definition const.h:19
#define GRAY
Definition const.h:62
#define BR
Definition const.h:73
#define F
Definition eval.h:12
gbisect_t * newGbisect(graph_t *G)
Definition gbisect.c:59
void constructSeparator(gbisect_t *Gbisect, options_t *options, timings_t *cpus)
Definition gbisect.c:182
void smoothSeparator(gbisect_t *Gbisect, options_t *options)
Definition gbisect.c:443
void checkSeparator(gbisect_t *Gbisect)
Definition gbisect.c:117
PORD_INT smoothBy2Layers(gbisect_t *Gbisect, PORD_INT *bipartvertex, PORD_INT *pnX, PORD_INT black, PORD_INT white)
Definition gbisect.c:293
void freeGbisect(gbisect_t *Gbisect)
Definition gbisect.c:77
void printGbisect(gbisect_t *Gbisect)
Definition gbisect.c:87
#define pord_starttimer(var)
Definition macros.h:58
#define pord_stoptimer(var)
Definition macros.h:61
#define quit()
Definition macros.h:64
#define mymalloc(ptr, nr, type)
Definition macros.h:23
#define MIN_DOMAINS
Definition params.h:18
#define MAX_COARSENING_STEPS
Definition params.h:19
void DMviaMatching(gbipart_t *, PORD_INT *, PORD_INT *, PORD_INT *)
Definition gbipart.c:435
void freeDomainDecomposition(domdec_t *)
Definition ddcreate.c:120
void DMviaFlow(gbipart_t *, PORD_INT *, PORD_INT *, PORD_INT *, PORD_INT *)
Definition gbipart.c:528
void freeBipartiteGraph(gbipart_t *)
Definition gbipart.c:81
void improveDDSep(domdec_t *)
Definition ddbisect.c:607
void checkDomainDecomposition(domdec_t *)
Definition ddcreate.c:163
gbipart_t * setupBipartiteGraph(graph_t *, PORD_INT *, PORD_INT, PORD_INT, PORD_INT *)
Definition gbipart.c:118
void checkDDSep(domdec_t *)
Definition ddbisect.c:68
void shrinkDomainDecomposition(domdec_t *, PORD_INT)
Definition ddcreate.c:898
void initialDDSep(domdec_t *)
Definition ddbisect.c:348
domdec_t * constructDomainDecomposition(graph_t *, PORD_INT *)
Definition ddcreate.c:472
void maximumFlow(gbipart_t *, PORD_INT *, PORD_INT *)
Definition gbipart.c:322
void maximumMatching(gbipart_t *, PORD_INT *)
Definition gbipart.c:195
struct _domdec * prev
Definition types.h:60
struct _domdec * next
Definition types.h:60
PORD_INT ndom
Definition types.h:54
PORD_INT cwght[3]
Definition types.h:58
PORD_INT domwght
Definition types.h:55
PORD_INT * color
Definition types.h:57
graph_t * G
Definition types.h:53
PORD_INT * map
Definition types.h:59
graph_t * G
Definition types.h:67
PORD_INT * color
Definition types.h:45
graph_t * G
Definition types.h:44
PORD_INT cwght[3]
Definition types.h:46
PORD_INT totvwght
Definition types.h:34
PORD_INT * xadj
Definition types.h:35
PORD_INT type
Definition types.h:33
PORD_INT nedges
Definition types.h:32
PORD_INT nvtx
Definition types.h:31
PORD_INT * vwght
Definition types.h:37
PORD_INT * adjncy
Definition types.h:36
FLOAT timings_t
Definition types.h:25
#define PORD_INT
Definition types.h:20
struct _graph graph_t
PORD_INT options_t
Definition types.h:24
struct _gbisect gbisect_t
struct _gbipart gbipart_t
struct _domdec domdec_t