void ProjectKWayPartition(ctrl_t *ctrl, graph_t *graph) { idx_t i, j, k, nvtxs, nbnd, nparts, me, other, istart, iend, tid, ted; idx_t *xadj, *adjncy, *adjwgt; idx_t *cmap, *where, *bndptr, *bndind, *cwhere, *htable; graph_t *cgraph; WCOREPUSH; nparts = ctrl->nparts; cgraph = graph->coarser; cwhere = cgraph->where; nvtxs = graph->nvtxs; cmap = graph->cmap; xadj = graph->xadj; adjncy = graph->adjncy; adjwgt = graph->adjwgt; AllocateKWayPartitionMemory(ctrl, graph); where = graph->where; bndind = graph->bndind; bndptr = iset(nvtxs, -1, graph->bndptr); htable = iset(nparts, -1, iwspacemalloc(ctrl, nparts)); /* Compute the required info for refinement */ switch (ctrl->objtype) { case METIS_OBJTYPE_CUT: ASSERT(CheckBnd2(cgraph)); { ckrinfo_t *myrinfo; cnbr_t *mynbrs; /* go through and project partition and compute id/ed for the nodes */ for (i=0; i<nvtxs; i++) { k = cmap[i]; where[i] = cwhere[k]; cmap[i] = cgraph->ckrinfo[k].ed; /* For optimization */ } memset(graph->ckrinfo, 0, sizeof(ckrinfo_t)*nvtxs); cnbrpoolReset(ctrl); for (nbnd=0, i=0; i<nvtxs; i++) { istart = xadj[i]; iend = xadj[i+1]; myrinfo = graph->ckrinfo+i; if (cmap[i] == 0) { /* Interior node. Note that cmap[i] = crinfo[cmap[i]].ed */ for (tid=0, j=istart; j<iend; j++) tid += adjwgt[j]; myrinfo->id = tid; myrinfo->inbr = -1; } else { /* Potentially an interface node */ myrinfo->inbr = cnbrpoolGetNext(ctrl, iend-istart+1); mynbrs = ctrl->cnbrpool + myrinfo->inbr; me = where[i]; for (tid=0, ted=0, j=istart; j<iend; j++) { other = where[adjncy[j]]; if (me == other) { tid += adjwgt[j]; } else { ted += adjwgt[j]; if ((k = htable[other]) == -1) { htable[other] = myrinfo->nnbrs; mynbrs[myrinfo->nnbrs].pid = other; mynbrs[myrinfo->nnbrs++].ed = adjwgt[j]; } else { mynbrs[k].ed += adjwgt[j]; } } } myrinfo->id = tid; myrinfo->ed = ted; /* Remove space for edegrees if it was interior */ if (ted == 0) { ctrl->nbrpoolcpos -= iend-istart+1; myrinfo->inbr = -1; } else { if (ted-tid >= 0) BNDInsert(nbnd, bndind, bndptr, i); for (j=0; j<myrinfo->nnbrs; j++) htable[mynbrs[j].pid] = -1; } } } graph->nbnd = nbnd; } ASSERT(CheckBnd2(graph)); break; case METIS_OBJTYPE_VOL: { vkrinfo_t *myrinfo; vnbr_t *mynbrs; ASSERT(cgraph->minvol == ComputeVolume(cgraph, cgraph->where)); /* go through and project partition and compute id/ed for the nodes */ for (i=0; i<nvtxs; i++) { k = cmap[i]; where[i] = cwhere[k]; cmap[i] = cgraph->vkrinfo[k].ned; /* For optimization */ } memset(graph->vkrinfo, 0, sizeof(vkrinfo_t)*nvtxs); vnbrpoolReset(ctrl); for (i=0; i<nvtxs; i++) { istart = xadj[i]; iend = xadj[i+1]; myrinfo = graph->vkrinfo+i; if (cmap[i] == 0) { /* Note that cmap[i] = crinfo[cmap[i]].ed */ myrinfo->nid = iend-istart; myrinfo->inbr = -1; } else { /* Potentially an interface node */ myrinfo->inbr = vnbrpoolGetNext(ctrl, iend-istart+1); mynbrs = ctrl->vnbrpool + myrinfo->inbr; me = where[i]; for (tid=0, ted=0, j=istart; j<iend; j++) { other = where[adjncy[j]]; if (me == other) { tid++; } else { ted++; if ((k = htable[other]) == -1) { htable[other] = myrinfo->nnbrs; mynbrs[myrinfo->nnbrs].gv = 0; mynbrs[myrinfo->nnbrs].pid = other; mynbrs[myrinfo->nnbrs++].ned = 1; } else { mynbrs[k].ned++; } } } myrinfo->nid = tid; myrinfo->ned = ted; /* Remove space for edegrees if it was interior */ if (ted == 0) { ctrl->nbrpoolcpos -= iend-istart+1; myrinfo->inbr = -1; } else { for (j=0; j<myrinfo->nnbrs; j++) htable[mynbrs[j].pid] = -1; } } } ComputeKWayVolGains(ctrl, graph); ASSERT(graph->minvol == ComputeVolume(graph, graph->where)); } break; default: gk_errexit(SIGERR, "Unknown objtype of %d\n", ctrl->objtype); } graph->mincut = cgraph->mincut; icopy(nparts*graph->ncon, cgraph->pwgts, graph->pwgts); FreeGraph(&graph->coarser); graph->coarser = NULL; WCOREPOP; }
void MoveGroupContigForCut(ctrl_t *ctrl, graph_t *graph, idx_t to, idx_t gid, idx_t *ptr, idx_t *ind) { idx_t i, ii, iii, j, jj, k, l, nvtxs, nbnd, from, me; idx_t *xadj, *adjncy, *adjwgt, *where, *bndptr, *bndind; ckrinfo_t *myrinfo; cnbr_t *mynbrs; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; adjwgt = graph->adjwgt; where = graph->where; bndptr = graph->bndptr; bndind = graph->bndind; nbnd = graph->nbnd; for (iii = ptr[gid]; iii < ptr[gid + 1]; iii++) { i = ind[iii]; from = where[i]; myrinfo = graph->ckrinfo + i; if (myrinfo->inbr == -1) { myrinfo->inbr = cnbrpoolGetNext(ctrl, xadj[i + 1] - xadj[i] + 1); myrinfo->nnbrs = 0; } mynbrs = ctrl->cnbrpool + myrinfo->inbr; /* find the location of 'to' in myrinfo or create it if it is not there */ for (k = 0; k < myrinfo->nnbrs; k++) { if (mynbrs[k].pid == to) { break; } } if (k == myrinfo->nnbrs) { mynbrs[k].pid = to; mynbrs[k].ed = 0; myrinfo->nnbrs++; } graph->mincut -= mynbrs[k].ed - myrinfo->id; /* Update ID/ED and BND related information for the moved vertex */ iaxpy(graph->ncon, 1, graph->vwgt + i * graph->ncon, 1, graph->pwgts + to * graph->ncon, 1); iaxpy(graph->ncon, -1, graph->vwgt + i * graph->ncon, 1, graph->pwgts + from * graph->ncon, 1); UpdateMovedVertexInfoAndBND(i, from, k, to, myrinfo, mynbrs, where, nbnd, bndptr, bndind, BNDTYPE_REFINE); /* Update the degrees of adjacent vertices */ for (j = xadj[i]; j < xadj[i + 1]; j++) { ii = adjncy[j]; me = where[ii]; myrinfo = graph->ckrinfo + ii; UpdateAdjacentVertexInfoAndBND(ctrl, ii, xadj[ii + 1] - xadj[ii], me, from, to, myrinfo, adjwgt[j], nbnd, bndptr, bndind, BNDTYPE_REFINE); } ASSERT(CheckRInfo(ctrl, graph->ckrinfo + i)); } graph->nbnd = nbnd; }
void ComputeKWayPartitionParams(ctrl_t *ctrl, graph_t *graph) { idx_t i, j, k, l, nvtxs, ncon, nparts, nbnd, mincut, me, other; idx_t *xadj, *vwgt, *adjncy, *adjwgt, *pwgts, *where, *bndind, *bndptr; nparts = ctrl->nparts; nvtxs = graph->nvtxs; ncon = graph->ncon; xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; adjwgt = graph->adjwgt; where = graph->where; pwgts = iset(nparts*ncon, 0, graph->pwgts); bndind = graph->bndind; bndptr = iset(nvtxs, -1, graph->bndptr); nbnd = mincut = 0; /* Compute pwgts */ if (ncon == 1) { for (i=0; i<nvtxs; i++) { ASSERT(where[i] >= 0 && where[i] < nparts); pwgts[where[i]] += vwgt[i]; } } else { for (i=0; i<nvtxs; i++) { me = where[i]; for (j=0; j<ncon; j++) pwgts[me*ncon+j] += vwgt[i*ncon+j]; } } /* Compute the required info for refinement */ switch (ctrl->objtype) { case METIS_OBJTYPE_CUT: { ckrinfo_t *myrinfo; cnbr_t *mynbrs; memset(graph->ckrinfo, 0, sizeof(ckrinfo_t)*nvtxs); cnbrpoolReset(ctrl); for (i=0; i<nvtxs; i++) { me = where[i]; myrinfo = graph->ckrinfo+i; for (j=xadj[i]; j<xadj[i+1]; j++) { if (me == where[adjncy[j]]) myrinfo->id += adjwgt[j]; else myrinfo->ed += adjwgt[j]; } /* Time to compute the particular external degrees */ if (myrinfo->ed > 0) { mincut += myrinfo->ed; myrinfo->inbr = cnbrpoolGetNext(ctrl, xadj[i+1]-xadj[i]+1); mynbrs = ctrl->cnbrpool + myrinfo->inbr; for (j=xadj[i]; j<xadj[i+1]; j++) { other = where[adjncy[j]]; if (me != other) { for (k=0; k<myrinfo->nnbrs; k++) { if (mynbrs[k].pid == other) { mynbrs[k].ed += adjwgt[j]; break; } } if (k == myrinfo->nnbrs) { mynbrs[k].pid = other; mynbrs[k].ed = adjwgt[j]; myrinfo->nnbrs++; } } } ASSERT(myrinfo->nnbrs <= xadj[i+1]-xadj[i]); /* Only ed-id>=0 nodes are considered to be in the boundary */ if (myrinfo->ed-myrinfo->id >= 0) BNDInsert(nbnd, bndind, bndptr, i); } else { myrinfo->inbr = -1; } } graph->mincut = mincut/2; graph->nbnd = nbnd; } ASSERT(CheckBnd2(graph)); break; case METIS_OBJTYPE_VOL: { vkrinfo_t *myrinfo; vnbr_t *mynbrs; memset(graph->vkrinfo, 0, sizeof(vkrinfo_t)*nvtxs); vnbrpoolReset(ctrl); /* Compute now the id/ed degrees */ for (i=0; i<nvtxs; i++) { me = where[i]; myrinfo = graph->vkrinfo+i; for (j=xadj[i]; j<xadj[i+1]; j++) { if (me == where[adjncy[j]]) myrinfo->nid++; else myrinfo->ned++; } /* Time to compute the particular external degrees */ if (myrinfo->ned > 0) { mincut += myrinfo->ned; myrinfo->inbr = vnbrpoolGetNext(ctrl, xadj[i+1]-xadj[i]+1); mynbrs = ctrl->vnbrpool + myrinfo->inbr; for (j=xadj[i]; j<xadj[i+1]; j++) { other = where[adjncy[j]]; if (me != other) { for (k=0; k<myrinfo->nnbrs; k++) { if (mynbrs[k].pid == other) { mynbrs[k].ned++; break; } } if (k == myrinfo->nnbrs) { mynbrs[k].gv = 0; mynbrs[k].pid = other; mynbrs[k].ned = 1; myrinfo->nnbrs++; } } } ASSERT(myrinfo->nnbrs <= xadj[i+1]-xadj[i]); } else { myrinfo->inbr = -1; } } graph->mincut = mincut/2; ComputeKWayVolGains(ctrl, graph); } ASSERT(graph->minvol == ComputeVolume(graph, graph->where)); break; default: gk_errexit(SIGERR, "Unknown objtype of %d\n", ctrl->objtype); } }
void MoveGroupMinConnForCut(ctrl_t *ctrl, graph_t *graph, idx_t to, idx_t nind, idx_t *ind) { idx_t i, ii, j, jj, k, l, nvtxs, nbnd, from, me; idx_t *xadj, *adjncy, *adjwgt, *where, *bndptr, *bndind; ckrinfo_t *myrinfo; cnbr_t *mynbrs; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; adjwgt = graph->adjwgt; where = graph->where; bndptr = graph->bndptr; bndind = graph->bndind; nbnd = graph->nbnd; while (--nind>=0) { i = ind[nind]; from = where[i]; myrinfo = graph->ckrinfo+i; if (myrinfo->inbr == -1) { myrinfo->inbr = cnbrpoolGetNext(ctrl, xadj[i+1]-xadj[i]+1); myrinfo->nnbrs = 0; } mynbrs = ctrl->cnbrpool + myrinfo->inbr; /* find the location of 'to' in myrinfo or create it if it is not there */ for (k=0; k<myrinfo->nnbrs; k++) { if (mynbrs[k].pid == to) break; } if (k == myrinfo->nnbrs) { ASSERT(k < xadj[i+1]-xadj[i]); mynbrs[k].pid = to; mynbrs[k].ed = 0; myrinfo->nnbrs++; } /* Update pwgts */ iaxpy(graph->ncon, 1, graph->vwgt+i*graph->ncon, 1, graph->pwgts+to*graph->ncon, 1); iaxpy(graph->ncon, -1, graph->vwgt+i*graph->ncon, 1, graph->pwgts+from*graph->ncon, 1); /* Update mincut */ graph->mincut -= mynbrs[k].ed-myrinfo->id; /* Update subdomain connectivity graph to reflect the move of 'i' */ UpdateEdgeSubDomainGraph(ctrl, from, to, myrinfo->id-mynbrs[k].ed, NULL); /* Update ID/ED and BND related information for the moved vertex */ UpdateMovedVertexInfoAndBND(i, from, k, to, myrinfo, mynbrs, where, nbnd, bndptr, bndind, BNDTYPE_REFINE); /* Update the degrees of adjacent vertices */ for (j=xadj[i]; j<xadj[i+1]; j++) { ii = adjncy[j]; me = where[ii]; myrinfo = graph->ckrinfo+ii; UpdateAdjacentVertexInfoAndBND(ctrl, ii, xadj[ii+1]-xadj[ii], me, from, to, myrinfo, adjwgt[j], nbnd, bndptr, bndind, BNDTYPE_REFINE); /* Update subdomain graph to reflect the move of 'i' for domains other than 'from' and 'to' */ if (me != from && me != to) { UpdateEdgeSubDomainGraph(ctrl, from, me, -adjwgt[j], NULL); UpdateEdgeSubDomainGraph(ctrl, to, me, adjwgt[j], NULL); } } } ASSERT(ComputeCut(graph, where) == graph->mincut); graph->nbnd = nbnd; }