void TTetrahedron::SetPoints(const TPoint& P1, const TPoint& P2, const TPoint& P3, const TPoint& P4) { X1 = P1; X2 = P2; X3 = P3; X4 = P4; T1.SetPoints(P2, P3, P4); T2.SetPoints(P1, P3, P4); T3.SetPoints(P1, P2, P4); T4.SetPoints(P1, P2, P3); A1->SetPoints(P1, P2); A2->SetPoints(P2, P3); A3->SetPoints(P3, P1); A4->SetPoints(P1, P4); A5->SetPoints(P2, P4); A6->SetPoints(P3, P4); ComputeVolume(); }
TTetrahedron::TTetrahedron(const TPoint& X1, const TPoint& X2, const TPoint& X3, const TPoint& X4) { id = generateId(); this->X1 = X1; this->X2 = X2; this->X3 = X3; this->X4 = X4; T1.SetPoints(X2, X3, X4); T2.SetPoints(X1, X3, X4); T3.SetPoints(X1, X2, X4); T4.SetPoints(X1, X2, X3); A1 = new TAbscissa(X1, X2); A2 = new TAbscissa(X2, X3); A3 = new TAbscissa(X3, X1); A4 = new TAbscissa(X1, X4); A5 = new TAbscissa(X2, X4); A6 = new TAbscissa(X3, X4); ComputeVolume(); }
/************************************************************************* * This function performs k-way refinement **************************************************************************/ void Random_KWayEdgeRefineMConn(CtrlType *ctrl, GraphType *graph, int nparts, float *tpwgts, float ubfactor, int npasses, int ffactor) { int i, ii, iii, j, jj, k, l, pass, nvtxs, nmoves, nbnd, tvwgt, myndegrees; int from, me, to, oldcut, vwgt, gain; int maxndoms, nadd; idxtype *xadj, *adjncy, *adjwgt; idxtype *where, *pwgts, *perm, *bndptr, *bndind, *minwgt, *maxwgt, *itpwgts; idxtype *phtable, *pmat, *pmatptr, *ndoms; EDegreeType *myedegrees; RInfoType *myrinfo; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; adjwgt = graph->adjwgt; bndptr = graph->bndptr; bndind = graph->bndind; where = graph->where; pwgts = graph->pwgts; pmat = ctrl->wspace.pmat; phtable = idxwspacemalloc(ctrl, nparts); ndoms = idxwspacemalloc(ctrl, nparts); ComputeSubDomainGraph(graph, nparts, pmat, ndoms); /* Setup the weight intervals of the various subdomains */ minwgt = idxwspacemalloc(ctrl, nparts); maxwgt = idxwspacemalloc(ctrl, nparts); itpwgts = idxwspacemalloc(ctrl, nparts); tvwgt = idxsum(nparts, pwgts); ASSERT(tvwgt == idxsum(nvtxs, graph->vwgt)); for (i=0; i<nparts; i++) { itpwgts[i] = tpwgts[i]*tvwgt; maxwgt[i] = tpwgts[i]*tvwgt*ubfactor; minwgt[i] = tpwgts[i]*tvwgt*(1.0/ubfactor); } perm = idxwspacemalloc(ctrl, nvtxs); IFSET(ctrl->dbglvl, DBG_REFINE, printf("Partitions: [%6d %6d]-[%6d %6d], Balance: %5.3f, Nv-Nb[%6d %6d]. Cut: %6d\n", pwgts[idxamin(nparts, pwgts)], pwgts[idxamax(nparts, pwgts)], minwgt[0], maxwgt[0], 1.0*nparts*pwgts[idxamax(nparts, pwgts)]/tvwgt, graph->nvtxs, graph->nbnd, graph->mincut)); for (pass=0; pass<npasses; pass++) { ASSERT(ComputeCut(graph, where) == graph->mincut); maxndoms = ndoms[idxamax(nparts, ndoms)]; oldcut = graph->mincut; nbnd = graph->nbnd; RandomPermute(nbnd, perm, 1); for (nmoves=iii=0; iii<graph->nbnd; iii++) { ii = perm[iii]; if (ii >= nbnd) continue; i = bndind[ii]; myrinfo = graph->rinfo+i; if (myrinfo->ed >= myrinfo->id) { /* Total ED is too high */ from = where[i]; vwgt = graph->vwgt[i]; if (myrinfo->id > 0 && pwgts[from]-vwgt < minwgt[from]) continue; /* This cannot be moved! */ myedegrees = myrinfo->edegrees; myndegrees = myrinfo->ndegrees; /* Determine the valid domains */ for (j=0; j<myndegrees; j++) { to = myedegrees[j].pid; phtable[to] = 1; pmatptr = pmat + to*nparts; for (nadd=0, k=0; k<myndegrees; k++) { if (k == j) continue; l = myedegrees[k].pid; if (pmatptr[l] == 0) { if (ndoms[l] > maxndoms-1) { phtable[to] = 0; nadd = maxndoms; break; } nadd++; } } if (ndoms[to]+nadd > maxndoms) phtable[to] = 0; if (nadd == 0) phtable[to] = 2; } /* Find the first valid move */ j = myrinfo->id; for (k=0; k<myndegrees; k++) { to = myedegrees[k].pid; if (!phtable[to]) continue; gain = myedegrees[k].ed-j; /* j = myrinfo->id. Allow good nodes to move */ if (pwgts[to]+vwgt <= maxwgt[to]+ffactor*gain && gain >= 0) break; } if (k == myndegrees) continue; /* break out if you did not find a candidate */ for (j=k+1; j<myndegrees; j++) { to = myedegrees[j].pid; if (!phtable[to]) continue; if ((myedegrees[j].ed > myedegrees[k].ed && pwgts[to]+vwgt <= maxwgt[to]) || (myedegrees[j].ed == myedegrees[k].ed && itpwgts[myedegrees[k].pid]*pwgts[to] < itpwgts[to]*pwgts[myedegrees[k].pid])) k = j; } to = myedegrees[k].pid; j = 0; if (myedegrees[k].ed-myrinfo->id > 0) j = 1; else if (myedegrees[k].ed-myrinfo->id == 0) { if (/*(iii&7) == 0 ||*/ phtable[myedegrees[k].pid] == 2 || pwgts[from] >= maxwgt[from] || itpwgts[from]*(pwgts[to]+vwgt) < itpwgts[to]*pwgts[from]) j = 1; } if (j == 0) continue; /*===================================================================== * If we got here, we can now move the vertex from 'from' to 'to' *======================================================================*/ graph->mincut -= myedegrees[k].ed-myrinfo->id; IFSET(ctrl->dbglvl, DBG_MOVEINFO, printf("\t\tMoving %6d to %3d. Gain: %4d. Cut: %6d\n", i, to, myedegrees[k].ed-myrinfo->id, graph->mincut)); /* Update pmat to reflect the move of 'i' */ pmat[from*nparts+to] += (myrinfo->id-myedegrees[k].ed); pmat[to*nparts+from] += (myrinfo->id-myedegrees[k].ed); if (pmat[from*nparts+to] == 0) { ndoms[from]--; if (ndoms[from]+1 == maxndoms) maxndoms = ndoms[idxamax(nparts, ndoms)]; } if (pmat[to*nparts+from] == 0) { ndoms[to]--; if (ndoms[to]+1 == maxndoms) maxndoms = ndoms[idxamax(nparts, ndoms)]; } /* Update where, weight, and ID/ED information of the vertex you moved */ where[i] = to; INC_DEC(pwgts[to], pwgts[from], vwgt); myrinfo->ed += myrinfo->id-myedegrees[k].ed; SWAP(myrinfo->id, myedegrees[k].ed, j); if (myedegrees[k].ed == 0) myedegrees[k] = myedegrees[--myrinfo->ndegrees]; else myedegrees[k].pid = from; if (myrinfo->ed-myrinfo->id < 0) BNDDelete(nbnd, bndind, bndptr, i); /* Update the degrees of adjacent vertices */ for (j=xadj[i]; j<xadj[i+1]; j++) { ii = adjncy[j]; me = where[ii]; myrinfo = graph->rinfo+ii; if (myrinfo->edegrees == NULL) { myrinfo->edegrees = ctrl->wspace.edegrees+ctrl->wspace.cdegree; ctrl->wspace.cdegree += xadj[ii+1]-xadj[ii]; } myedegrees = myrinfo->edegrees; ASSERT(CheckRInfo(myrinfo)); if (me == from) { INC_DEC(myrinfo->ed, myrinfo->id, adjwgt[j]); if (myrinfo->ed-myrinfo->id >= 0 && bndptr[ii] == -1) BNDInsert(nbnd, bndind, bndptr, ii); } else if (me == to) { INC_DEC(myrinfo->id, myrinfo->ed, adjwgt[j]); if (myrinfo->ed-myrinfo->id < 0 && bndptr[ii] != -1) BNDDelete(nbnd, bndind, bndptr, ii); } /* Remove contribution from the .ed of 'from' */ if (me != from) { for (k=0; k<myrinfo->ndegrees; k++) { if (myedegrees[k].pid == from) { if (myedegrees[k].ed == adjwgt[j]) myedegrees[k] = myedegrees[--myrinfo->ndegrees]; else myedegrees[k].ed -= adjwgt[j]; break; } } } /* Add contribution to the .ed of 'to' */ if (me != to) { for (k=0; k<myrinfo->ndegrees; k++) { if (myedegrees[k].pid == to) { myedegrees[k].ed += adjwgt[j]; break; } } if (k == myrinfo->ndegrees) { myedegrees[myrinfo->ndegrees].pid = to; myedegrees[myrinfo->ndegrees++].ed = adjwgt[j]; } } /* Update pmat to reflect the move of 'i' for domains other than 'from' and 'to' */ if (me != from && me != to) { pmat[me*nparts+from] -= adjwgt[j]; pmat[from*nparts+me] -= adjwgt[j]; if (pmat[me*nparts+from] == 0) { ndoms[me]--; if (ndoms[me]+1 == maxndoms) maxndoms = ndoms[idxamax(nparts, ndoms)]; } if (pmat[from*nparts+me] == 0) { ndoms[from]--; if (ndoms[from]+1 == maxndoms) maxndoms = ndoms[idxamax(nparts, ndoms)]; } if (pmat[me*nparts+to] == 0) { ndoms[me]++; if (ndoms[me] > maxndoms) { printf("You just increased the maxndoms: %d %d\n", ndoms[me], maxndoms); maxndoms = ndoms[me]; } } if (pmat[to*nparts+me] == 0) { ndoms[to]++; if (ndoms[to] > maxndoms) { printf("You just increased the maxndoms: %d %d\n", ndoms[to], maxndoms); maxndoms = ndoms[to]; } } pmat[me*nparts+to] += adjwgt[j]; pmat[to*nparts+me] += adjwgt[j]; } ASSERT(myrinfo->ndegrees <= xadj[ii+1]-xadj[ii]); ASSERT(CheckRInfo(myrinfo)); } nmoves++; } } graph->nbnd = nbnd; IFSET(ctrl->dbglvl, DBG_REFINE, printf("\t[%6d %6d], Balance: %5.3f, Nb: %6d. Nmoves: %5d, Cut: %5d, Vol: %5d, %d\n", pwgts[idxamin(nparts, pwgts)], pwgts[idxamax(nparts, pwgts)], 1.0*nparts*pwgts[idxamax(nparts, pwgts)]/tvwgt, graph->nbnd, nmoves, graph->mincut, ComputeVolume(graph, where), idxsum(nparts, ndoms))); if (graph->mincut == oldcut) break; } idxwspacefree(ctrl, nparts); idxwspacefree(ctrl, nparts); idxwspacefree(ctrl, nparts); idxwspacefree(ctrl, nparts); idxwspacefree(ctrl, nparts); idxwspacefree(ctrl, nvtxs); }
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 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 InitKWayPartitioningRB(ctrl_t *ctrl, graph_t *graph) { idx_t i, options[METIS_NOPTIONS], curobj=0; idx_t *bestwhere=NULL; real_t *ubvec=NULL; int status; METIS_SetDefaultOptions(options); options[METIS_OPTION_NITER] = 10; options[METIS_OPTION_OBJTYPE] = METIS_OBJTYPE_CUT; options[METIS_OPTION_NO2HOP] = ctrl->no2hop; options[METIS_OPTION_ONDISK] = ctrl->ondisk; ubvec = rmalloc(graph->ncon, "InitKWayPartitioning: ubvec"); for (i=0; i<graph->ncon; i++) ubvec[i] = (real_t)pow(ctrl->ubfactors[i], 1.0/log(ctrl->nparts)); switch (ctrl->objtype) { case METIS_OBJTYPE_CUT: case METIS_OBJTYPE_VOL: options[METIS_OPTION_NCUTS] = ctrl->nIparts; status = METIS_PartGraphRecursive(&graph->nvtxs, &graph->ncon, graph->xadj, graph->adjncy, graph->vwgt, graph->vsize, graph->adjwgt, &ctrl->nparts, ctrl->tpwgts, ubvec, options, &curobj, graph->where); if (status != METIS_OK) gk_errexit(SIGERR, "Failed during initial partitioning\n"); break; #ifdef XXX /* This does not seem to help */ case METIS_OBJTYPE_VOL: bestwhere = imalloc(graph->nvtxs, "InitKWayPartitioning: bestwhere"); options[METIS_OPTION_NCUTS] = 2; ntrials = (ctrl->nIparts+1)/2; for (i=0; i<ntrials; i++) { status = METIS_PartGraphRecursive(&graph->nvtxs, &graph->ncon, graph->xadj, graph->adjncy, graph->vwgt, graph->vsize, graph->adjwgt, &ctrl->nparts, ctrl->tpwgts, ubvec, options, &curobj, graph->where); if (status != METIS_OK) gk_errexit(SIGERR, "Failed during initial partitioning\n"); curobj = ComputeVolume(graph, graph->where); if (i == 0 || bestobj > curobj) { bestobj = curobj; if (i < ntrials-1) icopy(graph->nvtxs, graph->where, bestwhere); } if (bestobj == 0) break; } if (bestobj != curobj) icopy(graph->nvtxs, bestwhere, graph->where); break; #endif default: gk_errexit(SIGERR, "Unknown objtype: %d\n", ctrl->objtype); } gk_free((void **)&ubvec, &bestwhere, LTERM); }
/************************************************************************* * This function computes cuts and balance information **************************************************************************/ void ComputePartitionInfo(GraphType *graph, int nparts, idxtype *where) { int i, j, /*k,*/ nvtxs, ncon, mustfree=0; idxtype *xadj, *adjncy, *vwgt, *adjwgt, *kpwgts, *tmpptr; idxtype *padjncy, *padjwgt, *padjcut; nvtxs = graph->nvtxs; ncon = graph->ncon; xadj = graph->xadj; adjncy = graph->adjncy; vwgt = graph->vwgt; adjwgt = graph->adjwgt; if (vwgt == NULL) { vwgt = graph->vwgt = idxsmalloc(nvtxs, 1, "vwgt"); mustfree = 1; } if (adjwgt == NULL) { adjwgt = graph->adjwgt = idxsmalloc(xadj[nvtxs], 1, "adjwgt"); mustfree += 2; } printf("%d-way Cut: %5d, Vol: %5d, ", nparts, ComputeCut(graph, where), ComputeVolume(graph, where)); /* Compute balance information */ kpwgts = idxsmalloc(ncon*nparts, 0, "ComputePartitionInfo: kpwgts"); for (i=0; i<nvtxs; i++) { for (j=0; j<ncon; j++) kpwgts[where[i]*ncon+j] += vwgt[i*ncon+j]; } if (ncon == 1) { printf("\tBalance: %5.3f out of %5.3f\n", 1.0*nparts*kpwgts[idxamax(nparts, kpwgts)]/(1.0*idxsum(nparts, kpwgts)), 1.0*nparts*vwgt[idxamax(nvtxs, vwgt)]/(1.0*idxsum(nparts, kpwgts))); } else { printf("\tBalance:"); for (j=0; j<ncon; j++) printf(" (%5.3f out of %5.3f)", 1.0*nparts*kpwgts[ncon*idxamax_strd(nparts, kpwgts+j, ncon)+j]/(1.0*idxsum_strd(nparts, kpwgts+j, ncon)), 1.0*nparts*vwgt[ncon*idxamax_strd(nvtxs, vwgt+j, ncon)+j]/(1.0*idxsum_strd(nparts, kpwgts+j, ncon))); printf("\n"); } /* Compute p-adjncy information */ padjncy = idxsmalloc(nparts*nparts, 0, "ComputePartitionInfo: padjncy"); padjwgt = idxsmalloc(nparts*nparts, 0, "ComputePartitionInfo: padjwgt"); padjcut = idxsmalloc(nparts*nparts, 0, "ComputePartitionInfo: padjwgt"); idxset(nparts, 0, kpwgts); for (i=0; i<nvtxs; i++) { for (j=xadj[i]; j<xadj[i+1]; j++) { if (where[i] != where[adjncy[j]]) { padjncy[where[i]*nparts+where[adjncy[j]]] = 1; padjcut[where[i]*nparts+where[adjncy[j]]] += adjwgt[j]; if (kpwgts[where[adjncy[j]]] == 0) { padjwgt[where[i]*nparts+where[adjncy[j]]]++; kpwgts[where[adjncy[j]]] = 1; } } } for (j=xadj[i]; j<xadj[i+1]; j++) kpwgts[where[adjncy[j]]] = 0; } for (i=0; i<nparts; i++) kpwgts[i] = idxsum(nparts, padjncy+i*nparts); printf("Min/Max/Avg/Bal # of adjacent subdomains: %5d %5d %5.2f %7.3f\n", kpwgts[idxamin(nparts, kpwgts)], kpwgts[idxamax(nparts, kpwgts)], 1.0*idxsum(nparts, kpwgts)/(1.0*nparts), 1.0*nparts*kpwgts[idxamax(nparts, kpwgts)]/(1.0*idxsum(nparts, kpwgts))); for (i=0; i<nparts; i++) kpwgts[i] = idxsum(nparts, padjcut+i*nparts); printf("Min/Max/Avg/Bal # of adjacent subdomain cuts: %5d %5d %5d %7.3f\n", kpwgts[idxamin(nparts, kpwgts)], kpwgts[idxamax(nparts, kpwgts)], idxsum(nparts, kpwgts)/nparts, 1.0*nparts*kpwgts[idxamax(nparts, kpwgts)]/(1.0*idxsum(nparts, kpwgts))); for (i=0; i<nparts; i++) kpwgts[i] = idxsum(nparts, padjwgt+i*nparts); printf("Min/Max/Avg/Bal/Frac # of interface nodes: %5d %5d %5d %7.3f %7.3f\n", kpwgts[idxamin(nparts, kpwgts)], kpwgts[idxamax(nparts, kpwgts)], idxsum(nparts, kpwgts)/nparts, 1.0*nparts*kpwgts[idxamax(nparts, kpwgts)]/(1.0*idxsum(nparts, kpwgts)), 1.0*idxsum(nparts, kpwgts)/(1.0*nvtxs)); tmpptr = graph->where; graph->where = where; for (i=0; i<nparts; i++) IsConnectedSubdomain(NULL, graph, i, 1); graph->where = tmpptr; if (mustfree == 1 || mustfree == 3) { free(vwgt); graph->vwgt = NULL; } if (mustfree == 2 || mustfree == 3) { free(adjwgt); graph->adjwgt = NULL; } GKfree((void**)&kpwgts, &padjncy, &padjwgt, &padjcut, LTERM); }
} } } } graph->minvol -= xgain; graph->mincut -= -myrinfo->nid; } else { graph->minvol -= (xgain + mynbrs[k].gv); graph->mincut -= mynbrs[k].ned - myrinfo->nid; } /* Update where and pwgts */ where[i] = to; 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 the id/ed/gains/bnd of potentially affected nodes */ KWayVolUpdate(ctrl, graph, i, from, to, NULL, NULL, NULL, NULL, NULL, BNDTYPE_REFINE, vmarker, pmarker, modind); /*CheckKWayVolPartitionParams(ctrl, graph);*/ } ASSERT(ComputeCut(graph, where) == graph->mincut); ASSERTP(ComputeVolume(graph, where) == graph->minvol, ("%"PRIDX" %"PRIDX"\n", ComputeVolume(graph, where), graph->minvol)); }
bool ccVolumeCalcTool::updateGrid() { if (!m_cloud2) { assert(false); return false; } //cloud bounding-box --> grid size ccBBox box = getCustomBBox(); if (!box.isValid()) { return false; } unsigned gridWidth = 0, gridHeight = 0; if (!getGridSize(gridWidth, gridHeight)) { return false; } //grid step double gridStep = getGridStep(); assert(gridStep != 0); //ground ccGenericPointCloud* groundCloud = 0; double groundHeight = 0; switch (groundComboBox->currentIndex()) { case 0: groundHeight = groundEmptyValueDoubleSpinBox->value(); break; case 1: groundCloud = m_cloud1 ? m_cloud1 : m_cloud2; break; case 2: groundCloud = m_cloud2; break; default: assert(false); return false; } //ceil ccGenericPointCloud* ceilCloud = 0; double ceilHeight = 0; switch (ceilComboBox->currentIndex()) { case 0: ceilHeight = ceilEmptyValueDoubleSpinBox->value(); break; case 1: ceilCloud = m_cloud1 ? m_cloud1 : m_cloud2; break; case 2: ceilCloud = m_cloud2; break; default: assert(false); return false; } ccVolumeCalcTool::ReportInfo reportInfo; if (ComputeVolume( m_grid, groundCloud, ceilCloud, box, getProjectionDimension(), gridStep, gridWidth, gridHeight, getTypeOfProjection(), getFillEmptyCellsStrategy(fillGroundEmptyCellsComboBox), reportInfo, groundHeight, ceilHeight, this)) { outputReport(reportInfo); return true; } else { return false; } }
/************************************************************************* * This function computes cuts and balance information **************************************************************************/ void ComputePartitionInfoBipartite(graph_t *graph, idx_t nparts, idx_t *where) { idx_t i, j, k, nvtxs, ncon, mustfree=0; idx_t *xadj, *adjncy, *vwgt, *vsize, *adjwgt, *kpwgts, *tmpptr; idx_t *padjncy, *padjwgt, *padjcut; nvtxs = graph->nvtxs; ncon = graph->ncon; xadj = graph->xadj; adjncy = graph->adjncy; vwgt = graph->vwgt; vsize = graph->vsize; adjwgt = graph->adjwgt; if (vwgt == NULL) { vwgt = graph->vwgt = ismalloc(nvtxs, 1, "vwgt"); mustfree = 1; } if (adjwgt == NULL) { adjwgt = graph->adjwgt = ismalloc(xadj[nvtxs], 1, "adjwgt"); mustfree += 2; } printf("%"PRIDX"-way Cut: %5"PRIDX", Vol: %5"PRIDX", ", nparts, ComputeCut(graph, where), ComputeVolume(graph, where)); /* Compute balance information */ kpwgts = ismalloc(ncon*nparts, 0, "ComputePartitionInfo: kpwgts"); for (i=0; i<nvtxs; i++) { for (j=0; j<ncon; j++) kpwgts[where[i]*ncon+j] += vwgt[i*ncon+j]; } if (ncon == 1) { printf("\tBalance: %5.3"PRREAL" out of %5.3"PRREAL"\n", 1.0*nparts*kpwgts[iargmax(nparts, kpwgts)]/(1.0*isum(nparts, kpwgts, 1)), 1.0*nparts*vwgt[iargmax(nvtxs, vwgt)]/(1.0*isum(nparts, kpwgts, 1))); } else { printf("\tBalance:"); for (j=0; j<ncon; j++) printf(" (%5.3"PRREAL" out of %5.3"PRREAL")", 1.0*nparts*kpwgts[ncon*iargmax_strd(nparts, kpwgts+j, ncon)+j]/(1.0*isum(nparts, kpwgts+j, ncon)), 1.0*nparts*vwgt[ncon*iargmax_strd(nvtxs, vwgt+j, ncon)+j]/(1.0*isum(nparts, kpwgts+j, ncon))); printf("\n"); } /* Compute p-adjncy information */ padjncy = ismalloc(nparts*nparts, 0, "ComputePartitionInfo: padjncy"); padjwgt = ismalloc(nparts*nparts, 0, "ComputePartitionInfo: padjwgt"); padjcut = ismalloc(nparts*nparts, 0, "ComputePartitionInfo: padjwgt"); iset(nparts, 0, kpwgts); for (i=0; i<nvtxs; i++) { for (j=xadj[i]; j<xadj[i+1]; j++) { if (where[i] != where[adjncy[j]]) { padjncy[where[i]*nparts+where[adjncy[j]]] = 1; padjcut[where[i]*nparts+where[adjncy[j]]] += adjwgt[j]; if (kpwgts[where[adjncy[j]]] == 0) { padjwgt[where[i]*nparts+where[adjncy[j]]] += vsize[i]; kpwgts[where[adjncy[j]]] = 1; } } } for (j=xadj[i]; j<xadj[i+1]; j++) kpwgts[where[adjncy[j]]] = 0; } for (i=0; i<nparts; i++) kpwgts[i] = isum(nparts, padjncy+i*nparts, 1); printf("Min/Max/Avg/Bal # of adjacent subdomains: %5"PRIDX" %5"PRIDX" %5"PRIDX" %7.3"PRREAL"\n", kpwgts[iargmin(nparts, kpwgts)], kpwgts[iargmax(nparts, kpwgts)], isum(nparts, kpwgts, 1)/nparts, 1.0*nparts*kpwgts[iargmax(nparts, kpwgts)]/(1.0*isum(nparts, kpwgts, 1))); for (i=0; i<nparts; i++) kpwgts[i] = isum(nparts, padjcut+i*nparts, 1); printf("Min/Max/Avg/Bal # of adjacent subdomain cuts: %5"PRIDX" %5"PRIDX" %5"PRIDX" %7.3"PRREAL"\n", kpwgts[iargmin(nparts, kpwgts)], kpwgts[iargmax(nparts, kpwgts)], isum(nparts, kpwgts, 1)/nparts, 1.0*nparts*kpwgts[iargmax(nparts, kpwgts)]/(1.0*isum(nparts, kpwgts, 1))); for (i=0; i<nparts; i++) kpwgts[i] = isum(nparts, padjwgt+i*nparts, 1); printf("Min/Max/Avg/Bal/Frac # of interface nodes: %5"PRIDX" %5"PRIDX" %5"PRIDX" %7.3"PRREAL" %7.3"PRREAL"\n", kpwgts[iargmin(nparts, kpwgts)], kpwgts[iargmax(nparts, kpwgts)], isum(nparts, kpwgts, 1)/nparts, 1.0*nparts*kpwgts[iargmax(nparts, kpwgts)]/(1.0*isum(nparts, kpwgts, 1)), 1.0*isum(nparts, kpwgts, 1)/(1.0*nvtxs)); if (mustfree == 1 || mustfree == 3) { gk_free((void **)&vwgt, LTERM); graph->vwgt = NULL; } if (mustfree == 2 || mustfree == 3) { gk_free((void **)&adjwgt, LTERM); graph->adjwgt = NULL; } gk_free((void **)&kpwgts, &padjncy, &padjwgt, &padjcut, LTERM); }
/************************************************************************* * This function is the entry point for KMETIS **************************************************************************/ void *METIS_PartGraphForContact(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, double *xyzcoords, idxtype *sflag, idxtype *numflag, idxtype *nparts, idxtype *options, idxtype *edgecut, idxtype *part) { idxtype i, j, ii, dim, ncon, wgtflag, mcnumflag, nnodes, nlnodes, nclean, naclean, ndirty, maxdepth, rwgtflag, rnumflag; idxtype *mcvwgt, *dtpart, *marker, *leafpart; idxtype *adjwgt; float rubvec[2], lbvec[2]; GraphType graph, *cgraph; ContactInfoType *cinfo; DKeyValueType *xyzcand[3]; if (*numflag == 1) Change2CNumbering(*nvtxs, xadj, adjncy); /*--------------------------------------------------------------------- * Allocate memory for the contact info type *---------------------------------------------------------------------*/ cinfo = (ContactInfoType *)gk_malloc(sizeof(ContactInfoType), "METIS_PartGraphForContact: cinfo"); cinfo->leafptr = idxsmalloc(*nvtxs+1, 0, "METIS_PartGraphForContact: leafptr"); cinfo->leafind = idxsmalloc(*nvtxs, 0, "METIS_PartGraphForContact: leafind"); cinfo->leafwgt = idxsmalloc(*nvtxs, 0, "METIS_PartGraphForContact: leafwgt"); cinfo->part = idxsmalloc(*nvtxs, 0, "METIS_PartGraphForContact: part"); leafpart = cinfo->leafpart = idxmalloc(*nvtxs, "METIS_PartGraphForContact: leafpart"); cinfo->dtree = (DTreeNodeType *)gk_malloc(sizeof(DTreeNodeType)*(*nvtxs), "METIS_PartGraphForContact: cinfo->dtree"); cinfo->nvtxs = *nvtxs; /*--------------------------------------------------------------------- * Compute the initial k-way partitioning *---------------------------------------------------------------------*/ mcvwgt = idxsmalloc(2*(*nvtxs), 0, "METIS_PartGraphForContact: mcvwgt"); for (i=0; i<*nvtxs; i++) { mcvwgt[2*i+0] = 1; mcvwgt[2*i+1] = (sflag[i] == 0 ? 0 : 1); } adjwgt = idxmalloc(xadj[*nvtxs], "METIS_PartGraphForContact: adjwgt"); for (i=0; i<*nvtxs; i++) { for (j=xadj[i]; j<xadj[i+1]; j++) adjwgt[j] = (sflag[i] && sflag[adjncy[j]] ? 5 : 1); } rubvec[0] = 1.03; rubvec[1] = 1.05; ncon = 2; mcnumflag = 0; wgtflag = 1; METIS_mCPartGraphKway(nvtxs, &ncon, xadj, adjncy, mcvwgt, adjwgt, &wgtflag, &mcnumflag, nparts, rubvec, options, edgecut, part); /* The following is just for stat reporting purposes */ SetUpGraph(&graph, OP_KMETIS, *nvtxs, 2, xadj, adjncy, mcvwgt, NULL, 0); graph.vwgt = mcvwgt; ComputePartitionBalance(&graph, *nparts, part, lbvec); mprintf(" %D-way Edge-Cut: %7D, Balance: %5.2f %5.2f\n", *nparts, ComputeCut(&graph, part), lbvec[0], lbvec[1]); /*--------------------------------------------------------------------- * Induce the decission tree *---------------------------------------------------------------------*/ dtpart = idxmalloc(*nvtxs, "METIS_PartGraphForContact: dtpart"); marker = idxsmalloc(*nvtxs, 0, "METIS_PartGraphForContact: marker"); for (dim=0; dim<3; dim++) { xyzcand[dim] = (DKeyValueType *)gk_malloc(sizeof(DKeyValueType)*(*nvtxs), "METIS_PartGraphForContact: xyzcand[dim]"); for (i=0; i<*nvtxs; i++) { xyzcand[dim][i].key = xyzcoords[3*i+dim]; xyzcand[dim][i].val = i; } idkeysort(*nvtxs, xyzcand[dim]); } nnodes = nlnodes = nclean = naclean = ndirty = maxdepth = 0; InduceDecissionTree(*nvtxs, xyzcand, sflag, *nparts, part, *nvtxs/(20*(*nparts)), *nvtxs/(20*(*nparts)*(*nparts)), 0.90, &nnodes, &nlnodes, cinfo->dtree, leafpart, dtpart, &nclean, &naclean, &ndirty, &maxdepth, marker); mprintf("NNodes: %5D, NLNodes: %5D, NClean: %5D, NAClean: %5D, NDirty: %5D, MaxDepth: %3D\n", nnodes, nlnodes, nclean, naclean, ndirty, maxdepth); /*--------------------------------------------------------------------- * Create the tree-induced coarse graph and refine it *---------------------------------------------------------------------*/ cgraph = CreatePartitionGraphForContact(*nvtxs, xadj, adjncy, mcvwgt, adjwgt, nlnodes, leafpart); for (i=0; i<*nvtxs; i++) part[leafpart[i]] = dtpart[i]; ComputePartitionBalance(cgraph, *nparts, part, lbvec); mprintf(" %D-way Edge-Cut: %7D, Balance: %5.2f %5.2f\n", *nparts, ComputeCut(cgraph, part), lbvec[0], lbvec[1]); rwgtflag = 3; rnumflag = 0; METIS_mCRefineGraphKway(&(cgraph->nvtxs), &ncon, cgraph->xadj, cgraph->adjncy, cgraph->vwgt, cgraph->adjwgt, &rwgtflag, &rnumflag, nparts, rubvec, options, edgecut, part); ComputePartitionBalance(cgraph, *nparts, part, lbvec); mprintf(" %D-way Edge-Cut: %7D, Balance: %5.2f %5.2f\n", *nparts, ComputeCut(cgraph, part), lbvec[0], lbvec[1]); /*--------------------------------------------------------------------- * Use that to compute the partition of the original graph *---------------------------------------------------------------------*/ idxcopy(cgraph->nvtxs, part, dtpart); for (i=0; i<*nvtxs; i++) part[i] = dtpart[leafpart[i]]; ComputePartitionBalance(&graph, *nparts, part, lbvec); idxset(*nvtxs, 1, graph.vwgt); mprintf(" %D-way Edge-Cut: %7D, Volume: %7D, Balance: %5.2f %5.2f\n", *nparts, ComputeCut(&graph, part), ComputeVolume(&graph, part), lbvec[0], lbvec[1]); /*--------------------------------------------------------------------- * Induce the final decission tree *---------------------------------------------------------------------*/ nnodes = nlnodes = nclean = naclean = ndirty = maxdepth = 0; InduceDecissionTree(*nvtxs, xyzcand, sflag, *nparts, part, *nvtxs/((40)*(*nparts)), 1, 1.00, &nnodes, &nlnodes, cinfo->dtree, leafpart, dtpart, &nclean, &naclean, &ndirty, &maxdepth, marker); mprintf("NNodes: %5D, NLNodes: %5D, NClean: %5D, NAClean: %5D, NDirty: %5D, MaxDepth: %3D\n", nnodes, nlnodes, nclean, naclean, ndirty, maxdepth); /*--------------------------------------------------------------------- * Populate the remaining fields of the cinfo data structure *---------------------------------------------------------------------*/ cinfo->nnodes = nnodes; cinfo->nleafs = nlnodes; idxcopy(*nvtxs, part, cinfo->part); BuildDTLeafContents(cinfo, sflag); CheckDTree(*nvtxs, xyzcoords, part, cinfo); gk_free((void **)&mcvwgt, &dtpart, &xyzcand[0], &xyzcand[1], &xyzcand[2], &marker, &adjwgt, LTERM); if (*numflag == 1) Change2FNumbering(*nvtxs, xadj, adjncy, part); return (void *)cinfo; }
double ComputeMinAdditionVolume(RSTRange& range1,RSTRange& range2){ RSTRange boundingRange; ComputeBoundingRectangle(range1,range2,boundingRange); return ComputeVolume(boundingRange)-ComputeVolume(range1); }