/************************************************************************* * This function finds a matching using the HEM heuristic **************************************************************************/ void Match_HEM(CtrlType *ctrl, GraphType *graph) { int i, ii, j, k, nvtxs, cnvtxs, maxidx, dim; idxtype *xadj, *vwgt, *adjncy; idxtype *match, *cmap, *perm, *tperm; realtype curwgt, maxwgt; realtype *vvol, *vsurf, *adjwgt, *adjwgtsum; dim = ctrl->dim; nvtxs = graph->nvtxs; xadj = graph->xadj; vwgt = graph->vwgt; vvol = graph->vvol; vsurf = graph->vsurf; adjncy = graph->adjncy; adjwgt = graph->adjwgt; adjwgtsum = graph->adjwgtsum; cmap = graph->cmap = idxsmalloc(nvtxs, -1, "cmap"); match = idxsmalloc(nvtxs, -1, "match"); perm = idxmalloc(nvtxs, "perm"); tperm = idxmalloc(nvtxs, "tperm"); RandomPermute(nvtxs, tperm, 1); BucketSortKeysInc(nvtxs, vwgt[iamax(nvtxs, vwgt)], vwgt, tperm, perm); /* RandomPermute(nvtxs, perm, 1); */ cnvtxs = 0; /* Compute a heavy-edge style matching giving preferance to small vertices */ for (ii=0; ii<nvtxs; ii++) { i = perm[ii]; if (match[i] == UNMATCHED) { maxidx = i; maxwgt = 0.0; /* Find a heavy-edge matching, subject to maxvwgt constraints */ for (j=xadj[i]; j<xadj[i+1]; j++) { k = adjncy[j]; curwgt = 1.0/ARATIO2(dim, vsurf[i]+vsurf[k]+adjwgtsum[i]+adjwgtsum[k]- 2.0*adjwgt[j], vvol[i]+vvol[k]); if (match[k] == UNMATCHED && vwgt[i]+vwgt[k] <= ctrl->maxsize && curwgt > maxwgt) { maxwgt = curwgt; maxidx = k; } } cmap[i] = cmap[maxidx] = cnvtxs++; match[i] = maxidx; match[maxidx] = i; } } CreateCoarseGraph(graph, cnvtxs, match, perm); IMfree((void**)&tperm, &perm, &match, LTERM); }
void GrowKWayPartitioning(ctrl_t *ctrl, graph_t *graph) { idx_t v, i, ii, j, nvtxs, nparts, nmis, minvwgt; idx_t *xadj, *adjncy, *vwgt, *adjwgt; idx_t *where, *pwgts, *minwgt, *maxwgt, *nbrwgt; idx_t *perm; real_t ubfactor_original; WCOREPUSH; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; adjwgt = graph->adjwgt; vwgt = graph->vwgt; where = graph->where; pwgts = graph->pwgts; nparts = ctrl->nparts; /* setup the weight intervals of the various subdomains */ minwgt = iwspacemalloc(ctrl, nparts); maxwgt = iwspacemalloc(ctrl, nparts); for (i=0; i<nparts; i++) { maxwgt[i] = ctrl->tpwgts[i]*graph->tvwgt[0]*ctrl->ubfactors[0]; minwgt[i] = ctrl->tpwgts[i]*graph->tvwgt[0]*(1.0/ctrl->ubfactors[0]); } /* setup the initial state of the partitioning */ iset(nvtxs, nparts, where); iset(nparts, 0, pwgts); perm = iwspacemalloc(ctrl, nvtxs); /* compute the weights of the neighborhood */ nbrwgt = iwspacemalloc(ctrl, nvtxs); /* for (i=0; i<nvtxs; i++) { nbrwgt[i] = vwgt[i]; for (j=xadj[i]; j<xadj[i+1]; j++) { ii = adjncy[j]; nbrwgt[i] += vwgt[ii]/log2(2+xadj[ii+1]-xadj[ii]); } } */ for (i=0; i<nvtxs; i++) { nbrwgt[i] = 0; for (j=xadj[i]; j<xadj[i+1]; j++) nbrwgt[i] += adjwgt[j]; } minvwgt = isum(nvtxs, nbrwgt, 1)/nvtxs; #ifdef XXX perm = iwspacemalloc(ctrl, nvtxs); tperm = iwspacemalloc(ctrl, nvtxs); degrees = iwspacemalloc(ctrl, nvtxs); irandArrayPermute(nvtxs, tperm, nvtxs, 1); irandArrayPermute(nvtxs, tperm, nvtxs, 0); avgdegree = 1.0*(xadj[nvtxs]/nvtxs); for (i=0; i<nvtxs; i++) { bnum = sqrt(1+xadj[i+1]-xadj[i]); degrees[i] = (bnum > avgdegree ? avgdegree : bnum); } BucketSortKeysInc(ctrl, nvtxs, avgdegree, degrees, tperm, perm); #endif ubfactor_original = ctrl->ubfactors[0]; ctrl->ubfactors[0] = 1.05*ubfactor_original; /* find an MIS of vertices by randomly traversing the vertices and assign them to the different partitions */ irandArrayPermute(nvtxs, perm, nvtxs, 1); for (nmis=0, ii=0; ii<nvtxs; ii++) { i=perm[ii]; if (nbrwgt[i] < minvwgt) continue; if (where[i] == nparts) { pwgts[nmis] = vwgt[i]; where[i] = nmis++; /* mark first level neighbors */ for (j=xadj[i]; j<xadj[i+1]; j++) { v = adjncy[j]; if (where[v] == nparts) where[v] = nparts+1; } } if (nmis == nparts) break; } printf(" nvtxs: %"PRIDX", nmis: %"PRIDX", minvwgt: %"PRIDX", ii: %"PRIDX"\n", nvtxs, nmis, minvwgt, ii); /* if the size of the MIS is not sufficiently large, go and find some additional seeds */ if (nmis < nparts) { minvwgt = .75*minvwgt; irandArrayPermute(nvtxs, perm, nvtxs, 0); for (ii=0; ii<nvtxs; ii++) { i=perm[ii]; if (nbrwgt[i] < minvwgt) continue; if (where[i] == nparts) { pwgts[nmis] = vwgt[i]; where[i] = nmis++; /* mark first level neighbors */ for (j=xadj[i]; j<xadj[i+1]; j++) { v = adjncy[j]; if (where[v] == nparts) where[v] = nparts+1; } } if (nmis == nparts) break; } printf(" nvtxs: %"PRIDX", nmis: %"PRIDX"\n", nvtxs, nmis); } /* if the size of the MIS is not sufficiently large, go and find some additional seeds */ if (nmis < nparts) { irandArrayPermute(nvtxs, perm, nvtxs, 0); for (ii=0; ii<nvtxs; ii++) { i = perm[ii]; if (where[i] == nparts+1) { pwgts[nmis] = vwgt[i]; where[i] = nmis++; } if (nmis == nparts) break; } printf(" nvtxs: %"PRIDX", nmis: %"PRIDX"\n", nvtxs, nmis); } /* set all unassigned vertices to 'nparts' */ for (i=0; i<nvtxs; i++) { if (where[i] >= nparts) where[i] = nparts; } WCOREPOP; /* refine the partition */ ComputeKWayPartitionParams(ctrl, graph); if (ctrl->minconn) EliminateSubDomainEdges(ctrl, graph); for (i=0; i<4; i++) { ComputeKWayBoundary(ctrl, graph, BNDTYPE_BALANCE); Greedy_KWayOptimize(ctrl, graph, 10, 0, OMODE_BALANCE); /* for (k=0; k<nparts; k++) printf("%"PRIDX"\n", graph->pwgts[k]); exit(0); */ ComputeKWayBoundary(ctrl, graph, BNDTYPE_REFINE); Greedy_KWayOptimize(ctrl, graph, ctrl->niter, 1, OMODE_REFINE); Greedy_KWayEdgeCutOptimize(ctrl, graph, ctrl->niter); } ctrl->ubfactors[0] = ubfactor_original; }
/************************************************************************* * This function finds a matching using the HEM heuristic **************************************************************************/ void Match_SHEM(CtrlType *ctrl, GraphType *graph) { int i, ii, j, k, nvtxs, cnvtxs, maxidx, maxwgt, avgdegree; idxtype *xadj, *vwgt, *adjncy, *adjwgt; idxtype *match, *cmap, *degrees, *perm, *tperm; IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->MatchTmr)); nvtxs = graph->nvtxs; xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; adjwgt = graph->adjwgt; cmap = graph->cmap; match = idxset(nvtxs, UNMATCHED, idxwspacemalloc(ctrl, nvtxs)); perm = idxwspacemalloc(ctrl, nvtxs); tperm = idxwspacemalloc(ctrl, nvtxs); degrees = idxwspacemalloc(ctrl, nvtxs); RandomPermute(nvtxs, tperm, 1); avgdegree = 0.7*(xadj[nvtxs]/nvtxs); for (i=0; i<nvtxs; i++) degrees[i] = (xadj[i+1]-xadj[i] > avgdegree ? avgdegree : xadj[i+1]-xadj[i]); BucketSortKeysInc(nvtxs, avgdegree, degrees, tperm, perm); cnvtxs = 0; /* Take care any islands. Islands are matched with non-islands due to coarsening */ for (ii=0; ii<nvtxs; ii++) { i = perm[ii]; if (match[i] == UNMATCHED) { /* Unmatched */ if (xadj[i] < xadj[i+1]) break; maxidx = i; for (j=nvtxs-1; j>ii; j--) { k = perm[j]; if (match[k] == UNMATCHED && xadj[k] < xadj[k+1]) { maxidx = k; break; } } cmap[i] = cmap[maxidx] = cnvtxs++; match[i] = maxidx; match[maxidx] = i; } } /* Continue with normal matching */ for (; ii<nvtxs; ii++) { i = perm[ii]; if (match[i] == UNMATCHED) { /* Unmatched */ maxidx = i; maxwgt = 0; /* Find a heavy-edge matching, subject to maxvwgt constraints */ for (j=xadj[i]; j<xadj[i+1]; j++) { if (match[adjncy[j]] == UNMATCHED && maxwgt < adjwgt[j] && vwgt[i]+vwgt[adjncy[j]] <= ctrl->maxvwgt) { maxwgt = adjwgt[j]; maxidx = adjncy[j]; } } cmap[i] = cmap[maxidx] = cnvtxs++; match[i] = maxidx; match[maxidx] = i; } } IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->MatchTmr)); idxwspacefree(ctrl, nvtxs); /* degrees */ idxwspacefree(ctrl, nvtxs); /* tperm */ CreateCoarseGraph(ctrl, graph, cnvtxs, match, perm); idxwspacefree(ctrl, nvtxs); idxwspacefree(ctrl, nvtxs); }
/************************************************************************* * This function finds a matching using the HEM heuristic **************************************************************************/ void MCMatch_SBHEM(CtrlType *ctrl, GraphType *graph, int norm) { int i, ii, j, k, nvtxs, cnvtxs, ncon, maxidx, maxwgt, avgdegree; idxtype *xadj, *adjncy, *adjwgt; idxtype *match, *cmap, *degrees, *perm, *tperm; float *nvwgt, vbal; IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->MatchTmr)); nvtxs = graph->nvtxs; ncon = graph->ncon; xadj = graph->xadj; nvwgt = graph->nvwgt; adjncy = graph->adjncy; adjwgt = graph->adjwgt; cmap = graph->cmap; match = idxset(nvtxs, UNMATCHED, idxwspacemalloc(ctrl, nvtxs)); perm = idxwspacemalloc(ctrl, nvtxs); tperm = idxwspacemalloc(ctrl, nvtxs); degrees = idxwspacemalloc(ctrl, nvtxs); RandomPermute(nvtxs, tperm, 1); avgdegree = (int)(0.7*(xadj[nvtxs]/nvtxs)); for (i=0; i<nvtxs; i++) degrees[i] = (xadj[i+1]-xadj[i] > avgdegree ? avgdegree : xadj[i+1]-xadj[i]); BucketSortKeysInc(nvtxs, avgdegree, degrees, tperm, perm); cnvtxs = 0; /* Take care any islands. Islands are matched with non-islands due to coarsening */ for (ii=0; ii<nvtxs; ii++) { i = perm[ii]; if (match[i] == UNMATCHED) { /* Unmatched */ if (xadj[i] < xadj[i+1]) break; maxidx = i; for (j=nvtxs-1; j>ii; j--) { k = perm[j]; if (match[k] == UNMATCHED && xadj[k] < xadj[k+1]) { maxidx = k; break; } } cmap[i] = cmap[maxidx] = cnvtxs++; match[i] = maxidx; match[maxidx] = i; } } /* Continue with normal matching */ for (; ii<nvtxs; ii++) { i = perm[ii]; if (match[i] == UNMATCHED) { /* Unmatched */ maxidx = i; maxwgt = -1; vbal = 0.0; /* Find a heavy-edge matching, subject to maxvwgt constraints */ for (j=xadj[i]; j<xadj[i+1]; j++) { k = adjncy[j]; if (match[k] == UNMATCHED && AreAllVwgtsBelowFast(ncon, nvwgt+i*ncon, nvwgt+k*ncon, ctrl->nmaxvwgt)) { if (maxidx != i) vbal = BetterVBalance(ncon, norm, nvwgt+i*ncon, nvwgt+maxidx*ncon, nvwgt+k*ncon); if (vbal > 0 || (vbal > -.01 && maxwgt < adjwgt[j])) { maxwgt = adjwgt[j]; maxidx = k; } } } cmap[i] = cmap[maxidx] = cnvtxs++; match[i] = maxidx; match[maxidx] = i; } } IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->MatchTmr)); idxwspacefree(ctrl, nvtxs); /* degrees */ idxwspacefree(ctrl, nvtxs); /* tperm */ CreateCoarseGraph(ctrl, graph, cnvtxs, match, perm); idxwspacefree(ctrl, nvtxs); idxwspacefree(ctrl, nvtxs); }