graph_t *CompressGraph(ctrl_t *ctrl, idx_t nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t *cptr, idx_t *cind) { idx_t i, ii, iii, j, jj, k, l, cnvtxs, cnedges; idx_t *cxadj, *cadjncy, *cvwgt, *mark, *map; ikv_t *keys; graph_t *graph=NULL; mark = ismalloc(nvtxs, -1, "CompressGraph: mark"); map = ismalloc(nvtxs, -1, "CompressGraph: map"); keys = ikvmalloc(nvtxs, "CompressGraph: keys"); /* Compute a key for each adjacency list */ for (i=0; i<nvtxs; i++) { k = 0; for (j=xadj[i]; j<xadj[i+1]; j++) k += adjncy[j]; keys[i].key = k+i; /* Add the diagonal entry as well */ keys[i].val = i; } ikvsorti(nvtxs, keys); l = cptr[0] = 0; for (cnvtxs=i=0; i<nvtxs; i++) { ii = keys[i].val; if (map[ii] == -1) { mark[ii] = i; /* Add the diagonal entry */ for (j=xadj[ii]; j<xadj[ii+1]; j++) mark[adjncy[j]] = i; map[ii] = cnvtxs; cind[l++] = ii; for (j=i+1; j<nvtxs; j++) { iii = keys[j].val; if (keys[i].key != keys[j].key || xadj[ii+1]-xadj[ii] != xadj[iii+1]-xadj[iii]) break; /* Break if keys or degrees are different */ if (map[iii] == -1) { /* Do a comparison if iii has not been mapped */ for (jj=xadj[iii]; jj<xadj[iii+1]; jj++) { if (mark[adjncy[jj]] != i) break; } if (jj == xadj[iii+1]) { /* Identical adjacency structure */ map[iii] = cnvtxs; cind[l++] = iii; } } } cptr[++cnvtxs] = l; } } IFSET(ctrl->dbglvl, METIS_DBG_INFO, printf(" Compression: reduction in # of vertices: %"PRIDX".\n", nvtxs-cnvtxs)); if (cnvtxs < COMPRESSION_FRACTION*nvtxs) { /* Sufficient compression is possible, so go ahead and create the compressed graph */ graph = CreateGraph(); cnedges = 0; for (i=0; i<cnvtxs; i++) { ii = cind[cptr[i]]; cnedges += xadj[ii+1]-xadj[ii]; } /* Allocate memory for the compressed graph */ cxadj = graph->xadj = imalloc(cnvtxs+1, "CompressGraph: xadj"); cvwgt = graph->vwgt = ismalloc(cnvtxs, 0, "CompressGraph: vwgt"); cadjncy = graph->adjncy = imalloc(cnedges, "CompressGraph: adjncy"); graph->adjwgt = ismalloc(cnedges, 1, "CompressGraph: adjwgt"); /* Now go and compress the graph */ iset(nvtxs, -1, mark); l = cxadj[0] = 0; for (i=0; i<cnvtxs; i++) { mark[i] = i; /* Remove any dioganal entries in the compressed graph */ for (j=cptr[i]; j<cptr[i+1]; j++) { ii = cind[j]; /* accumulate the vertex weights of the consistuent vertices */ cvwgt[i] += (vwgt == NULL ? 1 : vwgt[ii]); /* generate the combined adjancency list */ for (jj=xadj[ii]; jj<xadj[ii+1]; jj++) { k = map[adjncy[jj]]; if (mark[k] != i) { mark[k] = i; cadjncy[l++] = k; } } } cxadj[i+1] = l; } graph->nvtxs = cnvtxs; graph->nedges = l; graph->ncon = 1; SetupGraph_tvwgt(graph); SetupGraph_label(graph); } gk_free((void **)&keys, &map, &mark, LTERM); return graph; }
void SplitGraphOrder(ctrl_t *ctrl, graph_t *graph, graph_t **r_lgraph, graph_t **r_rgraph) { idx_t i, ii, j, k, l, istart, iend, mypart, nvtxs, snvtxs[3], snedges[3]; idx_t *xadj, *vwgt, *adjncy, *adjwgt, *label, *where, *bndptr, *bndind; idx_t *sxadj[2], *svwgt[2], *sadjncy[2], *sadjwgt[2], *slabel[2]; idx_t *rename; idx_t *auxadjncy; graph_t *lgraph, *rgraph; WCOREPUSH; IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->SplitTmr)); nvtxs = graph->nvtxs; xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; adjwgt = graph->adjwgt; label = graph->label; where = graph->where; bndptr = graph->bndptr; bndind = graph->bndind; ASSERT(bndptr != NULL); rename = iwspacemalloc(ctrl, nvtxs); snvtxs[0] = snvtxs[1] = snvtxs[2] = snedges[0] = snedges[1] = snedges[2] = 0; for (i=0; i<nvtxs; i++) { k = where[i]; rename[i] = snvtxs[k]++; snedges[k] += xadj[i+1]-xadj[i]; } lgraph = SetupSplitGraph(graph, snvtxs[0], snedges[0]); sxadj[0] = lgraph->xadj; svwgt[0] = lgraph->vwgt; sadjncy[0] = lgraph->adjncy; sadjwgt[0] = lgraph->adjwgt; slabel[0] = lgraph->label; rgraph = SetupSplitGraph(graph, snvtxs[1], snedges[1]); sxadj[1] = rgraph->xadj; svwgt[1] = rgraph->vwgt; sadjncy[1] = rgraph->adjncy; sadjwgt[1] = rgraph->adjwgt; slabel[1] = rgraph->label; /* Go and use bndptr to also mark the boundary nodes in the two partitions */ for (ii=0; ii<graph->nbnd; ii++) { i = bndind[ii]; for (j=xadj[i]; j<xadj[i+1]; j++) bndptr[adjncy[j]] = 1; } snvtxs[0] = snvtxs[1] = snedges[0] = snedges[1] = 0; sxadj[0][0] = sxadj[1][0] = 0; for (i=0; i<nvtxs; i++) { if ((mypart = where[i]) == 2) continue; istart = xadj[i]; iend = xadj[i+1]; if (bndptr[i] == -1) { /* This is an interior vertex */ auxadjncy = sadjncy[mypart] + snedges[mypart] - istart; for(j=istart; j<iend; j++) auxadjncy[j] = adjncy[j]; snedges[mypart] += iend-istart; } else { auxadjncy = sadjncy[mypart]; l = snedges[mypart]; for (j=istart; j<iend; j++) { k = adjncy[j]; if (where[k] == mypart) auxadjncy[l++] = k; } snedges[mypart] = l; } svwgt[mypart][snvtxs[mypart]] = vwgt[i]; slabel[mypart][snvtxs[mypart]] = label[i]; sxadj[mypart][++snvtxs[mypart]] = snedges[mypart]; } for (mypart=0; mypart<2; mypart++) { iend = snedges[mypart]; iset(iend, 1, sadjwgt[mypart]); auxadjncy = sadjncy[mypart]; for (i=0; i<iend; i++) auxadjncy[i] = rename[auxadjncy[i]]; } lgraph->nvtxs = snvtxs[0]; lgraph->nedges = snedges[0]; rgraph->nvtxs = snvtxs[1]; rgraph->nedges = snedges[1]; SetupGraph_tvwgt(lgraph); SetupGraph_tvwgt(rgraph); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->SplitTmr)); *r_lgraph = lgraph; *r_rgraph = rgraph; WCOREPOP; }
graph_t *PruneGraph(ctrl_t *ctrl, idx_t nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t *iperm, real_t factor) { idx_t i, j, k, l, nlarge, pnvtxs, pnedges; idx_t *pxadj, *padjncy, *pvwgt; idx_t *perm; graph_t *graph=NULL; perm = imalloc(nvtxs, "PruneGraph: perm"); factor = factor*xadj[nvtxs]/nvtxs; pnvtxs = pnedges = nlarge = 0; for (i=0; i<nvtxs; i++) { if (xadj[i+1]-xadj[i] < factor) { perm[i] = pnvtxs; iperm[pnvtxs++] = i; pnedges += xadj[i+1]-xadj[i]; } else { perm[i] = nvtxs - ++nlarge; iperm[nvtxs-nlarge] = i; } } IFSET(ctrl->dbglvl, METIS_DBG_INFO, printf(" Pruned %"PRIDX" of %"PRIDX" vertices.\n", nlarge, nvtxs)); if (nlarge > 0 && nlarge < nvtxs) { /* Prunning is possible, so go ahead and create the prunned graph */ graph = CreateGraph(); /* Allocate memory for the prunned graph*/ pxadj = graph->xadj = imalloc(pnvtxs+1, "PruneGraph: xadj"); pvwgt = graph->vwgt = imalloc(pnvtxs, "PruneGraph: vwgt"); padjncy = graph->adjncy = imalloc(pnedges, "PruneGraph: adjncy"); graph->adjwgt = ismalloc(pnedges, 1, "PruneGraph: adjwgt"); pxadj[0] = pnedges = l = 0; for (i=0; i<nvtxs; i++) { if (xadj[i+1]-xadj[i] < factor) { pvwgt[l] = (vwgt == NULL ? 1 : vwgt[i]); for (j=xadj[i]; j<xadj[i+1]; j++) { k = perm[adjncy[j]]; if (k < pnvtxs) padjncy[pnedges++] = k; } pxadj[++l] = pnedges; } } graph->nvtxs = pnvtxs; graph->nedges = pnedges; graph->ncon = 1; SetupGraph_tvwgt(graph); SetupGraph_label(graph); } else if (nlarge > 0 && nlarge == nvtxs) { IFSET(ctrl->dbglvl, METIS_DBG_INFO, printf(" Pruning is ignored as it removes all vertices.\n")); nlarge = 0; } gk_free((void **)&perm, LTERM); return graph; }