Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/elmergrid/src/metis-5.1.0/libmetis/initpart.c
3206 views
1
/*
2
* Copyright 1997, Regents of the University of Minnesota
3
*
4
* initpart.c
5
*
6
* This file contains code that performs the initial partition of the
7
* coarsest graph
8
*
9
* Started 7/23/97
10
* George
11
*
12
*/
13
14
#include "metislib.h"
15
16
/*************************************************************************/
17
/*! This function computes the initial bisection of the coarsest graph */
18
/*************************************************************************/
19
void Init2WayPartition(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts,
20
idx_t niparts)
21
{
22
mdbglvl_et dbglvl;
23
24
ASSERT(graph->tvwgt[0] >= 0);
25
26
dbglvl = ctrl->dbglvl;
27
IFSET(ctrl->dbglvl, METIS_DBG_REFINE, ctrl->dbglvl -= METIS_DBG_REFINE);
28
IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, ctrl->dbglvl -= METIS_DBG_MOVEINFO);
29
30
IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->InitPartTmr));
31
32
switch (ctrl->iptype) {
33
case METIS_IPTYPE_RANDOM:
34
if (graph->ncon == 1)
35
RandomBisection(ctrl, graph, ntpwgts, niparts);
36
else
37
McRandomBisection(ctrl, graph, ntpwgts, niparts);
38
break;
39
40
case METIS_IPTYPE_GROW:
41
if (graph->nedges == 0)
42
if (graph->ncon == 1)
43
RandomBisection(ctrl, graph, ntpwgts, niparts);
44
else
45
McRandomBisection(ctrl, graph, ntpwgts, niparts);
46
else
47
if (graph->ncon == 1)
48
GrowBisection(ctrl, graph, ntpwgts, niparts);
49
else
50
McGrowBisection(ctrl, graph, ntpwgts, niparts);
51
break;
52
53
default:
54
gk_errexit(SIGERR, "Unknown initial partition type: %d\n", ctrl->iptype);
55
}
56
57
IFSET(ctrl->dbglvl, METIS_DBG_IPART, printf("Initial Cut: %"PRIDX"\n", graph->mincut));
58
IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->InitPartTmr));
59
ctrl->dbglvl = dbglvl;
60
61
}
62
63
64
/*************************************************************************/
65
/*! This function computes the initial separator of the coarsest graph */
66
/*************************************************************************/
67
void InitSeparator(ctrl_t *ctrl, graph_t *graph, idx_t niparts)
68
{
69
real_t ntpwgts[2] = {0.5, 0.5};
70
mdbglvl_et dbglvl;
71
72
dbglvl = ctrl->dbglvl;
73
IFSET(ctrl->dbglvl, METIS_DBG_REFINE, ctrl->dbglvl -= METIS_DBG_REFINE);
74
IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, ctrl->dbglvl -= METIS_DBG_MOVEINFO);
75
76
IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->InitPartTmr));
77
78
/* this is required for the cut-based part of the refinement */
79
Setup2WayBalMultipliers(ctrl, graph, ntpwgts);
80
81
switch (ctrl->iptype) {
82
case METIS_IPTYPE_EDGE:
83
if (graph->nedges == 0)
84
RandomBisection(ctrl, graph, ntpwgts, niparts);
85
else
86
GrowBisection(ctrl, graph, ntpwgts, niparts);
87
88
Compute2WayPartitionParams(ctrl, graph);
89
ConstructSeparator(ctrl, graph);
90
break;
91
92
case METIS_IPTYPE_NODE:
93
GrowBisectionNode(ctrl, graph, ntpwgts, niparts);
94
break;
95
96
default:
97
gk_errexit(SIGERR, "Unkown iptype of %"PRIDX"\n", ctrl->iptype);
98
}
99
100
IFSET(ctrl->dbglvl, METIS_DBG_IPART, printf("Initial Sep: %"PRIDX"\n", graph->mincut));
101
IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->InitPartTmr));
102
103
ctrl->dbglvl = dbglvl;
104
105
}
106
107
108
/*************************************************************************/
109
/*! This function computes a bisection of a graph by randomly assigning
110
the vertices followed by a bisection refinement.
111
The resulting partition is returned in graph->where.
112
*/
113
/*************************************************************************/
114
void RandomBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts,
115
idx_t niparts)
116
{
117
idx_t i, ii, j, k, nvtxs, pwgts[2], zeromaxpwgt, from, me,
118
bestcut=0, icut, mincut, inbfs;
119
idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where;
120
idx_t *perm, *bestwhere;
121
122
WCOREPUSH;
123
124
nvtxs = graph->nvtxs;
125
xadj = graph->xadj;
126
vwgt = graph->vwgt;
127
adjncy = graph->adjncy;
128
adjwgt = graph->adjwgt;
129
130
Allocate2WayPartitionMemory(ctrl, graph);
131
where = graph->where;
132
133
bestwhere = iwspacemalloc(ctrl, nvtxs);
134
perm = iwspacemalloc(ctrl, nvtxs);
135
136
zeromaxpwgt = ctrl->ubfactors[0]*graph->tvwgt[0]*ntpwgts[0];
137
138
for (inbfs=0; inbfs<niparts; inbfs++) {
139
iset(nvtxs, 1, where);
140
141
if (inbfs > 0) {
142
irandArrayPermute(nvtxs, perm, nvtxs/2, 1);
143
pwgts[1] = graph->tvwgt[0];
144
pwgts[0] = 0;
145
146
for (ii=0; ii<nvtxs; ii++) {
147
i = perm[ii];
148
if (pwgts[0]+vwgt[i] < zeromaxpwgt) {
149
where[i] = 0;
150
pwgts[0] += vwgt[i];
151
pwgts[1] -= vwgt[i];
152
if (pwgts[0] > zeromaxpwgt)
153
break;
154
}
155
}
156
}
157
158
/* Do some partition refinement */
159
Compute2WayPartitionParams(ctrl, graph);
160
/* printf("IPART: %3"PRIDX" [%5"PRIDX" %5"PRIDX"] [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n", graph->nvtxs, pwgts[0], pwgts[1], graph->pwgts[0], graph->pwgts[1], graph->mincut); */
161
162
Balance2Way(ctrl, graph, ntpwgts);
163
/* printf("BPART: [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n", graph->pwgts[0], graph->pwgts[1], graph->mincut); */
164
165
FM_2WayRefine(ctrl, graph, ntpwgts, 4);
166
/* printf("RPART: [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n", graph->pwgts[0], graph->pwgts[1], graph->mincut); */
167
168
if (inbfs==0 || bestcut > graph->mincut) {
169
bestcut = graph->mincut;
170
icopy(nvtxs, where, bestwhere);
171
if (bestcut == 0)
172
break;
173
}
174
}
175
176
graph->mincut = bestcut;
177
icopy(nvtxs, bestwhere, where);
178
179
WCOREPOP;
180
}
181
182
183
/*************************************************************************/
184
/*! This function takes a graph and produces a bisection by using a region
185
growing algorithm. The resulting bisection is refined using FM.
186
The resulting partition is returned in graph->where.
187
*/
188
/*************************************************************************/
189
void GrowBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts,
190
idx_t niparts)
191
{
192
idx_t i, j, k, nvtxs, drain, nleft, first, last,
193
pwgts[2], oneminpwgt, onemaxpwgt,
194
from, me, bestcut=0, icut, mincut, inbfs;
195
idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where;
196
idx_t *queue, *touched, *gain, *bestwhere;
197
198
WCOREPUSH;
199
200
nvtxs = graph->nvtxs;
201
xadj = graph->xadj;
202
vwgt = graph->vwgt;
203
adjncy = graph->adjncy;
204
adjwgt = graph->adjwgt;
205
206
Allocate2WayPartitionMemory(ctrl, graph);
207
where = graph->where;
208
209
bestwhere = iwspacemalloc(ctrl, nvtxs);
210
queue = iwspacemalloc(ctrl, nvtxs);
211
touched = iwspacemalloc(ctrl, nvtxs);
212
213
onemaxpwgt = ctrl->ubfactors[0]*graph->tvwgt[0]*ntpwgts[1];
214
oneminpwgt = (1.0/ctrl->ubfactors[0])*graph->tvwgt[0]*ntpwgts[1];
215
216
for (inbfs=0; inbfs<niparts; inbfs++) {
217
iset(nvtxs, 1, where);
218
219
iset(nvtxs, 0, touched);
220
221
pwgts[1] = graph->tvwgt[0];
222
pwgts[0] = 0;
223
224
225
queue[0] = irandInRange(nvtxs);
226
touched[queue[0]] = 1;
227
first = 0;
228
last = 1;
229
nleft = nvtxs-1;
230
drain = 0;
231
232
/* Start the BFS from queue to get a partition */
233
for (;;) {
234
if (first == last) { /* Empty. Disconnected graph! */
235
if (nleft == 0 || drain)
236
break;
237
238
k = irandInRange(nleft);
239
for (i=0; i<nvtxs; i++) {
240
if (touched[i] == 0) {
241
if (k == 0)
242
break;
243
else
244
k--;
245
}
246
}
247
248
queue[0] = i;
249
touched[i] = 1;
250
first = 0;
251
last = 1;
252
nleft--;
253
}
254
255
i = queue[first++];
256
if (pwgts[0] > 0 && pwgts[1]-vwgt[i] < oneminpwgt) {
257
drain = 1;
258
continue;
259
}
260
261
where[i] = 0;
262
INC_DEC(pwgts[0], pwgts[1], vwgt[i]);
263
if (pwgts[1] <= onemaxpwgt)
264
break;
265
266
drain = 0;
267
for (j=xadj[i]; j<xadj[i+1]; j++) {
268
k = adjncy[j];
269
if (touched[k] == 0) {
270
queue[last++] = k;
271
touched[k] = 1;
272
nleft--;
273
}
274
}
275
}
276
277
/* Check to see if we hit any bad limiting cases */
278
if (pwgts[1] == 0)
279
where[irandInRange(nvtxs)] = 1;
280
if (pwgts[0] == 0)
281
where[irandInRange(nvtxs)] = 0;
282
283
/*************************************************************
284
* Do some partition refinement
285
**************************************************************/
286
Compute2WayPartitionParams(ctrl, graph);
287
/*
288
printf("IPART: %3"PRIDX" [%5"PRIDX" %5"PRIDX"] [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n",
289
graph->nvtxs, pwgts[0], pwgts[1], graph->pwgts[0], graph->pwgts[1], graph->mincut);
290
*/
291
292
Balance2Way(ctrl, graph, ntpwgts);
293
/*
294
printf("BPART: [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n", graph->pwgts[0],
295
graph->pwgts[1], graph->mincut);
296
*/
297
298
FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter);
299
/*
300
printf("RPART: [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n", graph->pwgts[0],
301
graph->pwgts[1], graph->mincut);
302
*/
303
304
if (inbfs == 0 || bestcut > graph->mincut) {
305
bestcut = graph->mincut;
306
icopy(nvtxs, where, bestwhere);
307
if (bestcut == 0)
308
break;
309
}
310
}
311
312
graph->mincut = bestcut;
313
icopy(nvtxs, bestwhere, where);
314
315
WCOREPOP;
316
}
317
318
319
/*************************************************************************/
320
/*! This function takes a multi-constraint graph and computes a bisection
321
by randomly assigning the vertices and then refining it. The resulting
322
partition is returned in graph->where.
323
*/
324
/**************************************************************************/
325
void McRandomBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts,
326
idx_t niparts)
327
{
328
idx_t i, ii, j, k, nvtxs, ncon, from, bestcut=0, mincut, inbfs, qnum;
329
idx_t *bestwhere, *where, *perm, *counts;
330
idx_t *vwgt;
331
332
WCOREPUSH;
333
334
nvtxs = graph->nvtxs;
335
ncon = graph->ncon;
336
vwgt = graph->vwgt;
337
338
Allocate2WayPartitionMemory(ctrl, graph);
339
where = graph->where;
340
341
bestwhere = iwspacemalloc(ctrl, nvtxs);
342
perm = iwspacemalloc(ctrl, nvtxs);
343
counts = iwspacemalloc(ctrl, ncon);
344
345
for (inbfs=0; inbfs<2*niparts; inbfs++) {
346
irandArrayPermute(nvtxs, perm, nvtxs/2, 1);
347
iset(ncon, 0, counts);
348
349
/* partition by spliting the queues randomly */
350
for (ii=0; ii<nvtxs; ii++) {
351
i = perm[ii];
352
qnum = iargmax(ncon, vwgt+i*ncon);
353
where[i] = (counts[qnum]++)%2;
354
}
355
356
Compute2WayPartitionParams(ctrl, graph);
357
358
FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter);
359
Balance2Way(ctrl, graph, ntpwgts);
360
FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter);
361
Balance2Way(ctrl, graph, ntpwgts);
362
FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter);
363
364
if (inbfs == 0 || bestcut >= graph->mincut) {
365
bestcut = graph->mincut;
366
icopy(nvtxs, where, bestwhere);
367
if (bestcut == 0)
368
break;
369
}
370
}
371
372
graph->mincut = bestcut;
373
icopy(nvtxs, bestwhere, where);
374
375
WCOREPOP;
376
}
377
378
379
/*************************************************************************/
380
/*! This function takes a multi-constraint graph and produces a bisection
381
by using a region growing algorithm. The resulting partition is
382
returned in graph->where.
383
*/
384
/*************************************************************************/
385
void McGrowBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts,
386
idx_t niparts)
387
{
388
idx_t i, j, k, nvtxs, ncon, from, bestcut=0, mincut, inbfs;
389
idx_t *bestwhere, *where;
390
391
WCOREPUSH;
392
393
nvtxs = graph->nvtxs;
394
395
Allocate2WayPartitionMemory(ctrl, graph);
396
where = graph->where;
397
398
bestwhere = iwspacemalloc(ctrl, nvtxs);
399
400
for (inbfs=0; inbfs<2*niparts; inbfs++) {
401
iset(nvtxs, 1, where);
402
where[irandInRange(nvtxs)] = 0;
403
404
Compute2WayPartitionParams(ctrl, graph);
405
406
Balance2Way(ctrl, graph, ntpwgts);
407
FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter);
408
Balance2Way(ctrl, graph, ntpwgts);
409
FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter);
410
411
if (inbfs == 0 || bestcut >= graph->mincut) {
412
bestcut = graph->mincut;
413
icopy(nvtxs, where, bestwhere);
414
if (bestcut == 0)
415
break;
416
}
417
}
418
419
graph->mincut = bestcut;
420
icopy(nvtxs, bestwhere, where);
421
422
WCOREPOP;
423
}
424
425
426
/*************************************************************************/
427
/* This function takes a graph and produces a tri-section into left, right,
428
and separator using a region growing algorithm. The resulting separator
429
is refined using node FM.
430
The resulting partition is returned in graph->where.
431
*/
432
/**************************************************************************/
433
void GrowBisectionNode(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts,
434
idx_t niparts)
435
{
436
idx_t i, j, k, nvtxs, drain, nleft, first, last, pwgts[2], oneminpwgt,
437
onemaxpwgt, from, me, bestcut=0, icut, mincut, inbfs;
438
idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where, *bndind;
439
idx_t *queue, *touched, *gain, *bestwhere;
440
441
WCOREPUSH;
442
443
nvtxs = graph->nvtxs;
444
xadj = graph->xadj;
445
vwgt = graph->vwgt;
446
adjncy = graph->adjncy;
447
adjwgt = graph->adjwgt;
448
449
bestwhere = iwspacemalloc(ctrl, nvtxs);
450
queue = iwspacemalloc(ctrl, nvtxs);
451
touched = iwspacemalloc(ctrl, nvtxs);
452
453
onemaxpwgt = ctrl->ubfactors[0]*graph->tvwgt[0]*0.5;
454
oneminpwgt = (1.0/ctrl->ubfactors[0])*graph->tvwgt[0]*0.5;
455
456
457
/* Allocate refinement memory. Allocate sufficient memory for both edge and node */
458
graph->pwgts = imalloc(3, "GrowBisectionNode: pwgts");
459
graph->where = imalloc(nvtxs, "GrowBisectionNode: where");
460
graph->bndptr = imalloc(nvtxs, "GrowBisectionNode: bndptr");
461
graph->bndind = imalloc(nvtxs, "GrowBisectionNode: bndind");
462
graph->id = imalloc(nvtxs, "GrowBisectionNode: id");
463
graph->ed = imalloc(nvtxs, "GrowBisectionNode: ed");
464
graph->nrinfo = (nrinfo_t *)gk_malloc(nvtxs*sizeof(nrinfo_t), "GrowBisectionNode: nrinfo");
465
466
where = graph->where;
467
bndind = graph->bndind;
468
469
for (inbfs=0; inbfs<niparts; inbfs++) {
470
iset(nvtxs, 1, where);
471
iset(nvtxs, 0, touched);
472
473
pwgts[1] = graph->tvwgt[0];
474
pwgts[0] = 0;
475
476
queue[0] = irandInRange(nvtxs);
477
touched[queue[0]] = 1;
478
first = 0; last = 1;
479
nleft = nvtxs-1;
480
drain = 0;
481
482
/* Start the BFS from queue to get a partition */
483
for (;;) {
484
if (first == last) { /* Empty. Disconnected graph! */
485
if (nleft == 0 || drain)
486
break;
487
488
k = irandInRange(nleft);
489
for (i=0; i<nvtxs; i++) { /* select the kth untouched vertex */
490
if (touched[i] == 0) {
491
if (k == 0)
492
break;
493
else
494
k--;
495
}
496
}
497
498
queue[0] = i;
499
touched[i] = 1;
500
first = 0;
501
last = 1;
502
nleft--;
503
}
504
505
i = queue[first++];
506
if (pwgts[1]-vwgt[i] < oneminpwgt) {
507
drain = 1;
508
continue;
509
}
510
511
where[i] = 0;
512
INC_DEC(pwgts[0], pwgts[1], vwgt[i]);
513
if (pwgts[1] <= onemaxpwgt)
514
break;
515
516
drain = 0;
517
for (j=xadj[i]; j<xadj[i+1]; j++) {
518
k = adjncy[j];
519
if (touched[k] == 0) {
520
queue[last++] = k;
521
touched[k] = 1;
522
nleft--;
523
}
524
}
525
}
526
527
/*************************************************************
528
* Do some partition refinement
529
**************************************************************/
530
Compute2WayPartitionParams(ctrl, graph);
531
Balance2Way(ctrl, graph, ntpwgts);
532
FM_2WayRefine(ctrl, graph, ntpwgts, 4);
533
534
/* Construct and refine the vertex separator */
535
for (i=0; i<graph->nbnd; i++) {
536
j = bndind[i];
537
if (xadj[j+1]-xadj[j] > 0) /* ignore islands */
538
where[j] = 2;
539
}
540
541
Compute2WayNodePartitionParams(ctrl, graph);
542
FM_2WayNodeRefine2Sided(ctrl, graph, 1);
543
FM_2WayNodeRefine1Sided(ctrl, graph, 4);
544
545
/*
546
printf("ISep: [%"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"] %"PRIDX"\n",
547
inbfs, graph->pwgts[0], graph->pwgts[1], graph->pwgts[2], bestcut);
548
*/
549
550
if (inbfs == 0 || bestcut > graph->mincut) {
551
bestcut = graph->mincut;
552
icopy(nvtxs, where, bestwhere);
553
}
554
}
555
556
graph->mincut = bestcut;
557
icopy(nvtxs, bestwhere, where);
558
559
WCOREPOP;
560
}
561
562
563
/*************************************************************************/
564
/* This function takes a graph and produces a tri-section into left, right,
565
and separator using a region growing algorithm. The resulting separator
566
is refined using node FM.
567
The resulting partition is returned in graph->where.
568
*/
569
/**************************************************************************/
570
void GrowBisectionNode2(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts,
571
idx_t niparts)
572
{
573
idx_t i, j, k, nvtxs, bestcut=0, mincut, inbfs;
574
idx_t *xadj, *where, *bndind, *bestwhere;
575
576
WCOREPUSH;
577
578
nvtxs = graph->nvtxs;
579
xadj = graph->xadj;
580
581
/* Allocate refinement memory. Allocate sufficient memory for both edge and node */
582
graph->pwgts = imalloc(3, "GrowBisectionNode: pwgts");
583
graph->where = imalloc(nvtxs, "GrowBisectionNode: where");
584
graph->bndptr = imalloc(nvtxs, "GrowBisectionNode: bndptr");
585
graph->bndind = imalloc(nvtxs, "GrowBisectionNode: bndind");
586
graph->id = imalloc(nvtxs, "GrowBisectionNode: id");
587
graph->ed = imalloc(nvtxs, "GrowBisectionNode: ed");
588
graph->nrinfo = (nrinfo_t *)gk_malloc(nvtxs*sizeof(nrinfo_t), "GrowBisectionNode: nrinfo");
589
590
bestwhere = iwspacemalloc(ctrl, nvtxs);
591
592
where = graph->where;
593
bndind = graph->bndind;
594
595
for (inbfs=0; inbfs<niparts; inbfs++) {
596
iset(nvtxs, 1, where);
597
if (inbfs > 0)
598
where[irandInRange(nvtxs)] = 0;
599
600
Compute2WayPartitionParams(ctrl, graph);
601
General2WayBalance(ctrl, graph, ntpwgts);
602
FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter);
603
604
/* Construct and refine the vertex separator */
605
for (i=0; i<graph->nbnd; i++) {
606
j = bndind[i];
607
if (xadj[j+1]-xadj[j] > 0) /* ignore islands */
608
where[j] = 2;
609
}
610
611
Compute2WayNodePartitionParams(ctrl, graph);
612
FM_2WayNodeRefine2Sided(ctrl, graph, 4);
613
614
/*
615
printf("ISep: [%"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"] %"PRIDX"\n",
616
inbfs, graph->pwgts[0], graph->pwgts[1], graph->pwgts[2], bestcut);
617
*/
618
619
if (inbfs == 0 || bestcut > graph->mincut) {
620
bestcut = graph->mincut;
621
icopy(nvtxs, where, bestwhere);
622
}
623
}
624
625
graph->mincut = bestcut;
626
icopy(nvtxs, bestwhere, where);
627
628
WCOREPOP;
629
}
630
631
632