00001
00012 #include "metislib.h"
00013
00014 #define UNMATCHEDFOR2HOP 0.10
00015
00016
00017
00021
00022 graph_t *CoarsenGraph(ctrl_t *ctrl, graph_t *graph)
00023 {
00024 idx_t i, eqewgts, level=0;
00025
00026 IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->CoarsenTmr));
00027
00028
00029 for (eqewgts=1, i=1; i<graph->nedges; i++) {
00030 if (graph->adjwgt[0] != graph->adjwgt[i]) {
00031 eqewgts = 0;
00032 break;
00033 }
00034 }
00035
00036
00037 for (i=0; i<graph->ncon; i++)
00038 ctrl->maxvwgt[i] = 1.5*graph->tvwgt[i]/ctrl->CoarsenTo;
00039
00040 do {
00041 IFSET(ctrl->dbglvl, METIS_DBG_COARSEN, PrintCGraphStats(ctrl, graph));
00042
00043
00044
00045 if (graph->cmap == NULL)
00046 graph->cmap = imalloc(graph->nvtxs, "CoarsenGraph: graph->cmap");
00047
00048
00049 switch (ctrl->ctype) {
00050 case METIS_CTYPE_RM:
00051 Match_RM(ctrl, graph);
00052 break;
00053 case METIS_CTYPE_SHEM:
00054 if (eqewgts || graph->nedges == 0)
00055 Match_RM(ctrl, graph);
00056 else
00057 Match_SHEM(ctrl, graph);
00058 break;
00059 default:
00060 gk_errexit(SIGERR, "Unknown ctype: %d\n", ctrl->ctype);
00061 }
00062
00063 graph = graph->coarser;
00064 eqewgts = 0;
00065 level++;
00066
00067 ASSERT(CheckGraph(graph, 0, 1));
00068
00069 } while (graph->nvtxs > ctrl->CoarsenTo &&
00070 graph->nvtxs < COARSEN_FRACTION*graph->finer->nvtxs &&
00071 graph->nedges > graph->nvtxs/2);
00072
00073 IFSET(ctrl->dbglvl, METIS_DBG_COARSEN, PrintCGraphStats(ctrl, graph));
00074 IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->CoarsenTmr));
00075
00076 return graph;
00077 }
00078
00079
00080
00084
00085 graph_t *CoarsenGraphNlevels(ctrl_t *ctrl, graph_t *graph, idx_t nlevels)
00086 {
00087 idx_t i, eqewgts, level;
00088
00089 IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->CoarsenTmr));
00090
00091
00092 for (eqewgts=1, i=1; i<graph->nedges; i++) {
00093 if (graph->adjwgt[0] != graph->adjwgt[i]) {
00094 eqewgts = 0;
00095 break;
00096 }
00097 }
00098
00099
00100 for (i=0; i<graph->ncon; i++)
00101 ctrl->maxvwgt[i] = 1.5*graph->tvwgt[i]/ctrl->CoarsenTo;
00102
00103 for (level=0; level<nlevels; level++) {
00104 IFSET(ctrl->dbglvl, METIS_DBG_COARSEN, PrintCGraphStats(ctrl, graph));
00105
00106
00107
00108 if (graph->cmap == NULL)
00109 graph->cmap = imalloc(graph->nvtxs, "CoarsenGraph: graph->cmap");
00110
00111
00112 switch (ctrl->ctype) {
00113 case METIS_CTYPE_RM:
00114 Match_RM(ctrl, graph);
00115 break;
00116 case METIS_CTYPE_SHEM:
00117 if (eqewgts || graph->nedges == 0)
00118 Match_RM(ctrl, graph);
00119 else
00120 Match_SHEM(ctrl, graph);
00121 break;
00122 default:
00123 gk_errexit(SIGERR, "Unknown ctype: %d\n", ctrl->ctype);
00124 }
00125
00126 graph = graph->coarser;
00127 eqewgts = 0;
00128
00129 ASSERT(CheckGraph(graph, 0, 1));
00130
00131 if (graph->nvtxs < ctrl->CoarsenTo ||
00132 graph->nvtxs > COARSEN_FRACTION*graph->finer->nvtxs ||
00133 graph->nedges < graph->nvtxs/2)
00134 break;
00135 }
00136
00137 IFSET(ctrl->dbglvl, METIS_DBG_COARSEN, PrintCGraphStats(ctrl, graph));
00138 IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->CoarsenTmr));
00139
00140 return graph;
00141 }
00142
00143
00144
00148
00149 idx_t Match_RM(ctrl_t *ctrl, graph_t *graph)
00150 {
00151 idx_t i, pi, ii, j, jj, jjinc, k, nvtxs, ncon, cnvtxs, maxidx, last_unmatched;
00152 idx_t *xadj, *vwgt, *adjncy, *adjwgt, *maxvwgt;
00153 idx_t *match, *cmap, *perm;
00154 size_t nunmatched=0;
00155
00156 WCOREPUSH;
00157
00158 IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->MatchTmr));
00159
00160 nvtxs = graph->nvtxs;
00161 ncon = graph->ncon;
00162 xadj = graph->xadj;
00163 vwgt = graph->vwgt;
00164 adjncy = graph->adjncy;
00165 adjwgt = graph->adjwgt;
00166 cmap = graph->cmap;
00167
00168 maxvwgt = ctrl->maxvwgt;
00169
00170 match = iset(nvtxs, UNMATCHED, iwspacemalloc(ctrl, nvtxs));
00171 perm = iwspacemalloc(ctrl, nvtxs);
00172
00173 irandArrayPermute(nvtxs, perm, nvtxs/8, 1);
00174
00175 for (cnvtxs=0, last_unmatched=0, pi=0; pi<nvtxs; pi++) {
00176 i = perm[pi];
00177
00178 if (match[i] == UNMATCHED) {
00179 maxidx = i;
00180
00181 if ((ncon == 1 ? vwgt[i] < maxvwgt[0] : ivecle(ncon, vwgt+i*ncon, maxvwgt))) {
00182
00183
00184 if (xadj[i] == xadj[i+1]) {
00185 last_unmatched = gk_max(pi, last_unmatched)+1;
00186 for (; last_unmatched<nvtxs; last_unmatched++) {
00187 j = perm[last_unmatched];
00188 if (match[j] == UNMATCHED) {
00189 maxidx = j;
00190 break;
00191 }
00192 }
00193 }
00194 else {
00195
00196 if (ncon == 1) {
00197
00198 for (j=xadj[i]; j<xadj[i+1]; j++) {
00199 k = adjncy[j];
00200 if (match[k] == UNMATCHED && vwgt[i]+vwgt[k] <= maxvwgt[0]) {
00201 maxidx = k;
00202 break;
00203 }
00204 }
00205
00206
00207 if (maxidx == i && 3*vwgt[i] < maxvwgt[0]) {
00208 nunmatched++;
00209 maxidx = UNMATCHED;
00210 }
00211 }
00212 else {
00213
00214 for (j=xadj[i]; j<xadj[i+1]; j++) {
00215 k = adjncy[j];
00216 if (match[k] == UNMATCHED &&
00217 ivecaxpylez(ncon, 1, vwgt+i*ncon, vwgt+k*ncon, maxvwgt)) {
00218 maxidx = k;
00219 break;
00220 }
00221 }
00222
00223
00224 if (maxidx == i && ivecaxpylez(ncon, 2, vwgt+i*ncon, vwgt+i*ncon, maxvwgt)) {
00225 nunmatched++;
00226 maxidx = UNMATCHED;
00227 }
00228 }
00229 }
00230 }
00231
00232 if (maxidx != UNMATCHED) {
00233 cmap[i] = cmap[maxidx] = cnvtxs++;
00234 match[i] = maxidx;
00235 match[maxidx] = i;
00236 }
00237 }
00238 }
00239
00240
00241
00242
00243 if (!ctrl->no2hop && nunmatched > UNMATCHEDFOR2HOP*nvtxs)
00244 cnvtxs = Match_2Hop(ctrl, graph, perm, match, cnvtxs, nunmatched);
00245
00246
00247
00248
00249 for (cnvtxs=0, i=0; i<nvtxs; i++) {
00250 if (match[i] == UNMATCHED) {
00251 match[i] = i;
00252 cmap[i] = cnvtxs++;
00253 }
00254 else {
00255 if (i <= match[i])
00256 cmap[i] = cmap[match[i]] = cnvtxs++;
00257 }
00258 }
00259
00260 IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->MatchTmr));
00261
00262 CreateCoarseGraph(ctrl, graph, cnvtxs, match);
00263
00264 WCOREPOP;
00265
00266 return cnvtxs;
00267 }
00268
00269
00270
00275
00276 idx_t Match_SHEM(ctrl_t *ctrl, graph_t *graph)
00277 {
00278 idx_t i, pi, ii, j, jj, jjinc, k, nvtxs, ncon, cnvtxs, maxidx, maxwgt,
00279 last_unmatched, avgdegree;
00280 idx_t *xadj, *vwgt, *adjncy, *adjwgt, *maxvwgt;
00281 idx_t *match, *cmap, *degrees, *perm, *tperm;
00282 size_t nunmatched=0;
00283
00284 WCOREPUSH;
00285
00286 IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->MatchTmr));
00287
00288 nvtxs = graph->nvtxs;
00289 ncon = graph->ncon;
00290 xadj = graph->xadj;
00291 vwgt = graph->vwgt;
00292 adjncy = graph->adjncy;
00293 adjwgt = graph->adjwgt;
00294 cmap = graph->cmap;
00295
00296 maxvwgt = ctrl->maxvwgt;
00297
00298 match = iset(nvtxs, UNMATCHED, iwspacemalloc(ctrl, nvtxs));
00299 perm = iwspacemalloc(ctrl, nvtxs);
00300 tperm = iwspacemalloc(ctrl, nvtxs);
00301 degrees = iwspacemalloc(ctrl, nvtxs);
00302
00303 irandArrayPermute(nvtxs, tperm, nvtxs/8, 1);
00304
00305 avgdegree = 0.7*(xadj[nvtxs]/nvtxs);
00306 for (i=0; i<nvtxs; i++)
00307 degrees[i] = (xadj[i+1]-xadj[i] > avgdegree ? avgdegree : xadj[i+1]-xadj[i]);
00308 BucketSortKeysInc(ctrl, nvtxs, avgdegree, degrees, tperm, perm);
00309
00310 for (cnvtxs=0, last_unmatched=0, pi=0; pi<nvtxs; pi++) {
00311 i = perm[pi];
00312
00313 if (match[i] == UNMATCHED) {
00314 maxidx = i;
00315 maxwgt = -1;
00316
00317 if ((ncon == 1 ? vwgt[i] < maxvwgt[0] : ivecle(ncon, vwgt+i*ncon, maxvwgt))) {
00318
00319
00320 if (xadj[i] == xadj[i+1]) {
00321 last_unmatched = gk_max(pi, last_unmatched)+1;
00322 for (; last_unmatched<nvtxs; last_unmatched++) {
00323 j = perm[last_unmatched];
00324 if (match[j] == UNMATCHED) {
00325 maxidx = j;
00326 break;
00327 }
00328 }
00329 }
00330 else {
00331
00332 if (ncon == 1) {
00333
00334 for (j=xadj[i]; j<xadj[i+1]; j++) {
00335 k = adjncy[j];
00336 if (match[k] == UNMATCHED &&
00337 maxwgt < adjwgt[j] && vwgt[i]+vwgt[k] <= maxvwgt[0]) {
00338 maxidx = k;
00339 maxwgt = adjwgt[j];
00340 }
00341 }
00342
00343
00344 if (maxidx == i && 3*vwgt[i] < maxvwgt[0]) {
00345 nunmatched++;
00346 maxidx = UNMATCHED;
00347 }
00348 }
00349 else {
00350
00351 for (j=xadj[i]; j<xadj[i+1]; j++) {
00352 k = adjncy[j];
00353 if (match[k] == UNMATCHED &&
00354 ivecaxpylez(ncon, 1, vwgt+i*ncon, vwgt+k*ncon, maxvwgt) &&
00355 (maxwgt < adjwgt[j] ||
00356 (maxwgt == adjwgt[j] &&
00357 BetterVBalance(ncon, graph->invtvwgt, vwgt+i*ncon,
00358 vwgt+maxidx*ncon, vwgt+k*ncon)))) {
00359 maxidx = k;
00360 maxwgt = adjwgt[j];
00361 }
00362 }
00363
00364
00365 if (maxidx == i && ivecaxpylez(ncon, 2, vwgt+i*ncon, vwgt+i*ncon, maxvwgt)) {
00366 nunmatched++;
00367 maxidx = UNMATCHED;
00368 }
00369 }
00370 }
00371 }
00372
00373 if (maxidx != UNMATCHED) {
00374 cmap[i] = cmap[maxidx] = cnvtxs++;
00375 match[i] = maxidx;
00376 match[maxidx] = i;
00377 }
00378 }
00379 }
00380
00381
00382
00383
00384 if (!ctrl->no2hop && nunmatched > UNMATCHEDFOR2HOP*nvtxs)
00385 cnvtxs = Match_2Hop(ctrl, graph, perm, match, cnvtxs, nunmatched);
00386
00387
00388
00389
00390 for (cnvtxs=0, i=0; i<nvtxs; i++) {
00391 if (match[i] == UNMATCHED) {
00392 match[i] = i;
00393 cmap[i] = cnvtxs++;
00394 }
00395 else {
00396 if (i <= match[i])
00397 cmap[i] = cmap[match[i]] = cnvtxs++;
00398 }
00399 }
00400
00401 IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->MatchTmr));
00402
00403 CreateCoarseGraph(ctrl, graph, cnvtxs, match);
00404
00405 WCOREPOP;
00406
00407 return cnvtxs;
00408 }
00409
00410
00411
00414
00415 idx_t Match_2Hop(ctrl_t *ctrl, graph_t *graph, idx_t *perm, idx_t *match,
00416 idx_t cnvtxs, size_t nunmatched)
00417 {
00418
00419 cnvtxs = Match_2HopAny(ctrl, graph, perm, match, cnvtxs, &nunmatched, 2);
00420 cnvtxs = Match_2HopAll(ctrl, graph, perm, match, cnvtxs, &nunmatched, 64);
00421 if (nunmatched > 1.5*UNMATCHEDFOR2HOP*graph->nvtxs)
00422 cnvtxs = Match_2HopAny(ctrl, graph, perm, match, cnvtxs, &nunmatched, 3);
00423 if (nunmatched > 2.0*UNMATCHEDFOR2HOP*graph->nvtxs)
00424 cnvtxs = Match_2HopAny(ctrl, graph, perm, match, cnvtxs, &nunmatched, graph->nvtxs);
00425
00426 return cnvtxs;
00427 }
00428
00429
00430
00436
00437 idx_t Match_2HopAny(ctrl_t *ctrl, graph_t *graph, idx_t *perm, idx_t *match,
00438 idx_t cnvtxs, size_t *r_nunmatched, size_t maxdegree)
00439 {
00440 idx_t i, pi, ii, j, jj, k, nvtxs;
00441 idx_t *xadj, *adjncy, *colptr, *rowind;
00442 idx_t *cmap;
00443 size_t nunmatched;
00444
00445 IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->Aux3Tmr));
00446
00447 nvtxs = graph->nvtxs;
00448 xadj = graph->xadj;
00449 adjncy = graph->adjncy;
00450 cmap = graph->cmap;
00451
00452 nunmatched = *r_nunmatched;
00453
00454
00455
00456
00457 WCOREPUSH;
00458 colptr = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs+1));
00459 for (i=0; i<nvtxs; i++) {
00460 if (match[i] == UNMATCHED && xadj[i+1]-xadj[i] < maxdegree) {
00461 for (j=xadj[i]; j<xadj[i+1]; j++)
00462 colptr[adjncy[j]]++;
00463 }
00464 }
00465 MAKECSR(i, nvtxs, colptr);
00466
00467 rowind = iwspacemalloc(ctrl, colptr[nvtxs]);
00468 for (pi=0; pi<nvtxs; pi++) {
00469 i = perm[pi];
00470 if (match[i] == UNMATCHED && xadj[i+1]-xadj[i] < maxdegree) {
00471 for (j=xadj[i]; j<xadj[i+1]; j++)
00472 rowind[colptr[adjncy[j]]++] = i;
00473 }
00474 }
00475 SHIFTCSR(i, nvtxs, colptr);
00476
00477
00478 for (pi=0; pi<nvtxs; pi++) {
00479 i = perm[pi];
00480 if (colptr[i+1]-colptr[i] < 2)
00481 continue;
00482
00483 for (jj=colptr[i+1], j=colptr[i]; j<jj; j++) {
00484 if (match[rowind[j]] == UNMATCHED) {
00485 for (jj--; jj>j; jj--) {
00486 if (match[rowind[jj]] == UNMATCHED) {
00487 cmap[rowind[j]] = cmap[rowind[jj]] = cnvtxs++;
00488 match[rowind[j]] = rowind[jj];
00489 match[rowind[jj]] = rowind[j];
00490 nunmatched -= 2;
00491 break;
00492 }
00493 }
00494 }
00495 }
00496 }
00497 WCOREPOP;
00498
00499
00500
00501 IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->Aux3Tmr));
00502
00503 *r_nunmatched = nunmatched;
00504 return cnvtxs;
00505 }
00506
00507
00508
00515
00516 idx_t Match_2HopAll(ctrl_t *ctrl, graph_t *graph, idx_t *perm, idx_t *match,
00517 idx_t cnvtxs, size_t *r_nunmatched, size_t maxdegree)
00518 {
00519 idx_t i, pi, pk, ii, j, jj, k, nvtxs, mask, idegree;
00520 idx_t *xadj, *adjncy;
00521 idx_t *cmap, *mark;
00522 ikv_t *keys;
00523 size_t nunmatched, ncand;
00524
00525 IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->Aux3Tmr));
00526
00527 nvtxs = graph->nvtxs;
00528 xadj = graph->xadj;
00529 adjncy = graph->adjncy;
00530 cmap = graph->cmap;
00531
00532 nunmatched = *r_nunmatched;
00533 mask = IDX_MAX/maxdegree;
00534
00535
00536
00537 WCOREPUSH;
00538
00539
00540 keys = ikvwspacemalloc(ctrl, nunmatched);
00541 for (ncand=0, pi=0; pi<nvtxs; pi++) {
00542 i = perm[pi];
00543 idegree = xadj[i+1]-xadj[i];
00544 if (match[i] == UNMATCHED && idegree > 1 && idegree < maxdegree) {
00545 for (k=0, j=xadj[i]; j<xadj[i+1]; j++)
00546 k += adjncy[j]%mask;
00547 keys[ncand].val = i;
00548 keys[ncand].key = (k%mask)*maxdegree + idegree;
00549 ncand++;
00550 }
00551 }
00552 ikvsorti(ncand, keys);
00553
00554 mark = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs));
00555 for (pi=0; pi<ncand; pi++) {
00556 i = keys[pi].val;
00557 if (match[i] != UNMATCHED)
00558 continue;
00559
00560 for (j=xadj[i]; j<xadj[i+1]; j++)
00561 mark[adjncy[j]] = i;
00562
00563 for (pk=pi+1; pk<ncand; pk++) {
00564 k = keys[pk].val;
00565 if (match[k] != UNMATCHED)
00566 continue;
00567
00568 if (keys[pi].key != keys[pk].key)
00569 break;
00570 if (xadj[i+1]-xadj[i] != xadj[k+1]-xadj[k])
00571 break;
00572
00573 for (jj=xadj[k]; jj<xadj[k+1]; jj++) {
00574 if (mark[adjncy[jj]] != i)
00575 break;
00576 }
00577 if (jj == xadj[k+1]) {
00578 cmap[i] = cmap[k] = cnvtxs++;
00579 match[i] = k;
00580 match[k] = i;
00581 nunmatched -= 2;
00582 break;
00583 }
00584 }
00585 }
00586 WCOREPOP;
00587
00588
00589
00590 IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->Aux3Tmr));
00591
00592 *r_nunmatched = nunmatched;
00593 return cnvtxs;
00594 }
00595
00596
00597
00600
00601 void PrintCGraphStats(ctrl_t *ctrl, graph_t *graph)
00602 {
00603 idx_t i;
00604
00605 printf("%10"PRIDX" %10"PRIDX" %10"PRIDX" [%"PRIDX"] [",
00606 graph->nvtxs, graph->nedges, isum(graph->nedges, graph->adjwgt, 1), ctrl->CoarsenTo);
00607
00608 for (i=0; i<graph->ncon; i++)
00609 printf(" %8"PRIDX":%8"PRIDX, ctrl->maxvwgt[i], graph->tvwgt[i]);
00610 printf(" ]\n");
00611 }
00612
00613
00614
00620
00621 void CreateCoarseGraph(ctrl_t *ctrl, graph_t *graph, idx_t cnvtxs,
00622 idx_t *match)
00623 {
00624 idx_t j, jj, k, kk, l, m, istart, iend, nvtxs, nedges, ncon, cnedges,
00625 v, u, mask, dovsize;
00626 idx_t *xadj, *vwgt, *vsize, *adjncy, *adjwgt;
00627 idx_t *cmap, *htable;
00628 idx_t *cxadj, *cvwgt, *cvsize, *cadjncy, *cadjwgt;
00629 graph_t *cgraph;
00630
00631 dovsize = (ctrl->objtype == METIS_OBJTYPE_VOL ? 1 : 0);
00632
00633
00634 mask = HTLENGTH;
00635 if (cnvtxs < 2*mask || graph->nedges/graph->nvtxs > mask/20) {
00636 CreateCoarseGraphNoMask(ctrl, graph, cnvtxs, match);
00637 return;
00638 }
00639
00640 nvtxs = graph->nvtxs;
00641 xadj = graph->xadj;
00642 for (v=0; v<nvtxs; v++) {
00643 if (xadj[v+1]-xadj[v] > (mask>>3)) {
00644 CreateCoarseGraphNoMask(ctrl, graph, cnvtxs, match);
00645 return;
00646 }
00647 }
00648
00649
00650 WCOREPUSH;
00651
00652 IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->ContractTmr));
00653
00654 ncon = graph->ncon;
00655 vwgt = graph->vwgt;
00656 vsize = graph->vsize;
00657 adjncy = graph->adjncy;
00658 adjwgt = graph->adjwgt;
00659 cmap = graph->cmap;
00660
00661
00662 cgraph = SetupCoarseGraph(graph, cnvtxs, dovsize);
00663 cxadj = cgraph->xadj;
00664 cvwgt = cgraph->vwgt;
00665 cvsize = cgraph->vsize;
00666 cadjncy = cgraph->adjncy;
00667 cadjwgt = cgraph->adjwgt;
00668
00669 htable = iset(gk_min(cnvtxs+1, mask+1), -1, iwspacemalloc(ctrl, mask+1));
00670
00671 cxadj[0] = cnvtxs = cnedges = 0;
00672 for (v=0; v<nvtxs; v++) {
00673 if ((u = match[v]) < v)
00674 continue;
00675
00676 ASSERT(cmap[v] == cnvtxs);
00677 ASSERT(cmap[match[v]] == cnvtxs);
00678
00679 if (ncon == 1)
00680 cvwgt[cnvtxs] = vwgt[v];
00681 else
00682 icopy(ncon, vwgt+v*ncon, cvwgt+cnvtxs*ncon);
00683
00684 if (dovsize)
00685 cvsize[cnvtxs] = vsize[v];
00686
00687 nedges = 0;
00688
00689 istart = xadj[v];
00690 iend = xadj[v+1];
00691 for (j=istart; j<iend; j++) {
00692 k = cmap[adjncy[j]];
00693 kk = k&mask;
00694 if ((m = htable[kk]) == -1) {
00695 cadjncy[nedges] = k;
00696 cadjwgt[nedges] = adjwgt[j];
00697 htable[kk] = nedges++;
00698 }
00699 else if (cadjncy[m] == k) {
00700 cadjwgt[m] += adjwgt[j];
00701 }
00702 else {
00703 for (jj=0; jj<nedges; jj++) {
00704 if (cadjncy[jj] == k) {
00705 cadjwgt[jj] += adjwgt[j];
00706 break;
00707 }
00708 }
00709 if (jj == nedges) {
00710 cadjncy[nedges] = k;
00711 cadjwgt[nedges++] = adjwgt[j];
00712 }
00713 }
00714 }
00715
00716 if (v != u) {
00717 if (ncon == 1)
00718 cvwgt[cnvtxs] += vwgt[u];
00719 else
00720 iaxpy(ncon, 1, vwgt+u*ncon, 1, cvwgt+cnvtxs*ncon, 1);
00721
00722 if (dovsize)
00723 cvsize[cnvtxs] += vsize[u];
00724
00725 istart = xadj[u];
00726 iend = xadj[u+1];
00727 for (j=istart; j<iend; j++) {
00728 k = cmap[adjncy[j]];
00729 kk = k&mask;
00730 if ((m = htable[kk]) == -1) {
00731 cadjncy[nedges] = k;
00732 cadjwgt[nedges] = adjwgt[j];
00733 htable[kk] = nedges++;
00734 }
00735 else if (cadjncy[m] == k) {
00736 cadjwgt[m] += adjwgt[j];
00737 }
00738 else {
00739 for (jj=0; jj<nedges; jj++) {
00740 if (cadjncy[jj] == k) {
00741 cadjwgt[jj] += adjwgt[j];
00742 break;
00743 }
00744 }
00745 if (jj == nedges) {
00746 cadjncy[nedges] = k;
00747 cadjwgt[nedges++] = adjwgt[j];
00748 }
00749 }
00750 }
00751
00752
00753 jj = htable[cnvtxs&mask];
00754 if (jj >= 0 && cadjncy[jj] != cnvtxs) {
00755 for (jj=0; jj<nedges; jj++) {
00756 if (cadjncy[jj] == cnvtxs)
00757 break;
00758 }
00759 }
00760
00761 if (jj >= 0 && jj < nedges && cadjncy[jj] == cnvtxs) {
00762 cadjncy[jj] = cadjncy[--nedges];
00763 cadjwgt[jj] = cadjwgt[nedges];
00764 }
00765 }
00766
00767
00768 for (j=0; j<nedges; j++)
00769 htable[cadjncy[j]&mask] = -1;
00770 htable[cnvtxs&mask] = -1;
00771
00772 cnedges += nedges;
00773 cxadj[++cnvtxs] = cnedges;
00774 cadjncy += nedges;
00775 cadjwgt += nedges;
00776 }
00777
00778 cgraph->nedges = cnedges;
00779
00780 for (j=0; j<ncon; j++) {
00781 cgraph->tvwgt[j] = isum(cgraph->nvtxs, cgraph->vwgt+j, ncon);
00782 cgraph->invtvwgt[j] = 1.0/(cgraph->tvwgt[j] > 0 ? cgraph->tvwgt[j] : 1);
00783 }
00784
00785
00786 ReAdjustMemory(ctrl, graph, cgraph);
00787
00788 IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->ContractTmr));
00789
00790 WCOREPOP;
00791 }
00792
00793
00794
00799
00800 void CreateCoarseGraphNoMask(ctrl_t *ctrl, graph_t *graph, idx_t cnvtxs,
00801 idx_t *match)
00802 {
00803 idx_t j, k, m, istart, iend, nvtxs, nedges, ncon, cnedges, v, u, dovsize;
00804 idx_t *xadj, *vwgt, *vsize, *adjncy, *adjwgt;
00805 idx_t *cmap, *htable;
00806 idx_t *cxadj, *cvwgt, *cvsize, *cadjncy, *cadjwgt;
00807 graph_t *cgraph;
00808
00809 WCOREPUSH;
00810
00811 dovsize = (ctrl->objtype == METIS_OBJTYPE_VOL ? 1 : 0);
00812
00813 IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->ContractTmr));
00814
00815 nvtxs = graph->nvtxs;
00816 ncon = graph->ncon;
00817 xadj = graph->xadj;
00818 vwgt = graph->vwgt;
00819 vsize = graph->vsize;
00820 adjncy = graph->adjncy;
00821 adjwgt = graph->adjwgt;
00822 cmap = graph->cmap;
00823
00824
00825
00826 cgraph = SetupCoarseGraph(graph, cnvtxs, dovsize);
00827 cxadj = cgraph->xadj;
00828 cvwgt = cgraph->vwgt;
00829 cvsize = cgraph->vsize;
00830 cadjncy = cgraph->adjncy;
00831 cadjwgt = cgraph->adjwgt;
00832
00833 htable = iset(cnvtxs, -1, iwspacemalloc(ctrl, cnvtxs));
00834
00835 cxadj[0] = cnvtxs = cnedges = 0;
00836 for (v=0; v<nvtxs; v++) {
00837 if ((u = match[v]) < v)
00838 continue;
00839
00840 ASSERT(cmap[v] == cnvtxs);
00841 ASSERT(cmap[match[v]] == cnvtxs);
00842
00843 if (ncon == 1)
00844 cvwgt[cnvtxs] = vwgt[v];
00845 else
00846 icopy(ncon, vwgt+v*ncon, cvwgt+cnvtxs*ncon);
00847
00848 if (dovsize)
00849 cvsize[cnvtxs] = vsize[v];
00850
00851 nedges = 0;
00852
00853 istart = xadj[v];
00854 iend = xadj[v+1];
00855 for (j=istart; j<iend; j++) {
00856 k = cmap[adjncy[j]];
00857 if ((m = htable[k]) == -1) {
00858 cadjncy[nedges] = k;
00859 cadjwgt[nedges] = adjwgt[j];
00860 htable[k] = nedges++;
00861 }
00862 else {
00863 cadjwgt[m] += adjwgt[j];
00864 }
00865 }
00866
00867 if (v != u) {
00868 if (ncon == 1)
00869 cvwgt[cnvtxs] += vwgt[u];
00870 else
00871 iaxpy(ncon, 1, vwgt+u*ncon, 1, cvwgt+cnvtxs*ncon, 1);
00872
00873 if (dovsize)
00874 cvsize[cnvtxs] += vsize[u];
00875
00876 istart = xadj[u];
00877 iend = xadj[u+1];
00878 for (j=istart; j<iend; j++) {
00879 k = cmap[adjncy[j]];
00880 if ((m = htable[k]) == -1) {
00881 cadjncy[nedges] = k;
00882 cadjwgt[nedges] = adjwgt[j];
00883 htable[k] = nedges++;
00884 }
00885 else {
00886 cadjwgt[m] += adjwgt[j];
00887 }
00888 }
00889
00890
00891 if ((j = htable[cnvtxs]) != -1) {
00892 ASSERT(cadjncy[j] == cnvtxs);
00893 cadjncy[j] = cadjncy[--nedges];
00894 cadjwgt[j] = cadjwgt[nedges];
00895 htable[cnvtxs] = -1;
00896 }
00897 }
00898
00899
00900 for (j=0; j<nedges; j++)
00901 htable[cadjncy[j]] = -1;
00902
00903 cnedges += nedges;
00904 cxadj[++cnvtxs] = cnedges;
00905 cadjncy += nedges;
00906 cadjwgt += nedges;
00907 }
00908
00909 cgraph->nedges = cnedges;
00910
00911 for (j=0; j<ncon; j++) {
00912 cgraph->tvwgt[j] = isum(cgraph->nvtxs, cgraph->vwgt+j, ncon);
00913 cgraph->invtvwgt[j] = 1.0/(cgraph->tvwgt[j] > 0 ? cgraph->tvwgt[j] : 1);
00914 }
00915
00916 ReAdjustMemory(ctrl, graph, cgraph);
00917
00918 IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->ContractTmr));
00919
00920 WCOREPOP;
00921 }
00922
00923
00924
00931
00932 void CreateCoarseGraphPerm(ctrl_t *ctrl, graph_t *graph, idx_t cnvtxs,
00933 idx_t *match, idx_t *perm)
00934 {
00935 idx_t i, j, jj, k, kk, l, m, istart, iend, nvtxs, nedges, ncon, cnedges,
00936 v, u, mask, dovsize;
00937 idx_t *xadj, *vwgt, *vsize, *adjncy, *adjwgt;
00938 idx_t *cmap, *htable;
00939 idx_t *cxadj, *cvwgt, *cvsize, *cadjncy, *cadjwgt;
00940 graph_t *cgraph;
00941
00942 WCOREPUSH;
00943
00944 IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->ContractTmr));
00945
00946 dovsize = (ctrl->objtype == METIS_OBJTYPE_VOL ? 1 : 0);
00947
00948 mask = HTLENGTH;
00949
00950 nvtxs = graph->nvtxs;
00951 ncon = graph->ncon;
00952 xadj = graph->xadj;
00953 vwgt = graph->vwgt;
00954 vsize = graph->vsize;
00955 adjncy = graph->adjncy;
00956 adjwgt = graph->adjwgt;
00957 cmap = graph->cmap;
00958
00959
00960 cgraph = SetupCoarseGraph(graph, cnvtxs, dovsize);
00961 cxadj = cgraph->xadj;
00962 cvwgt = cgraph->vwgt;
00963 cvsize = cgraph->vsize;
00964 cadjncy = cgraph->adjncy;
00965 cadjwgt = cgraph->adjwgt;
00966
00967 htable = iset(mask+1, -1, iwspacemalloc(ctrl, mask+1));
00968
00969 cxadj[0] = cnvtxs = cnedges = 0;
00970 for (i=0; i<nvtxs; i++) {
00971 v = perm[i];
00972 if (cmap[v] != cnvtxs)
00973 continue;
00974
00975 u = match[v];
00976 if (ncon == 1)
00977 cvwgt[cnvtxs] = vwgt[v];
00978 else
00979 icopy(ncon, vwgt+v*ncon, cvwgt+cnvtxs*ncon);
00980
00981 if (dovsize)
00982 cvsize[cnvtxs] = vsize[v];
00983
00984 nedges = 0;
00985
00986 istart = xadj[v];
00987 iend = xadj[v+1];
00988 for (j=istart; j<iend; j++) {
00989 k = cmap[adjncy[j]];
00990 kk = k&mask;
00991 if ((m = htable[kk]) == -1) {
00992 cadjncy[nedges] = k;
00993 cadjwgt[nedges] = adjwgt[j];
00994 htable[kk] = nedges++;
00995 }
00996 else if (cadjncy[m] == k) {
00997 cadjwgt[m] += adjwgt[j];
00998 }
00999 else {
01000 for (jj=0; jj<nedges; jj++) {
01001 if (cadjncy[jj] == k) {
01002 cadjwgt[jj] += adjwgt[j];
01003 break;
01004 }
01005 }
01006 if (jj == nedges) {
01007 cadjncy[nedges] = k;
01008 cadjwgt[nedges++] = adjwgt[j];
01009 }
01010 }
01011 }
01012
01013 if (v != u) {
01014 if (ncon == 1)
01015 cvwgt[cnvtxs] += vwgt[u];
01016 else
01017 iaxpy(ncon, 1, vwgt+u*ncon, 1, cvwgt+cnvtxs*ncon, 1);
01018
01019 if (dovsize)
01020 cvsize[cnvtxs] += vsize[u];
01021
01022 istart = xadj[u];
01023 iend = xadj[u+1];
01024 for (j=istart; j<iend; j++) {
01025 k = cmap[adjncy[j]];
01026 kk = k&mask;
01027 if ((m = htable[kk]) == -1) {
01028 cadjncy[nedges] = k;
01029 cadjwgt[nedges] = adjwgt[j];
01030 htable[kk] = nedges++;
01031 }
01032 else if (cadjncy[m] == k) {
01033 cadjwgt[m] += adjwgt[j];
01034 }
01035 else {
01036 for (jj=0; jj<nedges; jj++) {
01037 if (cadjncy[jj] == k) {
01038 cadjwgt[jj] += adjwgt[j];
01039 break;
01040 }
01041 }
01042 if (jj == nedges) {
01043 cadjncy[nedges] = k;
01044 cadjwgt[nedges++] = adjwgt[j];
01045 }
01046 }
01047 }
01048
01049
01050 jj = htable[cnvtxs&mask];
01051 if (jj >= 0 && cadjncy[jj] != cnvtxs) {
01052 for (jj=0; jj<nedges; jj++) {
01053 if (cadjncy[jj] == cnvtxs)
01054 break;
01055 }
01056 }
01057 if (jj >= 0 && cadjncy[jj] == cnvtxs) {
01058 cadjncy[jj] = cadjncy[--nedges];
01059 cadjwgt[jj] = cadjwgt[nedges];
01060 }
01061 }
01062
01063 for (j=0; j<nedges; j++)
01064 htable[cadjncy[j]&mask] = -1;
01065 htable[cnvtxs&mask] = -1;
01066
01067 cnedges += nedges;
01068 cxadj[++cnvtxs] = cnedges;
01069 cadjncy += nedges;
01070 cadjwgt += nedges;
01071 }
01072
01073 cgraph->nedges = cnedges;
01074
01075 for (i=0; i<ncon; i++) {
01076 cgraph->tvwgt[i] = isum(cgraph->nvtxs, cgraph->vwgt+i, ncon);
01077 cgraph->invtvwgt[i] = 1.0/(cgraph->tvwgt[i] > 0 ? cgraph->tvwgt[i] : 1);
01078 }
01079
01080
01081 ReAdjustMemory(ctrl, graph, cgraph);
01082
01083 IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->ContractTmr));
01084
01085 WCOREPOP;
01086 }
01087
01088
01089
01092
01093 graph_t *SetupCoarseGraph(graph_t *graph, idx_t cnvtxs, idx_t dovsize)
01094 {
01095 graph_t *cgraph;
01096
01097 cgraph = CreateGraph();
01098
01099 cgraph->nvtxs = cnvtxs;
01100 cgraph->ncon = graph->ncon;
01101
01102 cgraph->finer = graph;
01103 graph->coarser = cgraph;
01104
01105
01106
01107 cgraph->xadj = imalloc(cnvtxs+1, "SetupCoarseGraph: xadj");
01108 cgraph->adjncy = imalloc(graph->nedges, "SetupCoarseGraph: adjncy");
01109 cgraph->adjwgt = imalloc(graph->nedges, "SetupCoarseGraph: adjwgt");
01110 cgraph->vwgt = imalloc(cgraph->ncon*cnvtxs, "SetupCoarseGraph: vwgt");
01111 cgraph->tvwgt = imalloc(cgraph->ncon, "SetupCoarseGraph: tvwgt");
01112 cgraph->invtvwgt = rmalloc(cgraph->ncon, "SetupCoarseGraph: invtvwgt");
01113
01114 if (dovsize)
01115 cgraph->vsize = imalloc(cnvtxs, "SetupCoarseGraph: vsize");
01116
01117 return cgraph;
01118 }
01119
01120
01121
01125
01126 void ReAdjustMemory(ctrl_t *ctrl, graph_t *graph, graph_t *cgraph)
01127 {
01128 if (cgraph->nedges > 10000 && cgraph->nedges < 0.9*graph->nedges) {
01129 cgraph->adjncy = irealloc(cgraph->adjncy, cgraph->nedges, "ReAdjustMemory: adjncy");
01130 cgraph->adjwgt = irealloc(cgraph->adjwgt, cgraph->nedges, "ReAdjustMemory: adjwgt");
01131 }
01132 }