Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/elmergrid/src/metis-5.1.0/libmetis/sfm.c
3206 views
1
/*
2
* Copyright 1997, Regents of the University of Minnesota
3
*
4
* sfm.c
5
*
6
* This file contains code that implementes an FM-based separator refinement
7
*
8
* Started 8/1/97
9
* George
10
*
11
* $Id: sfm.c 10874 2011-10-17 23:13:00Z karypis $
12
*
13
*/
14
15
#include "metislib.h"
16
17
18
/*************************************************************************/
19
/*! This function performs a node-based FM refinement */
20
/**************************************************************************/
21
void FM_2WayNodeRefine2Sided(ctrl_t *ctrl, graph_t *graph, idx_t niter)
22
{
23
idx_t i, ii, j, k, jj, kk, nvtxs, nbnd, nswaps, nmind;
24
idx_t *xadj, *vwgt, *adjncy, *where, *pwgts, *edegrees, *bndind, *bndptr;
25
idx_t *mptr, *mind, *moved, *swaps;
26
rpq_t *queues[2];
27
nrinfo_t *rinfo;
28
idx_t higain, oldgain, mincut, initcut, mincutorder;
29
idx_t pass, to, other, limit;
30
idx_t badmaxpwgt, mindiff, newdiff;
31
idx_t u[2], g[2];
32
real_t mult;
33
34
WCOREPUSH;
35
36
nvtxs = graph->nvtxs;
37
xadj = graph->xadj;
38
adjncy = graph->adjncy;
39
vwgt = graph->vwgt;
40
41
bndind = graph->bndind;
42
bndptr = graph->bndptr;
43
where = graph->where;
44
pwgts = graph->pwgts;
45
rinfo = graph->nrinfo;
46
47
queues[0] = rpqCreate(nvtxs);
48
queues[1] = rpqCreate(nvtxs);
49
50
moved = iwspacemalloc(ctrl, nvtxs);
51
swaps = iwspacemalloc(ctrl, nvtxs);
52
mptr = iwspacemalloc(ctrl, nvtxs+1);
53
mind = iwspacemalloc(ctrl, 2*nvtxs);
54
55
mult = 0.5*ctrl->ubfactors[0];
56
badmaxpwgt = (idx_t)(mult*(pwgts[0]+pwgts[1]+pwgts[2]));
57
58
IFSET(ctrl->dbglvl, METIS_DBG_REFINE,
59
printf("Partitions-N2: [%6"PRIDX" %6"PRIDX"] Nv-Nb[%6"PRIDX" %6"PRIDX"]. ISep: %6"PRIDX"\n", pwgts[0], pwgts[1], graph->nvtxs, graph->nbnd, graph->mincut));
60
61
for (pass=0; pass<niter; pass++) {
62
iset(nvtxs, -1, moved);
63
rpqReset(queues[0]);
64
rpqReset(queues[1]);
65
66
mincutorder = -1;
67
initcut = mincut = graph->mincut;
68
nbnd = graph->nbnd;
69
70
/* use the swaps array in place of the traditional perm array to save memory */
71
irandArrayPermute(nbnd, swaps, nbnd, 1);
72
for (ii=0; ii<nbnd; ii++) {
73
i = bndind[swaps[ii]];
74
ASSERT(where[i] == 2);
75
rpqInsert(queues[0], i, vwgt[i]-rinfo[i].edegrees[1]);
76
rpqInsert(queues[1], i, vwgt[i]-rinfo[i].edegrees[0]);
77
}
78
79
ASSERT(CheckNodeBnd(graph, nbnd));
80
ASSERT(CheckNodePartitionParams(graph));
81
82
limit = (ctrl->compress ? gk_min(5*nbnd, 400) : gk_min(2*nbnd, 300));
83
84
/******************************************************
85
* Get into the FM loop
86
*******************************************************/
87
mptr[0] = nmind = 0;
88
mindiff = iabs(pwgts[0]-pwgts[1]);
89
to = (pwgts[0] < pwgts[1] ? 0 : 1);
90
for (nswaps=0; nswaps<nvtxs; nswaps++) {
91
u[0] = rpqSeeTopVal(queues[0]);
92
u[1] = rpqSeeTopVal(queues[1]);
93
if (u[0] != -1 && u[1] != -1) {
94
g[0] = vwgt[u[0]]-rinfo[u[0]].edegrees[1];
95
g[1] = vwgt[u[1]]-rinfo[u[1]].edegrees[0];
96
97
to = (g[0] > g[1] ? 0 : (g[0] < g[1] ? 1 : pass%2));
98
99
if (pwgts[to]+vwgt[u[to]] > badmaxpwgt)
100
to = (to+1)%2;
101
}
102
else if (u[0] == -1 && u[1] == -1) {
103
break;
104
}
105
else if (u[0] != -1 && pwgts[0]+vwgt[u[0]] <= badmaxpwgt) {
106
to = 0;
107
}
108
else if (u[1] != -1 && pwgts[1]+vwgt[u[1]] <= badmaxpwgt) {
109
to = 1;
110
}
111
else
112
break;
113
114
other = (to+1)%2;
115
116
higain = rpqGetTop(queues[to]);
117
if (moved[higain] == -1) /* Delete if it was in the separator originally */
118
rpqDelete(queues[other], higain);
119
120
ASSERT(bndptr[higain] != -1);
121
122
/* The following check is to ensure we break out if there is a posibility
123
of over-running the mind array. */
124
if (nmind + xadj[higain+1]-xadj[higain] >= 2*nvtxs-1)
125
break;
126
127
pwgts[2] -= (vwgt[higain]-rinfo[higain].edegrees[other]);
128
129
newdiff = iabs(pwgts[to]+vwgt[higain] - (pwgts[other]-rinfo[higain].edegrees[other]));
130
if (pwgts[2] < mincut || (pwgts[2] == mincut && newdiff < mindiff)) {
131
mincut = pwgts[2];
132
mincutorder = nswaps;
133
mindiff = newdiff;
134
}
135
else {
136
if (nswaps - mincutorder > 2*limit ||
137
(nswaps - mincutorder > limit && pwgts[2] > 1.10*mincut)) {
138
pwgts[2] += (vwgt[higain]-rinfo[higain].edegrees[other]);
139
break; /* No further improvement, break out */
140
}
141
}
142
143
BNDDelete(nbnd, bndind, bndptr, higain);
144
pwgts[to] += vwgt[higain];
145
where[higain] = to;
146
moved[higain] = nswaps;
147
swaps[nswaps] = higain;
148
149
150
/**********************************************************
151
* Update the degrees of the affected nodes
152
***********************************************************/
153
for (j=xadj[higain]; j<xadj[higain+1]; j++) {
154
k = adjncy[j];
155
if (where[k] == 2) { /* For the in-separator vertices modify their edegree[to] */
156
oldgain = vwgt[k]-rinfo[k].edegrees[to];
157
rinfo[k].edegrees[to] += vwgt[higain];
158
if (moved[k] == -1 || moved[k] == -(2+other))
159
rpqUpdate(queues[other], k, oldgain-vwgt[higain]);
160
}
161
else if (where[k] == other) { /* This vertex is pulled into the separator */
162
ASSERTP(bndptr[k] == -1, ("%"PRIDX" %"PRIDX" %"PRIDX"\n", k, bndptr[k], where[k]));
163
BNDInsert(nbnd, bndind, bndptr, k);
164
165
mind[nmind++] = k; /* Keep track for rollback */
166
where[k] = 2;
167
pwgts[other] -= vwgt[k];
168
169
edegrees = rinfo[k].edegrees;
170
edegrees[0] = edegrees[1] = 0;
171
for (jj=xadj[k]; jj<xadj[k+1]; jj++) {
172
kk = adjncy[jj];
173
if (where[kk] != 2)
174
edegrees[where[kk]] += vwgt[kk];
175
else {
176
oldgain = vwgt[kk]-rinfo[kk].edegrees[other];
177
rinfo[kk].edegrees[other] -= vwgt[k];
178
if (moved[kk] == -1 || moved[kk] == -(2+to))
179
rpqUpdate(queues[to], kk, oldgain+vwgt[k]);
180
}
181
}
182
183
/* Insert the new vertex into the priority queue. Only one side! */
184
if (moved[k] == -1) {
185
rpqInsert(queues[to], k, vwgt[k]-edegrees[other]);
186
moved[k] = -(2+to);
187
}
188
}
189
}
190
mptr[nswaps+1] = nmind;
191
192
IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO,
193
printf("Moved %6"PRIDX" to %3"PRIDX", Gain: %5"PRIDX" [%5"PRIDX"] [%4"PRIDX" %4"PRIDX"] \t[%5"PRIDX" %5"PRIDX" %5"PRIDX"]\n", higain, to, g[to], g[other], vwgt[u[to]], vwgt[u[other]], pwgts[0], pwgts[1], pwgts[2]));
194
195
}
196
197
198
/****************************************************************
199
* Roll back computation
200
*****************************************************************/
201
for (nswaps--; nswaps>mincutorder; nswaps--) {
202
higain = swaps[nswaps];
203
204
ASSERT(CheckNodePartitionParams(graph));
205
206
to = where[higain];
207
other = (to+1)%2;
208
INC_DEC(pwgts[2], pwgts[to], vwgt[higain]);
209
where[higain] = 2;
210
BNDInsert(nbnd, bndind, bndptr, higain);
211
212
edegrees = rinfo[higain].edegrees;
213
edegrees[0] = edegrees[1] = 0;
214
for (j=xadj[higain]; j<xadj[higain+1]; j++) {
215
k = adjncy[j];
216
if (where[k] == 2)
217
rinfo[k].edegrees[to] -= vwgt[higain];
218
else
219
edegrees[where[k]] += vwgt[k];
220
}
221
222
/* Push nodes out of the separator */
223
for (j=mptr[nswaps]; j<mptr[nswaps+1]; j++) {
224
k = mind[j];
225
ASSERT(where[k] == 2);
226
where[k] = other;
227
INC_DEC(pwgts[other], pwgts[2], vwgt[k]);
228
BNDDelete(nbnd, bndind, bndptr, k);
229
for (jj=xadj[k]; jj<xadj[k+1]; jj++) {
230
kk = adjncy[jj];
231
if (where[kk] == 2)
232
rinfo[kk].edegrees[other] += vwgt[k];
233
}
234
}
235
}
236
237
ASSERT(mincut == pwgts[2]);
238
239
IFSET(ctrl->dbglvl, METIS_DBG_REFINE,
240
printf("\tMinimum sep: %6"PRIDX" at %5"PRIDX", PWGTS: [%6"PRIDX" %6"PRIDX"], NBND: %6"PRIDX"\n", mincut, mincutorder, pwgts[0], pwgts[1], nbnd));
241
242
graph->mincut = mincut;
243
graph->nbnd = nbnd;
244
245
if (mincutorder == -1 || mincut >= initcut)
246
break;
247
}
248
249
rpqDestroy(queues[0]);
250
rpqDestroy(queues[1]);
251
252
WCOREPOP;
253
}
254
255
256
/*************************************************************************/
257
/*! This function performs a node-based FM refinement.
258
Each refinement iteration is split into two sub-iterations.
259
In each sub-iteration only moves to one of the left/right partitions
260
is allowed; hence, it is one-sided.
261
*/
262
/**************************************************************************/
263
void FM_2WayNodeRefine1Sided(ctrl_t *ctrl, graph_t *graph, idx_t niter)
264
{
265
idx_t i, ii, j, k, jj, kk, nvtxs, nbnd, nswaps, nmind, iend;
266
idx_t *xadj, *vwgt, *adjncy, *where, *pwgts, *edegrees, *bndind, *bndptr;
267
idx_t *mptr, *mind, *swaps;
268
rpq_t *queue;
269
nrinfo_t *rinfo;
270
idx_t higain, mincut, initcut, mincutorder;
271
idx_t pass, to, other, limit;
272
idx_t badmaxpwgt, mindiff, newdiff;
273
real_t mult;
274
275
WCOREPUSH;
276
277
nvtxs = graph->nvtxs;
278
xadj = graph->xadj;
279
adjncy = graph->adjncy;
280
vwgt = graph->vwgt;
281
282
bndind = graph->bndind;
283
bndptr = graph->bndptr;
284
where = graph->where;
285
pwgts = graph->pwgts;
286
rinfo = graph->nrinfo;
287
288
queue = rpqCreate(nvtxs);
289
290
swaps = iwspacemalloc(ctrl, nvtxs);
291
mptr = iwspacemalloc(ctrl, nvtxs+1);
292
mind = iwspacemalloc(ctrl, 2*nvtxs);
293
294
mult = 0.5*ctrl->ubfactors[0];
295
badmaxpwgt = (idx_t)(mult*(pwgts[0]+pwgts[1]+pwgts[2]));
296
297
IFSET(ctrl->dbglvl, METIS_DBG_REFINE,
298
printf("Partitions-N1: [%6"PRIDX" %6"PRIDX"] Nv-Nb[%6"PRIDX" %6"PRIDX"]. ISep: %6"PRIDX"\n", pwgts[0], pwgts[1], graph->nvtxs, graph->nbnd, graph->mincut));
299
300
to = (pwgts[0] < pwgts[1] ? 1 : 0);
301
for (pass=0; pass<2*niter; pass++) { /* the 2*niter is for the two sides */
302
other = to;
303
to = (to+1)%2;
304
305
rpqReset(queue);
306
307
mincutorder = -1;
308
initcut = mincut = graph->mincut;
309
nbnd = graph->nbnd;
310
311
/* use the swaps array in place of the traditional perm array to save memory */
312
irandArrayPermute(nbnd, swaps, nbnd, 1);
313
for (ii=0; ii<nbnd; ii++) {
314
i = bndind[swaps[ii]];
315
ASSERT(where[i] == 2);
316
rpqInsert(queue, i, vwgt[i]-rinfo[i].edegrees[other]);
317
}
318
319
ASSERT(CheckNodeBnd(graph, nbnd));
320
ASSERT(CheckNodePartitionParams(graph));
321
322
limit = (ctrl->compress ? gk_min(5*nbnd, 500) : gk_min(3*nbnd, 300));
323
324
/******************************************************
325
* Get into the FM loop
326
*******************************************************/
327
IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->Aux3Tmr));
328
mptr[0] = nmind = 0;
329
mindiff = iabs(pwgts[0]-pwgts[1]);
330
for (nswaps=0; nswaps<nvtxs; nswaps++) {
331
if ((higain = rpqGetTop(queue)) == -1)
332
break;
333
334
ASSERT(bndptr[higain] != -1);
335
336
/* The following check is to ensure we break out if there is a posibility
337
of over-running the mind array. */
338
if (nmind + xadj[higain+1]-xadj[higain] >= 2*nvtxs-1)
339
break;
340
341
if (pwgts[to]+vwgt[higain] > badmaxpwgt)
342
break; /* No point going any further. Balance will be bad */
343
344
pwgts[2] -= (vwgt[higain]-rinfo[higain].edegrees[other]);
345
346
newdiff = iabs(pwgts[to]+vwgt[higain] - (pwgts[other]-rinfo[higain].edegrees[other]));
347
if (pwgts[2] < mincut || (pwgts[2] == mincut && newdiff < mindiff)) {
348
mincut = pwgts[2];
349
mincutorder = nswaps;
350
mindiff = newdiff;
351
}
352
else {
353
if (nswaps - mincutorder > 3*limit ||
354
(nswaps - mincutorder > limit && pwgts[2] > 1.10*mincut)) {
355
pwgts[2] += (vwgt[higain]-rinfo[higain].edegrees[other]);
356
break; /* No further improvement, break out */
357
}
358
}
359
360
BNDDelete(nbnd, bndind, bndptr, higain);
361
pwgts[to] += vwgt[higain];
362
where[higain] = to;
363
swaps[nswaps] = higain;
364
365
366
/**********************************************************
367
* Update the degrees of the affected nodes
368
***********************************************************/
369
IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->Aux1Tmr));
370
for (j=xadj[higain]; j<xadj[higain+1]; j++) {
371
k = adjncy[j];
372
373
if (where[k] == 2) { /* For the in-separator vertices modify their edegree[to] */
374
rinfo[k].edegrees[to] += vwgt[higain];
375
}
376
else if (where[k] == other) { /* This vertex is pulled into the separator */
377
ASSERTP(bndptr[k] == -1, ("%"PRIDX" %"PRIDX" %"PRIDX"\n", k, bndptr[k], where[k]));
378
BNDInsert(nbnd, bndind, bndptr, k);
379
380
mind[nmind++] = k; /* Keep track for rollback */
381
where[k] = 2;
382
pwgts[other] -= vwgt[k];
383
384
edegrees = rinfo[k].edegrees;
385
edegrees[0] = edegrees[1] = 0;
386
for (jj=xadj[k], iend=xadj[k+1]; jj<iend; jj++) {
387
kk = adjncy[jj];
388
if (where[kk] != 2)
389
edegrees[where[kk]] += vwgt[kk];
390
else {
391
rinfo[kk].edegrees[other] -= vwgt[k];
392
393
/* Since the moves are one-sided this vertex has not been moved yet */
394
rpqUpdate(queue, kk, vwgt[kk]-rinfo[kk].edegrees[other]);
395
}
396
}
397
398
/* Insert the new vertex into the priority queue. Safe due to one-sided moves */
399
rpqInsert(queue, k, vwgt[k]-edegrees[other]);
400
}
401
}
402
mptr[nswaps+1] = nmind;
403
IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->Aux1Tmr));
404
405
406
IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO,
407
printf("Moved %6"PRIDX" to %3"PRIDX", Gain: %5"PRIDX" [%5"PRIDX"] \t[%5"PRIDX" %5"PRIDX" %5"PRIDX"] [%3"PRIDX" %2"PRIDX"]\n",
408
higain, to, (vwgt[higain]-rinfo[higain].edegrees[other]), vwgt[higain],
409
pwgts[0], pwgts[1], pwgts[2], nswaps, limit));
410
}
411
IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->Aux3Tmr));
412
413
414
/****************************************************************
415
* Roll back computation
416
*****************************************************************/
417
IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->Aux2Tmr));
418
for (nswaps--; nswaps>mincutorder; nswaps--) {
419
higain = swaps[nswaps];
420
421
ASSERT(CheckNodePartitionParams(graph));
422
ASSERT(where[higain] == to);
423
424
INC_DEC(pwgts[2], pwgts[to], vwgt[higain]);
425
where[higain] = 2;
426
BNDInsert(nbnd, bndind, bndptr, higain);
427
428
edegrees = rinfo[higain].edegrees;
429
edegrees[0] = edegrees[1] = 0;
430
for (j=xadj[higain]; j<xadj[higain+1]; j++) {
431
k = adjncy[j];
432
if (where[k] == 2)
433
rinfo[k].edegrees[to] -= vwgt[higain];
434
else
435
edegrees[where[k]] += vwgt[k];
436
}
437
438
/* Push nodes out of the separator */
439
for (j=mptr[nswaps]; j<mptr[nswaps+1]; j++) {
440
k = mind[j];
441
ASSERT(where[k] == 2);
442
where[k] = other;
443
INC_DEC(pwgts[other], pwgts[2], vwgt[k]);
444
BNDDelete(nbnd, bndind, bndptr, k);
445
for (jj=xadj[k], iend=xadj[k+1]; jj<iend; jj++) {
446
kk = adjncy[jj];
447
if (where[kk] == 2)
448
rinfo[kk].edegrees[other] += vwgt[k];
449
}
450
}
451
}
452
IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->Aux2Tmr));
453
454
ASSERT(mincut == pwgts[2]);
455
456
IFSET(ctrl->dbglvl, METIS_DBG_REFINE,
457
printf("\tMinimum sep: %6"PRIDX" at %5"PRIDX", PWGTS: [%6"PRIDX" %6"PRIDX"], NBND: %6"PRIDX"\n", mincut, mincutorder, pwgts[0], pwgts[1], nbnd));
458
459
graph->mincut = mincut;
460
graph->nbnd = nbnd;
461
462
if (pass%2 == 1 && (mincutorder == -1 || mincut >= initcut))
463
break;
464
}
465
466
rpqDestroy(queue);
467
468
WCOREPOP;
469
}
470
471
472
/*************************************************************************/
473
/*! This function balances the left/right partitions of a separator
474
tri-section */
475
/*************************************************************************/
476
void FM_2WayNodeBalance(ctrl_t *ctrl, graph_t *graph)
477
{
478
idx_t i, ii, j, k, jj, kk, nvtxs, nbnd, nswaps, gain;
479
idx_t badmaxpwgt, higain, oldgain, pass, to, other;
480
idx_t *xadj, *vwgt, *adjncy, *where, *pwgts, *edegrees, *bndind, *bndptr;
481
idx_t *perm, *moved;
482
rpq_t *queue;
483
nrinfo_t *rinfo;
484
real_t mult;
485
486
nvtxs = graph->nvtxs;
487
xadj = graph->xadj;
488
adjncy = graph->adjncy;
489
vwgt = graph->vwgt;
490
491
bndind = graph->bndind;
492
bndptr = graph->bndptr;
493
where = graph->where;
494
pwgts = graph->pwgts;
495
rinfo = graph->nrinfo;
496
497
mult = 0.5*ctrl->ubfactors[0];
498
499
badmaxpwgt = (idx_t)(mult*(pwgts[0]+pwgts[1]));
500
if (gk_max(pwgts[0], pwgts[1]) < badmaxpwgt)
501
return;
502
if (iabs(pwgts[0]-pwgts[1]) < 3*graph->tvwgt[0]/nvtxs)
503
return;
504
505
WCOREPUSH;
506
507
to = (pwgts[0] < pwgts[1] ? 0 : 1);
508
other = (to+1)%2;
509
510
queue = rpqCreate(nvtxs);
511
512
perm = iwspacemalloc(ctrl, nvtxs);
513
moved = iset(nvtxs, -1, iwspacemalloc(ctrl, nvtxs));
514
515
IFSET(ctrl->dbglvl, METIS_DBG_REFINE,
516
printf("Partitions: [%6"PRIDX" %6"PRIDX"] Nv-Nb[%6"PRIDX" %6"PRIDX"]. ISep: %6"PRIDX" [B]\n", pwgts[0], pwgts[1], graph->nvtxs, graph->nbnd, graph->mincut));
517
518
nbnd = graph->nbnd;
519
irandArrayPermute(nbnd, perm, nbnd, 1);
520
for (ii=0; ii<nbnd; ii++) {
521
i = bndind[perm[ii]];
522
ASSERT(where[i] == 2);
523
rpqInsert(queue, i, vwgt[i]-rinfo[i].edegrees[other]);
524
}
525
526
ASSERT(CheckNodeBnd(graph, nbnd));
527
ASSERT(CheckNodePartitionParams(graph));
528
529
/******************************************************
530
* Get into the FM loop
531
*******************************************************/
532
for (nswaps=0; nswaps<nvtxs; nswaps++) {
533
if ((higain = rpqGetTop(queue)) == -1)
534
break;
535
536
moved[higain] = 1;
537
538
gain = vwgt[higain]-rinfo[higain].edegrees[other];
539
badmaxpwgt = (idx_t)(mult*(pwgts[0]+pwgts[1]));
540
541
/* break if other is now underwight */
542
if (pwgts[to] > pwgts[other])
543
break;
544
545
/* break if balance is achieved and no +ve or zero gain */
546
if (gain < 0 && pwgts[other] < badmaxpwgt)
547
break;
548
549
/* skip this vertex if it will violate balance on the other side */
550
if (pwgts[to]+vwgt[higain] > badmaxpwgt)
551
continue;
552
553
ASSERT(bndptr[higain] != -1);
554
555
pwgts[2] -= gain;
556
557
BNDDelete(nbnd, bndind, bndptr, higain);
558
pwgts[to] += vwgt[higain];
559
where[higain] = to;
560
561
IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO,
562
printf("Moved %6"PRIDX" to %3"PRIDX", Gain: %3"PRIDX", \t[%5"PRIDX" %5"PRIDX" %5"PRIDX"]\n", higain, to, vwgt[higain]-rinfo[higain].edegrees[other], pwgts[0], pwgts[1], pwgts[2]));
563
564
565
/**********************************************************
566
* Update the degrees of the affected nodes
567
***********************************************************/
568
for (j=xadj[higain]; j<xadj[higain+1]; j++) {
569
k = adjncy[j];
570
if (where[k] == 2) { /* For the in-separator vertices modify their edegree[to] */
571
rinfo[k].edegrees[to] += vwgt[higain];
572
}
573
else if (where[k] == other) { /* This vertex is pulled into the separator */
574
ASSERTP(bndptr[k] == -1, ("%"PRIDX" %"PRIDX" %"PRIDX"\n", k, bndptr[k], where[k]));
575
BNDInsert(nbnd, bndind, bndptr, k);
576
577
where[k] = 2;
578
pwgts[other] -= vwgt[k];
579
580
edegrees = rinfo[k].edegrees;
581
edegrees[0] = edegrees[1] = 0;
582
for (jj=xadj[k]; jj<xadj[k+1]; jj++) {
583
kk = adjncy[jj];
584
if (where[kk] != 2)
585
edegrees[where[kk]] += vwgt[kk];
586
else {
587
ASSERT(bndptr[kk] != -1);
588
oldgain = vwgt[kk]-rinfo[kk].edegrees[other];
589
rinfo[kk].edegrees[other] -= vwgt[k];
590
591
if (moved[kk] == -1)
592
rpqUpdate(queue, kk, oldgain+vwgt[k]);
593
}
594
}
595
596
/* Insert the new vertex into the priority queue */
597
rpqInsert(queue, k, vwgt[k]-edegrees[other]);
598
}
599
}
600
}
601
602
IFSET(ctrl->dbglvl, METIS_DBG_REFINE,
603
printf("\tBalanced sep: %6"PRIDX" at %4"PRIDX", PWGTS: [%6"PRIDX" %6"PRIDX"], NBND: %6"PRIDX"\n", pwgts[2], nswaps, pwgts[0], pwgts[1], nbnd));
604
605
graph->mincut = pwgts[2];
606
graph->nbnd = nbnd;
607
608
rpqDestroy(queue);
609
610
WCOREPOP;
611
}
612
613
614