int main() { static char buf[256]; int i, c; for (i = 1, iset(pow26[0],"1"), iset(pow26_sums[0],"1"); i < 23; i++) { imuls(pow26[i], pow26[i - 1], 26); iadd(pow26_sums[i], pow26_sums[i - 1], pow26[i]); } for (;;) { for (i = 0; (c = getchar()) != EOF && c != '\n';) if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) buf[i++] = c; buf[i] = '\0'; if (c == EOF) break; if (i == 0) continue; if (buf[0] >= '0' && buf[0] <= '9') giveword(buf); else givenum(buf, i); } return 0; }
void Compute2WayNodePartitionParams(ctrl_t *ctrl, graph_t *graph) { idx_t i, j, nvtxs, nbnd; idx_t *xadj, *adjncy, *vwgt; idx_t *where, *pwgts, *bndind, *bndptr, *edegrees; nrinfo_t *rinfo; idx_t me, other; nvtxs = graph->nvtxs; xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; where = graph->where; rinfo = graph->nrinfo; pwgts = iset(3, 0, graph->pwgts); bndind = graph->bndind; bndptr = iset(nvtxs, -1, graph->bndptr); /*------------------------------------------------------------ / Compute now the separator external degrees /------------------------------------------------------------*/ nbnd = 0; for (i=0; i<nvtxs; i++) { me = where[i]; pwgts[me] += vwgt[i]; ASSERT(me >=0 && me <= 2); if (me == 2) { /* If it is on the separator do some computations */ BNDInsert(nbnd, bndind, bndptr, i); edegrees = rinfo[i].edegrees; edegrees[0] = edegrees[1] = 0; for (j=xadj[i]; j<xadj[i+1]; j++) { other = where[adjncy[j]]; if (other != 2) edegrees[other] += vwgt[adjncy[j]]; } } } ASSERT(CheckNodeBnd(graph, nbnd)); graph->mincut = pwgts[2]; graph->nbnd = nbnd; }
/************************************************************************* * This function computes the balance of the partitioning **************************************************************************/ void ComputePartitionBalance(graph_t *graph, idx_t nparts, idx_t *where, real_t *ubvec) { idx_t i, j, nvtxs, ncon; idx_t *kpwgts, *vwgt; real_t balance; nvtxs = graph->nvtxs; ncon = graph->ncon; vwgt = graph->vwgt; kpwgts = ismalloc(nparts, 0, "ComputePartitionInfo: kpwgts"); if (vwgt == NULL) { for (i=0; i<nvtxs; i++) kpwgts[where[i]]++; ubvec[0] = 1.0*nparts*kpwgts[iargmax(nparts, kpwgts)]/(1.0*nvtxs); } else { for (j=0; j<ncon; j++) { iset(nparts, 0, kpwgts); for (i=0; i<graph->nvtxs; i++) kpwgts[where[i]] += vwgt[i*ncon+j]; ubvec[j] = 1.0*nparts*kpwgts[iargmax(nparts, kpwgts)]/(1.0*isum(nparts, kpwgts, 1)); } } gk_free((void **)&kpwgts, LTERM); }
void GrowBisectionNode2(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niparts) { idx_t i, j, k, nvtxs, bestcut=0, mincut, inbfs; idx_t *xadj, *where, *bndind, *bestwhere; WCOREPUSH; nvtxs = graph->nvtxs; xadj = graph->xadj; /* Allocate refinement memory. Allocate sufficient memory for both edge and node */ graph->pwgts = imalloc(3, "GrowBisectionNode: pwgts"); graph->where = imalloc(nvtxs, "GrowBisectionNode: where"); graph->bndptr = imalloc(nvtxs, "GrowBisectionNode: bndptr"); graph->bndind = imalloc(nvtxs, "GrowBisectionNode: bndind"); graph->id = imalloc(nvtxs, "GrowBisectionNode: id"); graph->ed = imalloc(nvtxs, "GrowBisectionNode: ed"); graph->nrinfo = (nrinfo_t *)gk_malloc(nvtxs*sizeof(nrinfo_t), "GrowBisectionNode: nrinfo"); bestwhere = iwspacemalloc(ctrl, nvtxs); where = graph->where; bndind = graph->bndind; for (inbfs=0; inbfs<niparts; inbfs++) { iset(nvtxs, 1, where); if (inbfs > 0) where[irandInRange(nvtxs)] = 0; Compute2WayPartitionParams(ctrl, graph); General2WayBalance(ctrl, graph, ntpwgts); FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter); /* Construct and refine the vertex separator */ for (i=0; i<graph->nbnd; i++) { j = bndind[i]; if (xadj[j+1]-xadj[j] > 0) /* ignore islands */ where[j] = 2; } Compute2WayNodePartitionParams(ctrl, graph); FM_2WayNodeRefine2Sided(ctrl, graph, 4); /* printf("ISep: [%"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"] %"PRIDX"\n", inbfs, graph->pwgts[0], graph->pwgts[1], graph->pwgts[2], bestcut); */ if (inbfs == 0 || bestcut > graph->mincut) { bestcut = graph->mincut; icopy(nvtxs, where, bestwhere); } } graph->mincut = bestcut; icopy(nvtxs, bestwhere, where); WCOREPOP; }
int removeElement(vector<int>& nums, int val) { multiset<int> iset(nums.cbegin(), nums.cend()); iset.erase(val); vector<int> tmp(iset.cbegin(), iset.cend()); nums = tmp; return tmp.size(); }
/************************************************************************* * The follwoing function allocates an array of integers **************************************************************************/ int *ismalloc(int n, int ival, char *msg) { if (n == 0) return NULL; return iset(n, ival, (int *)GKmalloc(sizeof(int)*n, msg)); }
/// HandleInput_Edit_FTP_Win void HandleInput_Edit_FTP_Win() { uint32 result = 0; uint16 code = 0; while ((result = RA_HandleInput(edit_ftp_win, &code))) { switch(result & WMHI_CLASSMASK) { case WMHI_CLOSEWINDOW: RA_CloseWindow(edit_ftp_win); edit_ftp_window = NULL; break; case WMHI_GADGETUP: switch (result & WMHI_GADGETMASK) { case OBJ_FTP_USE: gadset(GAD(OBJ_LBROWSER_BROW), window, LISTBROWSER_Labels, ~0); updateFTPNode(); gadset(GAD(OBJ_LBROWSER_BROW), window, LISTBROWSER_Labels, &list_FTPs, LISTBROWSER_AutoFit, TRUE); case OBJ_FTP_CANCEL: RA_CloseWindow(edit_ftp_win); edit_brow_window = NULL; break; case OBJ_FTP_PATH_GET: if (gfRequestFile(OBJ(OBJ_FTP_PATH_GET), edit_ftp_window)) { } break; case OBJ_FTP_PATH_CHOOSE: // set Attrs according to the button clicked on. case OBJ_FTP_OPEN_CHOOSE: case OBJ_FTP_NEW_CHOOSE: iset( OBJ(OBJ_HIDDEN_CHOOSER), CHOOSER_LabelArray, hidden_strings); IIntuition->ActivateGadget(GAD(OBJ_HIDDEN_CHOOSER), edit_ftp_window, NULL); break; case OBJ_FTP_AREXX_CHOOSE: iset( OBJ(OBJ_HIDDEN_CHOOSER), CHOOSER_LabelArray, hidden_strings); IIntuition->ActivateGadget(GAD(OBJ_HIDDEN_CHOOSER), edit_ftp_window, NULL); break; } } } }
/*********************************************************************************** * This function determines the cost of moving data between the two meshes assuming * that a good matching between the two partitions was done! ************************************************************************************/ int ComputeMapCost(idxtype nvtxs, idxtype nparts, idxtype *fepart, idxtype *cpart) { idxtype i, j, k, n, ncomm; KeyValueType cand[nparts*nparts]; idxtype fmatched[nparts], cmatched[nparts]; /* Compute the overlap */ for (i=0; i<nparts; i++) { for (j=0; j<nparts; j++) { cand[i*nparts+j].key = 0; cand[i*nparts+j].val = i*nparts+j; } } for (k=0, i=0; i<nvtxs; i++) { if (cpart[i] >= 0) { cand[(fepart[i]-1)*nparts+(cpart[i]-1)].key++; k++; } } mprintf("Contact points: %D\n", k); ikeysort(nparts*nparts, cand); iset(nparts, -1, fmatched); iset(nparts, -1, cmatched); for (ncomm=0, k=nparts*nparts-1; k>=0; k--) { i = cand[k].val/nparts; j = cand[k].val%nparts; if (fmatched[i] == -1 && cmatched[j] == -1) { fmatched[i] = j; cmatched[j] = i; } else ncomm += cand[k].key; } mprintf("Ncomm: %D\n", ncomm); return ncomm; }
StructureClass::StructureClass(Value name) : LispClass(WIDETAG_STRUCTURE_CLASS, 9) { set_layout(structure_class_layout()); iset(3, make_value(structure_class_layout())); set_name(name); // set_slots(structure_class_instance_slots()); set_slots(NIL); }
bool DelayHistogram:: StopAll() { if (nsets < 1) return false; struct timeval stop; if (0 != gettimeofday(&stop, 0)) return false; for (size_t iset(0); iset < nsets; ++iset) Update(iset, &stop); return true; }
void SkOperandInterpolator::UnitTest() { #ifdef SK_SUPPORT_UNITTEST SkOperandInterpolator inter(3, 2, SkType_Float); SkOperand v1[3], v2[3], v[3], vv[3]; Result result; inter.setKeyFrame(0, 100, iset(v1, 10, 20, 30), 0); inter.setKeyFrame(1, 200, iset(v2, 110, 220, 330)); result = inter.timeToValues(0, v); SkASSERT(result == kFreezeStart_Result); SkASSERT(memcmp(v, v1, sizeof(v)) == 0); result = inter.timeToValues(99, v); SkASSERT(result == kFreezeStart_Result); SkASSERT(memcmp(v, v1, sizeof(v)) == 0); result = inter.timeToValues(100, v); SkASSERT(result == kNormal_Result); SkASSERT(memcmp(v, v1, sizeof(v)) == 0); result = inter.timeToValues(200, v); SkASSERT(result == kNormal_Result); SkASSERT(memcmp(v, v2, sizeof(v)) == 0); result = inter.timeToValues(201, v); SkASSERT(result == kFreezeEnd_Result); SkASSERT(memcmp(v, v2, sizeof(v)) == 0); result = inter.timeToValues(150, v); SkASSERT(result == kNormal_Result); SkASSERT(memcmp(v, iset(vv, 60, 120, 180), sizeof(v)) == 0); result = inter.timeToValues(125, v); SkASSERT(result == kNormal_Result); result = inter.timeToValues(175, v); SkASSERT(result == kNormal_Result); #endif }
void McRandomBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niparts) { idx_t i, ii, j, k, nvtxs, ncon, from, bestcut=0, mincut, inbfs, qnum; idx_t *bestwhere, *where, *perm, *counts; idx_t *vwgt; WCOREPUSH; nvtxs = graph->nvtxs; ncon = graph->ncon; vwgt = graph->vwgt; Allocate2WayPartitionMemory(ctrl, graph); where = graph->where; bestwhere = iwspacemalloc(ctrl, nvtxs); perm = iwspacemalloc(ctrl, nvtxs); counts = iwspacemalloc(ctrl, ncon); for (inbfs=0; inbfs<2*niparts; inbfs++) { irandArrayPermute(nvtxs, perm, nvtxs/2, 1); iset(ncon, 0, counts); /* partition by spliting the queues randomly */ for (ii=0; ii<nvtxs; ii++) { i = perm[ii]; qnum = iargmax(ncon, vwgt+i*ncon); where[i] = (counts[qnum]++)%2; } Compute2WayPartitionParams(ctrl, graph); FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter); Balance2Way(ctrl, graph, ntpwgts); FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter); Balance2Way(ctrl, graph, ntpwgts); FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter); if (inbfs == 0 || bestcut >= graph->mincut) { bestcut = graph->mincut; icopy(nvtxs, where, bestwhere); if (bestcut == 0) break; } } graph->mincut = bestcut; icopy(nvtxs, bestwhere, where); WCOREPOP; }
void ComputeKWayBoundary(ctrl_t *ctrl, graph_t *graph, idx_t bndtype) { idx_t i, nvtxs, nbnd; idx_t *bndind, *bndptr; nvtxs = graph->nvtxs; bndind = graph->bndind; bndptr = iset(nvtxs, -1, graph->bndptr); nbnd = 0; switch (ctrl->objtype) { case METIS_OBJTYPE_CUT: /* Compute the boundary */ if (bndtype == BNDTYPE_REFINE) { for (i=0; i<nvtxs; i++) { if (graph->ckrinfo[i].ed-graph->ckrinfo[i].id >= 0) BNDInsert(nbnd, bndind, bndptr, i); } } else { /* BNDTYPE_BALANCE */ for (i=0; i<nvtxs; i++) { if (graph->ckrinfo[i].ed > 0) BNDInsert(nbnd, bndind, bndptr, i); } } break; case METIS_OBJTYPE_VOL: /* Compute the boundary */ if (bndtype == BNDTYPE_REFINE) { for (i=0; i<nvtxs; i++) { if (graph->vkrinfo[i].gv >= 0) BNDInsert(nbnd, bndind, bndptr, i); } } else { /* BNDTYPE_BALANCE */ for (i=0; i<nvtxs; i++) { if (graph->vkrinfo[i].ned > 0) BNDInsert(nbnd, bndind, bndptr, i); } } break; default: gk_errexit(SIGERR, "Unknown objtype of %d\n", ctrl->objtype); } graph->nbnd = nbnd; }
void updateBrowserWindow(struct URL_BrowserNode * pBrowser) { if(pBrowser != NULL) { iset(edit_brow_win, WINDOW_UserData, pBrowser); gadset(GAD(OBJ_BROW_NAME_STR), edit_brow_window, STRINGA_TextVal, pBrowser->ubn_Name); gadset(GAD(OBJ_BROW_PATH_GET), edit_brow_window, GETFILE_File, pBrowser->ubn_Path); gadset(GAD(OBJ_BROW_AREXX_STR), edit_brow_window, STRINGA_TextVal, pBrowser->ubn_Port); gadset(GAD(OBJ_BROW_SHOW_STR), edit_brow_window, STRINGA_TextVal, pBrowser->ubn_ShowCmd); gadset(GAD(OBJ_BROW_FRONT_STR), edit_brow_window, STRINGA_TextVal, pBrowser->ubn_ToFrontCmd); gadset(GAD(OBJ_BROW_OPEN_STR), edit_brow_window, STRINGA_TextVal, pBrowser->ubn_OpenURLCmd); gadset(GAD(OBJ_BROW_NEW_STR), edit_brow_window, STRINGA_TextVal, pBrowser->ubn_OpenURLWCmd); } else IDOS->Printf("No browser node\n"); }
void StandardObject::set_slot_value(Value arg1, Value arg2) { if (!symbolp(arg1)) { signal_type_error(arg1, S_symbol); return; } Layout * layout = this->layout(); if (!layout) { signal_lisp_error("No layout for instance."); return; } if (layout->is_invalid()) { // Update instance. layout = update_layout(); } long index = layout->slot_index(arg1); if (index >= 0) { iset(index, arg2); } else { // not an instance slot Value location = layout->shared_slot_location(arg1); if (location != NIL) SYS_setcdr(location, arg2); else { // slot-missing current_thread()->execute(the_symbol(S_slot_missing)->function(), class_of(), make_value(this), arg1, S_setf, arg2); } } }
static void givenum(const char *s, int len) { static limb_t x[NLIMBS]; int i; iset(x, "0"); for (i = 0; i < len; i++) { if (i >= 1) imuls(x, x, 26); if (s[i] >= 'a' && s[i] <= 'z') iadds(x, s[i] - 'a'); else iadds(x, s[i] - 'A'); } iadd(x, x, pow26_sums[len - 1]); printf("%-22s", s); iprint(x); }
void McGrowBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niparts) { idx_t i, j, k, nvtxs, ncon, from, bestcut=0, mincut, inbfs; idx_t *bestwhere, *where; WCOREPUSH; nvtxs = graph->nvtxs; Allocate2WayPartitionMemory(ctrl, graph); where = graph->where; bestwhere = iwspacemalloc(ctrl, nvtxs); for (inbfs=0; inbfs<2*niparts; inbfs++) { iset(nvtxs, 1, where); where[irandInRange(nvtxs)] = 0; Compute2WayPartitionParams(ctrl, graph); Balance2Way(ctrl, graph, ntpwgts); FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter); Balance2Way(ctrl, graph, ntpwgts); FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter); if (inbfs == 0 || bestcut >= graph->mincut) { bestcut = graph->mincut; icopy(nvtxs, where, bestwhere); if (bestcut == 0) break; } } graph->mincut = bestcut; icopy(nvtxs, bestwhere, where); WCOREPOP; }
static void giveword(const char *s) { static limb_t x[NLIMBS], z[NLIMBS]; static char buf[256], buf2[256]; int i, j, len; iset(x, s); for (len = 1; icmp(pow26_sums[len], x) < 0; len++); isub(z, x, pow26_sums[len - 1]); for (i = 0;;) { for (j = 0; j < NLIMBS; j++) if (z[j]) break; if (j >= NLIMBS && i > 0) break; buf[i++] = idivs(z, z, 26) + 'a'; } for (j = 0; i-- > 0;) buf2[j++] = buf[i]; buf2[j] = '\0'; printf("%-22s", buf2); iprint(x); }
void ComputeKWayVolGains(ctrl_t *ctrl, graph_t *graph) { idx_t i, ii, j, k, l, nvtxs, nparts, me, other, pid; idx_t *xadj, *vsize, *adjncy, *where, *bndind, *bndptr, *ophtable; vkrinfo_t *myrinfo, *orinfo; vnbr_t *mynbrs, *onbrs; WCOREPUSH; nparts = ctrl->nparts; nvtxs = graph->nvtxs; xadj = graph->xadj; vsize = graph->vsize; adjncy = graph->adjncy; where = graph->where; bndind = graph->bndind; bndptr = iset(nvtxs, -1, graph->bndptr); ophtable = iset(nparts, -1, iwspacemalloc(ctrl, nparts)); /* Compute the volume gains */ graph->minvol = graph->nbnd = 0; for (i=0; i<nvtxs; i++) { myrinfo = graph->vkrinfo+i; myrinfo->gv = IDX_MIN; if (myrinfo->nnbrs > 0) { me = where[i]; mynbrs = ctrl->vnbrpool + myrinfo->inbr; graph->minvol += myrinfo->nnbrs*vsize[i]; for (j=xadj[i]; j<xadj[i+1]; j++) { ii = adjncy[j]; other = where[ii]; orinfo = graph->vkrinfo+ii; onbrs = ctrl->vnbrpool + orinfo->inbr; for (k=0; k<orinfo->nnbrs; k++) ophtable[onbrs[k].pid] = k; ophtable[other] = 1; /* this is to simplify coding */ if (me == other) { /* Find which domains 'i' is connected to but 'ii' is not and update their gain */ for (k=0; k<myrinfo->nnbrs; k++) { if (ophtable[mynbrs[k].pid] == -1) mynbrs[k].gv -= vsize[ii]; } } else { ASSERT(ophtable[me] != -1); if (onbrs[ophtable[me]].ned == 1) { /* I'm the only connection of 'ii' in 'me' */ /* Increase the gains for all the common domains between 'i' and 'ii' */ for (k=0; k<myrinfo->nnbrs; k++) { if (ophtable[mynbrs[k].pid] != -1) mynbrs[k].gv += vsize[ii]; } } else { /* Find which domains 'i' is connected to and 'ii' is not and update their gain */ for (k=0; k<myrinfo->nnbrs; k++) { if (ophtable[mynbrs[k].pid] == -1) mynbrs[k].gv -= vsize[ii]; } } } /* Reset the marker vector */ for (k=0; k<orinfo->nnbrs; k++) ophtable[onbrs[k].pid] = -1; ophtable[other] = -1; } /* Compute the max vgain */ for (k=0; k<myrinfo->nnbrs; k++) { if (mynbrs[k].gv > myrinfo->gv) myrinfo->gv = mynbrs[k].gv; } /* Add the extra gain due to id == 0 */ if (myrinfo->ned > 0 && myrinfo->nid == 0) myrinfo->gv += vsize[i]; } if (myrinfo->gv >= 0) BNDInsert(graph->nbnd, bndind, bndptr, i); } WCOREPOP; }
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 InduceRowPartFromColumnPart(idx_t nrows, idx_t *rowptr, idx_t *rowind, idx_t *rpart, idx_t *cpart, idx_t nparts, real_t *tpwgts) { idx_t i, j, k, me; idx_t nnbrs, *pwgts, *nbrdom, *nbrwgt, *nbrmrk; idx_t *itpwgts; pwgts = ismalloc(nparts, 0, "InduceRowPartFromColumnPart: pwgts"); nbrdom = ismalloc(nparts, 0, "InduceRowPartFromColumnPart: nbrdom"); nbrwgt = ismalloc(nparts, 0, "InduceRowPartFromColumnPart: nbrwgt"); nbrmrk = ismalloc(nparts, -1, "InduceRowPartFromColumnPart: nbrmrk"); iset(nrows, -1, rpart); /* setup the integer target partition weights */ itpwgts = imalloc(nparts, "InduceRowPartFromColumnPart: itpwgts"); if (tpwgts == NULL) { iset(nparts, 1+nrows/nparts, itpwgts); } else { for (i=0; i<nparts; i++) itpwgts[i] = 1+nrows*tpwgts[i]; } /* first assign the rows consisting only of columns that belong to a single partition. Assign rows that are empty to -2 (un-assigned) */ for (i=0; i<nrows; i++) { if (rowptr[i+1]-rowptr[i] == 0) { rpart[i] = -2; continue; } me = cpart[rowind[rowptr[i]]]; for (j=rowptr[i]+1; j<rowptr[i+1]; j++) { if (cpart[rowind[j]] != me) break; } if (j == rowptr[i+1]) { rpart[i] = me; pwgts[me]++; } } /* next assign the rows consisting of columns belonging to multiple partitions in a balanced way */ for (i=0; i<nrows; i++) { if (rpart[i] == -1) { for (nnbrs=0, j=rowptr[i]; j<rowptr[i+1]; j++) { me = cpart[rowind[j]]; if (nbrmrk[me] == -1) { nbrdom[nnbrs] = me; nbrwgt[nnbrs] = 1; nbrmrk[me] = nnbrs++; } else { nbrwgt[nbrmrk[me]]++; } } ASSERT(nnbrs > 0); /* assign it first to the domain with most things in common */ rpart[i] = nbrdom[iargmax(nnbrs, nbrwgt)]; /* if overweight, assign it to the light domain */ if (pwgts[rpart[i]] > itpwgts[rpart[i]]) { for (j=0; j<nnbrs; j++) { if (pwgts[nbrdom[j]] < itpwgts[nbrdom[j]] || pwgts[nbrdom[j]]-itpwgts[nbrdom[j]] < pwgts[rpart[i]]-itpwgts[rpart[i]]) { rpart[i] = nbrdom[j]; break; } } } pwgts[rpart[i]]++; /* reset nbrmrk array */ for (j=0; j<nnbrs; j++) nbrmrk[nbrdom[j]] = -1; } } gk_free((void **)&pwgts, &nbrdom, &nbrwgt, &nbrmrk, &itpwgts, LTERM); }
/************************************************************************* * This function is the entry point of the initial partition algorithm * that does recursive bissection. * This algorithm assembles the graph to all the processors and preceeds * by parallelizing the recursive bisection step. **************************************************************************/ void InitPartition(ctrl_t *ctrl, graph_t *graph) { idx_t i, j, ncon, mype, npes, gnvtxs, ngroups; idx_t *xadj, *adjncy, *adjwgt, *vwgt; idx_t *part, *gwhere0, *gwhere1; idx_t *tmpwhere, *tmpvwgt, *tmpxadj, *tmpadjncy, *tmpadjwgt; graph_t *agraph; idx_t lnparts, fpart, fpe, lnpes; idx_t twoparts=2, moptions[METIS_NOPTIONS], edgecut, max_cut; real_t *tpwgts, *tpwgts2, *lbvec, lbsum, min_lbsum, wsum; MPI_Comm ipcomm; struct { double sum; int rank; } lpesum, gpesum; WCOREPUSH; ncon = graph->ncon; ngroups = gk_max(gk_min(RIP_SPLIT_FACTOR, ctrl->npes), 1); IFSET(ctrl->dbglvl, DBG_TIME, gkMPI_Barrier(ctrl->comm)); IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->InitPartTmr)); lbvec = rwspacemalloc(ctrl, ncon); /* assemble the graph to all the processors */ agraph = AssembleAdaptiveGraph(ctrl, graph); gnvtxs = agraph->nvtxs; /* make a copy of the graph's structure for later */ xadj = icopy(gnvtxs+1, agraph->xadj, iwspacemalloc(ctrl, gnvtxs+1)); vwgt = icopy(gnvtxs*ncon, agraph->vwgt, iwspacemalloc(ctrl, gnvtxs*ncon)); adjncy = icopy(agraph->nedges, agraph->adjncy, iwspacemalloc(ctrl, agraph->nedges)); adjwgt = icopy(agraph->nedges, agraph->adjwgt, iwspacemalloc(ctrl, agraph->nedges)); part = iwspacemalloc(ctrl, gnvtxs); /* create different processor groups */ gkMPI_Comm_split(ctrl->gcomm, ctrl->mype % ngroups, 0, &ipcomm); gkMPI_Comm_rank(ipcomm, &mype); gkMPI_Comm_size(ipcomm, &npes); /* Go into the recursive bisection */ METIS_SetDefaultOptions(moptions); moptions[METIS_OPTION_SEED] = ctrl->sync + (ctrl->mype % ngroups) + 1; tpwgts = ctrl->tpwgts; tpwgts2 = rwspacemalloc(ctrl, 2*ncon); lnparts = ctrl->nparts; fpart = fpe = 0; lnpes = npes; while (lnpes > 1 && lnparts > 1) { /* determine the weights of the two partitions as a function of the weight of the target partition weights */ for (j=(lnparts>>1), i=0; i<ncon; i++) { tpwgts2[i] = rsum(j, tpwgts+fpart*ncon+i, ncon); tpwgts2[ncon+i] = rsum(lnparts-j, tpwgts+(fpart+j)*ncon+i, ncon); wsum = 1.0/(tpwgts2[i] + tpwgts2[ncon+i]); tpwgts2[i] *= wsum; tpwgts2[ncon+i] *= wsum; } METIS_PartGraphRecursive(&agraph->nvtxs, &ncon, agraph->xadj, agraph->adjncy, agraph->vwgt, NULL, agraph->adjwgt, &twoparts, tpwgts2, NULL, moptions, &edgecut, part); /* pick one of the branches */ if (mype < fpe+lnpes/2) { KeepPart(ctrl, agraph, part, 0); lnpes = lnpes/2; lnparts = lnparts/2; } else { KeepPart(ctrl, agraph, part, 1); fpart = fpart + lnparts/2; fpe = fpe + lnpes/2; lnpes = lnpes - lnpes/2; lnparts = lnparts - lnparts/2; } } gwhere0 = iset(gnvtxs, 0, iwspacemalloc(ctrl, gnvtxs)); gwhere1 = iwspacemalloc(ctrl, gnvtxs); if (lnparts == 1) { /* Case npes is greater than or equal to nparts */ /* Only the first process will assign labels (for the reduction to work) */ if (mype == fpe) { for (i=0; i<agraph->nvtxs; i++) gwhere0[agraph->label[i]] = fpart; } } else { /* Case in which npes is smaller than nparts */ /* create the normalized tpwgts for the lnparts from ctrl->tpwgts */ tpwgts = rwspacemalloc(ctrl, lnparts*ncon); for (j=0; j<ncon; j++) { for (wsum=0.0, i=0; i<lnparts; i++) { tpwgts[i*ncon+j] = ctrl->tpwgts[(fpart+i)*ncon+j]; wsum += tpwgts[i*ncon+j]; } for (wsum=1.0/wsum, i=0; i<lnparts; i++) tpwgts[i*ncon+j] *= wsum; } METIS_PartGraphKway(&agraph->nvtxs, &ncon, agraph->xadj, agraph->adjncy, agraph->vwgt, NULL, agraph->adjwgt, &lnparts, tpwgts, NULL, moptions, &edgecut, part); for (i=0; i<agraph->nvtxs; i++) gwhere0[agraph->label[i]] = fpart + part[i]; } gkMPI_Allreduce((void *)gwhere0, (void *)gwhere1, gnvtxs, IDX_T, MPI_SUM, ipcomm); if (ngroups > 1) { tmpxadj = agraph->xadj; tmpadjncy = agraph->adjncy; tmpadjwgt = agraph->adjwgt; tmpvwgt = agraph->vwgt; tmpwhere = agraph->where; agraph->xadj = xadj; agraph->adjncy = adjncy; agraph->adjwgt = adjwgt; agraph->vwgt = vwgt; agraph->where = gwhere1; agraph->vwgt = vwgt; agraph->nvtxs = gnvtxs; edgecut = ComputeSerialEdgeCut(agraph); ComputeSerialBalance(ctrl, agraph, gwhere1, lbvec); lbsum = rsum(ncon, lbvec, 1); gkMPI_Allreduce((void *)&edgecut, (void *)&max_cut, 1, IDX_T, MPI_MAX, ctrl->gcomm); gkMPI_Allreduce((void *)&lbsum, (void *)&min_lbsum, 1, REAL_T, MPI_MIN, ctrl->gcomm); lpesum.sum = lbsum; if (min_lbsum < UNBALANCE_FRACTION*ncon) { if (lbsum < UNBALANCE_FRACTION*ncon) lpesum.sum = edgecut; else lpesum.sum = max_cut; } lpesum.rank = ctrl->mype; gkMPI_Allreduce((void *)&lpesum, (void *)&gpesum, 1, MPI_DOUBLE_INT, MPI_MINLOC, ctrl->gcomm); gkMPI_Bcast((void *)gwhere1, gnvtxs, IDX_T, gpesum.rank, ctrl->gcomm); agraph->xadj = tmpxadj; agraph->adjncy = tmpadjncy; agraph->adjwgt = tmpadjwgt; agraph->vwgt = tmpvwgt; agraph->where = tmpwhere; } icopy(graph->nvtxs, gwhere1+graph->vtxdist[ctrl->mype], graph->where); FreeGraph(agraph); gkMPI_Comm_free(&ipcomm); IFSET(ctrl->dbglvl, DBG_TIME, gkMPI_Barrier(ctrl->comm)); IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->InitPartTmr)); WCOREPOP; }
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; }
void FM_2WayCutRefine(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niter) { idx_t i, ii, j, k, kwgt, nvtxs, nbnd, nswaps, from, to, pass, me, limit, tmp; idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where, *id, *ed, *bndptr, *bndind, *pwgts; idx_t *moved, *swaps, *perm; rpq_t *queues[2]; idx_t higain, mincut, mindiff, origdiff, initcut, newcut, mincutorder, avgvwgt; idx_t tpwgts[2]; WCOREPUSH; nvtxs = graph->nvtxs; xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; adjwgt = graph->adjwgt; where = graph->where; id = graph->id; ed = graph->ed; pwgts = graph->pwgts; bndptr = graph->bndptr; bndind = graph->bndind; moved = iwspacemalloc(ctrl, nvtxs); swaps = iwspacemalloc(ctrl, nvtxs); perm = iwspacemalloc(ctrl, nvtxs); tpwgts[0] = graph->tvwgt[0]*ntpwgts[0]; tpwgts[1] = graph->tvwgt[0]-tpwgts[0]; limit = gk_min(gk_max(0.01*nvtxs, 15), 100); avgvwgt = gk_min((pwgts[0]+pwgts[1])/20, 2*(pwgts[0]+pwgts[1])/nvtxs); queues[0] = rpqCreate(nvtxs); queues[1] = rpqCreate(nvtxs); IFSET(ctrl->dbglvl, METIS_DBG_REFINE, Print2WayRefineStats(ctrl, graph, ntpwgts, 0, -2)); origdiff = iabs(tpwgts[0]-pwgts[0]); iset(nvtxs, -1, moved); for (pass=0; pass<niter; pass++) { /* Do a number of passes */ rpqReset(queues[0]); rpqReset(queues[1]); mincutorder = -1; newcut = mincut = initcut = graph->mincut; mindiff = iabs(tpwgts[0]-pwgts[0]); ASSERT(ComputeCut(graph, where) == graph->mincut); ASSERT(CheckBnd(graph)); /* Insert boundary nodes in the priority queues */ nbnd = graph->nbnd; irandArrayPermute(nbnd, perm, nbnd, 1); for (ii=0; ii<nbnd; ii++) { i = perm[ii]; ASSERT(ed[bndind[i]] > 0 || id[bndind[i]] == 0); ASSERT(bndptr[bndind[i]] != -1); rpqInsert(queues[where[bndind[i]]], bndind[i], ed[bndind[i]]-id[bndind[i]]); } for (nswaps=0; nswaps<nvtxs; nswaps++) { from = (tpwgts[0]-pwgts[0] < tpwgts[1]-pwgts[1] ? 0 : 1); to = (from+1)%2; if ((higain = rpqGetTop(queues[from])) == -1) break; ASSERT(bndptr[higain] != -1); newcut -= (ed[higain]-id[higain]); INC_DEC(pwgts[to], pwgts[from], vwgt[higain]); if ((newcut < mincut && iabs(tpwgts[0]-pwgts[0]) <= origdiff+avgvwgt) || (newcut == mincut && iabs(tpwgts[0]-pwgts[0]) < mindiff)) { mincut = newcut; mindiff = iabs(tpwgts[0]-pwgts[0]); mincutorder = nswaps; } else if (nswaps-mincutorder > limit) { /* We hit the limit, undo last move */ newcut += (ed[higain]-id[higain]); INC_DEC(pwgts[from], pwgts[to], vwgt[higain]); break; } where[higain] = to; moved[higain] = nswaps; swaps[nswaps] = higain; IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, printf("Moved %6"PRIDX" from %"PRIDX". [%3"PRIDX" %3"PRIDX"] %5"PRIDX" [%4"PRIDX" %4"PRIDX"]\n", higain, from, ed[higain]-id[higain], vwgt[higain], newcut, pwgts[0], pwgts[1])); /************************************************************** * Update the id[i]/ed[i] values of the affected nodes ***************************************************************/ SWAP(id[higain], ed[higain], tmp); if (ed[higain] == 0 && xadj[higain] < xadj[higain+1]) BNDDelete(nbnd, bndind, bndptr, higain); for (j=xadj[higain]; j<xadj[higain+1]; j++) { k = adjncy[j]; kwgt = (to == where[k] ? adjwgt[j] : -adjwgt[j]); INC_DEC(id[k], ed[k], kwgt); /* Update its boundary information and queue position */ if (bndptr[k] != -1) { /* If k was a boundary vertex */ if (ed[k] == 0) { /* Not a boundary vertex any more */ BNDDelete(nbnd, bndind, bndptr, k); if (moved[k] == -1) /* Remove it if in the queues */ rpqDelete(queues[where[k]], k); } else { /* If it has not been moved, update its position in the queue */ if (moved[k] == -1) rpqUpdate(queues[where[k]], k, ed[k]-id[k]); } } else { if (ed[k] > 0) { /* It will now become a boundary vertex */ BNDInsert(nbnd, bndind, bndptr, k); if (moved[k] == -1) rpqInsert(queues[where[k]], k, ed[k]-id[k]); } } } } /**************************************************************** * Roll back computations *****************************************************************/ for (i=0; i<nswaps; i++) moved[swaps[i]] = -1; /* reset moved array */ for (nswaps--; nswaps>mincutorder; nswaps--) { higain = swaps[nswaps]; to = where[higain] = (where[higain]+1)%2; SWAP(id[higain], ed[higain], tmp); if (ed[higain] == 0 && bndptr[higain] != -1 && xadj[higain] < xadj[higain+1]) BNDDelete(nbnd, bndind, bndptr, higain); else if (ed[higain] > 0 && bndptr[higain] == -1) BNDInsert(nbnd, bndind, bndptr, higain); INC_DEC(pwgts[to], pwgts[(to+1)%2], vwgt[higain]); for (j=xadj[higain]; j<xadj[higain+1]; j++) { k = adjncy[j]; kwgt = (to == where[k] ? adjwgt[j] : -adjwgt[j]); INC_DEC(id[k], ed[k], kwgt); if (bndptr[k] != -1 && ed[k] == 0) BNDDelete(nbnd, bndind, bndptr, k); if (bndptr[k] == -1 && ed[k] > 0) BNDInsert(nbnd, bndind, bndptr, k); } } graph->mincut = mincut; graph->nbnd = nbnd; IFSET(ctrl->dbglvl, METIS_DBG_REFINE, Print2WayRefineStats(ctrl, graph, ntpwgts, 0, mincutorder)); if (mincutorder <= 0 || mincut == initcut) break; } rpqDestroy(queues[0]); rpqDestroy(queues[1]); WCOREPOP; }
void FM_Mc2WayCutRefine(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niter) { idx_t i, ii, j, k, l, kwgt, nvtxs, ncon, nbnd, nswaps, from, to, pass, me, limit, tmp, cnum; idx_t *xadj, *adjncy, *vwgt, *adjwgt, *pwgts, *where, *id, *ed, *bndptr, *bndind; idx_t *moved, *swaps, *perm, *qnum; idx_t higain, mincut, initcut, newcut, mincutorder; real_t *invtvwgt, *ubfactors, *minbalv, *newbalv; real_t origbal, minbal, newbal, rgain, ffactor; rpq_t **queues; WCOREPUSH; nvtxs = graph->nvtxs; ncon = graph->ncon; xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; adjwgt = graph->adjwgt; invtvwgt = graph->invtvwgt; where = graph->where; id = graph->id; ed = graph->ed; pwgts = graph->pwgts; bndptr = graph->bndptr; bndind = graph->bndind; moved = iwspacemalloc(ctrl, nvtxs); swaps = iwspacemalloc(ctrl, nvtxs); perm = iwspacemalloc(ctrl, nvtxs); qnum = iwspacemalloc(ctrl, nvtxs); ubfactors = rwspacemalloc(ctrl, ncon); newbalv = rwspacemalloc(ctrl, ncon); minbalv = rwspacemalloc(ctrl, ncon); limit = gk_min(gk_max(0.01*nvtxs, 25), 150); /* Determine a fudge factor to allow the refinement routines to get out of tight balancing constraints. */ ffactor = .5/gk_max(20, nvtxs); /* Initialize the queues */ queues = (rpq_t **)wspacemalloc(ctrl, 2*ncon*sizeof(rpq_t *)); for (i=0; i<2*ncon; i++) queues[i] = rpqCreate(nvtxs); for (i=0; i<nvtxs; i++) qnum[i] = iargmax_nrm(ncon, vwgt+i*ncon, invtvwgt); /* Determine the unbalance tolerance for each constraint. The tolerance is equal to the maximum of the original load imbalance and the user-supplied allowed tolerance. The rationale behind this approach is to allow the refinement routine to improve the cut, without having to worry about fixing load imbalance problems. The load imbalance is addressed by the balancing routines. */ origbal = ComputeLoadImbalanceDiffVec(graph, 2, ctrl->pijbm, ctrl->ubfactors, ubfactors); for (i=0; i<ncon; i++) ubfactors[i] = (ubfactors[i] > 0 ? ctrl->ubfactors[i]+ubfactors[i] : ctrl->ubfactors[i]); IFSET(ctrl->dbglvl, METIS_DBG_REFINE, Print2WayRefineStats(ctrl, graph, ntpwgts, origbal, -2)); iset(nvtxs, -1, moved); for (pass=0; pass<niter; pass++) { /* Do a number of passes */ for (i=0; i<2*ncon; i++) rpqReset(queues[i]); mincutorder = -1; newcut = mincut = initcut = graph->mincut; minbal = ComputeLoadImbalanceDiffVec(graph, 2, ctrl->pijbm, ubfactors, minbalv); ASSERT(ComputeCut(graph, where) == graph->mincut); ASSERT(CheckBnd(graph)); /* Insert boundary nodes in the priority queues */ nbnd = graph->nbnd; irandArrayPermute(nbnd, perm, nbnd/5, 1); for (ii=0; ii<nbnd; ii++) { i = bndind[perm[ii]]; ASSERT(ed[i] > 0 || id[i] == 0); ASSERT(bndptr[i] != -1); //rgain = 1.0*(ed[i]-id[i])/sqrt(vwgt[i*ncon+qnum[i]]+1); //rgain = (ed[i]-id[i] > 0 ? 1.0*(ed[i]-id[i])/sqrt(vwgt[i*ncon+qnum[i]]+1) : ed[i]-id[i]); rgain = ed[i]-id[i]; rpqInsert(queues[2*qnum[i]+where[i]], i, rgain); } for (nswaps=0; nswaps<nvtxs; nswaps++) { SelectQueue(graph, ctrl->pijbm, ubfactors, queues, &from, &cnum); to = (from+1)%2; if (from == -1 || (higain = rpqGetTop(queues[2*cnum+from])) == -1) break; ASSERT(bndptr[higain] != -1); newcut -= (ed[higain]-id[higain]); iaxpy(ncon, 1, vwgt+higain*ncon, 1, pwgts+to*ncon, 1); iaxpy(ncon, -1, vwgt+higain*ncon, 1, pwgts+from*ncon, 1); newbal = ComputeLoadImbalanceDiffVec(graph, 2, ctrl->pijbm, ubfactors, newbalv); if ((newcut < mincut && newbal <= ffactor) || (newcut == mincut && (newbal < minbal || (newbal == minbal && BetterBalance2Way(ncon, minbalv, newbalv))))) { mincut = newcut; minbal = newbal; mincutorder = nswaps; rcopy(ncon, newbalv, minbalv); } else if (nswaps-mincutorder > limit) { /* We hit the limit, undo last move */ newcut += (ed[higain]-id[higain]); iaxpy(ncon, 1, vwgt+higain*ncon, 1, pwgts+from*ncon, 1); iaxpy(ncon, -1, vwgt+higain*ncon, 1, pwgts+to*ncon, 1); break; } where[higain] = to; moved[higain] = nswaps; swaps[nswaps] = higain; if (ctrl->dbglvl&METIS_DBG_MOVEINFO) { printf("Moved%6"PRIDX" from %"PRIDX"(%"PRIDX") Gain:%5"PRIDX", " "Cut:%5"PRIDX", NPwgts:", higain, from, cnum, ed[higain]-id[higain], newcut); for (l=0; l<ncon; l++) printf("(%.3"PRREAL" %.3"PRREAL")", pwgts[l]*invtvwgt[l], pwgts[ncon+l]*invtvwgt[l]); printf(" %+.3"PRREAL" LB: %.3"PRREAL"(%+.3"PRREAL")\n", minbal, ComputeLoadImbalance(graph, 2, ctrl->pijbm), newbal); } /************************************************************** * Update the id[i]/ed[i] values of the affected nodes ***************************************************************/ SWAP(id[higain], ed[higain], tmp); if (ed[higain] == 0 && xadj[higain] < xadj[higain+1]) BNDDelete(nbnd, bndind, bndptr, higain); for (j=xadj[higain]; j<xadj[higain+1]; j++) { k = adjncy[j]; kwgt = (to == where[k] ? adjwgt[j] : -adjwgt[j]); INC_DEC(id[k], ed[k], kwgt); /* Update its boundary information and queue position */ if (bndptr[k] != -1) { /* If k was a boundary vertex */ if (ed[k] == 0) { /* Not a boundary vertex any more */ BNDDelete(nbnd, bndind, bndptr, k); if (moved[k] == -1) /* Remove it if in the queues */ rpqDelete(queues[2*qnum[k]+where[k]], k); } else { /* If it has not been moved, update its position in the queue */ if (moved[k] == -1) { //rgain = 1.0*(ed[k]-id[k])/sqrt(vwgt[k*ncon+qnum[k]]+1); //rgain = (ed[k]-id[k] > 0 ? // 1.0*(ed[k]-id[k])/sqrt(vwgt[k*ncon+qnum[k]]+1) : ed[k]-id[k]); rgain = ed[k]-id[k]; rpqUpdate(queues[2*qnum[k]+where[k]], k, rgain); } } } else { if (ed[k] > 0) { /* It will now become a boundary vertex */ BNDInsert(nbnd, bndind, bndptr, k); if (moved[k] == -1) { //rgain = 1.0*(ed[k]-id[k])/sqrt(vwgt[k*ncon+qnum[k]]+1); //rgain = (ed[k]-id[k] > 0 ? // 1.0*(ed[k]-id[k])/sqrt(vwgt[k*ncon+qnum[k]]+1) : ed[k]-id[k]); rgain = ed[k]-id[k]; rpqInsert(queues[2*qnum[k]+where[k]], k, rgain); } } } } } /**************************************************************** * Roll back computations *****************************************************************/ for (i=0; i<nswaps; i++) moved[swaps[i]] = -1; /* reset moved array */ for (nswaps--; nswaps>mincutorder; nswaps--) { higain = swaps[nswaps]; to = where[higain] = (where[higain]+1)%2; SWAP(id[higain], ed[higain], tmp); if (ed[higain] == 0 && bndptr[higain] != -1 && xadj[higain] < xadj[higain+1]) BNDDelete(nbnd, bndind, bndptr, higain); else if (ed[higain] > 0 && bndptr[higain] == -1) BNDInsert(nbnd, bndind, bndptr, higain); iaxpy(ncon, 1, vwgt+higain*ncon, 1, pwgts+to*ncon, 1); iaxpy(ncon, -1, vwgt+higain*ncon, 1, pwgts+((to+1)%2)*ncon, 1); for (j=xadj[higain]; j<xadj[higain+1]; j++) { k = adjncy[j]; kwgt = (to == where[k] ? adjwgt[j] : -adjwgt[j]); INC_DEC(id[k], ed[k], kwgt); if (bndptr[k] != -1 && ed[k] == 0) BNDDelete(nbnd, bndind, bndptr, k); if (bndptr[k] == -1 && ed[k] > 0) BNDInsert(nbnd, bndind, bndptr, k); } } graph->mincut = mincut; graph->nbnd = nbnd; IFSET(ctrl->dbglvl, METIS_DBG_REFINE, Print2WayRefineStats(ctrl, graph, ntpwgts, minbal, mincutorder)); if (mincutorder <= 0 || mincut == initcut) break; } for (i=0; i<2*ncon; i++) rpqDestroy(queues[i]); WCOREPOP; }
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; }
/************************************************************************* * This function performs a k-way directed diffusion **************************************************************************/ real_t WavefrontDiffusion(ctrl_t *ctrl, graph_t *graph, idx_t *home) { idx_t ii, i, j, k, l, nvtxs, nedges, nparts; idx_t from, to, edge, done, nswaps, noswaps, totalv, wsize; idx_t npasses, first, second, third, mind, maxd; idx_t *xadj, *adjncy, *adjwgt, *where, *perm; idx_t *rowptr, *colind, *ed, *psize; real_t *transfer, *tmpvec; real_t balance = -1.0, *load, *solution, *workspace; real_t *nvwgt, *npwgts, flowFactor, cost, ubfactor; matrix_t matrix; ikv_t *cand; idx_t ndirty, nclean, dptr, clean; nvtxs = graph->nvtxs; nedges = graph->nedges; xadj = graph->xadj; nvwgt = graph->nvwgt; adjncy = graph->adjncy; adjwgt = graph->adjwgt; where = graph->where; nparts = ctrl->nparts; ubfactor = ctrl->ubvec[0]; matrix.nrows = nparts; flowFactor = 0.35; flowFactor = (ctrl->mype == 2) ? 0.50 : flowFactor; flowFactor = (ctrl->mype == 3) ? 0.75 : flowFactor; flowFactor = (ctrl->mype == 4) ? 1.00 : flowFactor; /* allocate memory */ solution = rmalloc(4*nparts+2*nedges, "WavefrontDiffusion: solution"); tmpvec = solution + nparts; npwgts = solution + 2*nparts; load = solution + 3*nparts; matrix.values = solution + 4*nparts; transfer = matrix.transfer = solution + 4*nparts + nedges; perm = imalloc(2*nvtxs+2*nparts+nedges+1, "WavefrontDiffusion: perm"); ed = perm + nvtxs; psize = perm + 2*nvtxs; rowptr = matrix.rowptr = perm + 2*nvtxs + nparts; colind = matrix.colind = perm + 2*nvtxs + 2*nparts + 1; /*GKTODO - Potential problem with this malloc */ wsize = gk_max(sizeof(real_t)*nparts*6, sizeof(idx_t)*(nvtxs+nparts*2+1)); workspace = (real_t *)gk_malloc(wsize, "WavefrontDiffusion: workspace"); cand = ikvmalloc(nvtxs, "WavefrontDiffusion: cand"); /*****************************/ /* Populate empty subdomains */ /*****************************/ iset(nparts, 0, psize); for (i=0; i<nvtxs; i++) psize[where[i]]++; mind = iargmin(nparts, psize); maxd = iargmax(nparts, psize); if (psize[mind] == 0) { for (i=0; i<nvtxs; i++) { k = (RandomInRange(nvtxs)+i)%nvtxs; if (where[k] == maxd) { where[k] = mind; psize[mind]++; psize[maxd]--; break; } } } iset(nvtxs, 0, ed); rset(nparts, 0.0, npwgts); for (i=0; i<nvtxs; i++) { npwgts[where[i]] += nvwgt[i]; for (j=xadj[i]; j<xadj[i+1]; j++) ed[i] += (where[i] != where[adjncy[j]] ? adjwgt[j] : 0); } ComputeLoad(graph, nparts, load, ctrl->tpwgts, 0); done = 0; /* zero out the tmpvec array */ rset(nparts, 0.0, tmpvec); npasses = gk_min(nparts/2, NGD_PASSES); for (l=0; l<npasses; l++) { /* Set-up and solve the diffusion equation */ nswaps = 0; /************************/ /* Solve flow equations */ /************************/ SetUpConnectGraph(graph, &matrix, (idx_t *)workspace); /* check for disconnected subdomains */ for(i=0; i<matrix.nrows; i++) { if (matrix.rowptr[i]+1 == matrix.rowptr[i+1]) { cost = (real_t)(ctrl->mype); goto CleanUpAndExit; } } ConjGrad2(&matrix, load, solution, 0.001, workspace); ComputeTransferVector(1, &matrix, solution, transfer, 0); GetThreeMax(nparts, load, &first, &second, &third); if (l%3 == 0) { FastRandomPermute(nvtxs, perm, 1); } else { /*****************************/ /* move dirty vertices first */ /*****************************/ ndirty = 0; for (i=0; i<nvtxs; i++) { if (where[i] != home[i]) ndirty++; } dptr = 0; for (i=0; i<nvtxs; i++) { if (where[i] != home[i]) perm[dptr++] = i; else perm[ndirty++] = i; } PASSERT(ctrl, ndirty == nvtxs); ndirty = dptr; nclean = nvtxs-dptr; FastRandomPermute(ndirty, perm, 0); FastRandomPermute(nclean, perm+ndirty, 0); } if (ctrl->mype == 0) { for (j=nvtxs, k=0, ii=0; ii<nvtxs; ii++) { i = perm[ii]; if (ed[i] != 0) { cand[k].key = -ed[i]; cand[k++].val = i; } else { cand[--j].key = 0; cand[j].val = i; } } ikvsorti(k, cand); } for (ii=0; ii<nvtxs/3; ii++) { i = (ctrl->mype == 0) ? cand[ii].val : perm[ii]; from = where[i]; /* don't move out the last vertex in a subdomain */ if (psize[from] == 1) continue; clean = (from == home[i]) ? 1 : 0; /* only move from top three or dirty vertices */ if (from != first && from != second && from != third && clean) continue; /* Scatter the sparse transfer row into the dense tmpvec row */ for (j=rowptr[from]+1; j<rowptr[from+1]; j++) tmpvec[colind[j]] = transfer[j]; for (j=xadj[i]; j<xadj[i+1]; j++) { to = where[adjncy[j]]; if (from != to) { if (tmpvec[to] > (flowFactor * nvwgt[i])) { tmpvec[to] -= nvwgt[i]; INC_DEC(psize[to], psize[from], 1); INC_DEC(npwgts[to], npwgts[from], nvwgt[i]); INC_DEC(load[to], load[from], nvwgt[i]); where[i] = to; nswaps++; /* Update external degrees */ ed[i] = 0; for (k=xadj[i]; k<xadj[i+1]; k++) { edge = adjncy[k]; ed[i] += (to != where[edge] ? adjwgt[k] : 0); if (where[edge] == from) ed[edge] += adjwgt[k]; if (where[edge] == to) ed[edge] -= adjwgt[k]; } break; } } } /* Gather the dense tmpvec row into the sparse transfer row */ for (j=rowptr[from]+1; j<rowptr[from+1]; j++) { transfer[j] = tmpvec[colind[j]]; tmpvec[colind[j]] = 0.0; } ASSERT(fabs(rsum(nparts, tmpvec, 1)) < .0001) } if (l % 2 == 1) { balance = rmax(nparts, npwgts)*nparts; if (balance < ubfactor + 0.035) done = 1; if (GlobalSESum(ctrl, done) > 0) break; noswaps = (nswaps > 0) ? 0 : 1; if (GlobalSESum(ctrl, noswaps) > ctrl->npes/2) break; } } graph->mincut = ComputeSerialEdgeCut(graph); totalv = Mc_ComputeSerialTotalV(graph, home); cost = ctrl->ipc_factor * (real_t)graph->mincut + ctrl->redist_factor * (real_t)totalv; CleanUpAndExit: gk_free((void **)&solution, (void **)&perm, (void **)&workspace, (void **)&cand, LTERM); return cost; }
/************************************************************************* * Let the game begin **************************************************************************/ int main(int argc, char *argv[]) { idxtype i, j, istep, options[10], nn, ne, fstep, lstep, nparts, nboxes, u[3], dim, nchanges, ncomm; char filename[256]; idxtype *mien, *mrng, *part, *oldpart, *sflag, *bestdims, *fepart; double *mxyz, *bxyz; idxtype *xadj, *adjncy, *cntptr, *cntind; idxtype numflag = 0, wgtflag = 0, edgecut, etype=2; void *cinfo; FILE *fpin; long long int *ltmp; if (argc != 6) { mfprintf(stderr, "Usage: %s <nn> <ne> <fstep> <lstep> <nparts>\n", argv[0]); exit(0); } nn = atoi(argv[1]); ne = atoi(argv[2]); fstep = atoi(argv[3]); lstep = atoi(argv[4]); nparts = atoi(argv[5]); mprintf("Reading %s, nn: %D, ne: %D, fstep: %D, lstep: %D, nparts: %D\n", filename, nn, ne, fstep, lstep, nparts); mien = idxmalloc(4*ne, "main: mien"); mxyz = gk_dmalloc(3*nn, "main: mxyz"); mrng = idxmalloc(4*ne, "main: mrng"); bxyz = gk_dmalloc(6*ne*4, "main: bxyz"); fepart = idxmalloc(nn, "main: fepart"); part = idxmalloc(nn, "main: part"); oldpart = idxmalloc(nn, "main: oldpart"); sflag = idxmalloc(nn, "main: sflag"); bestdims = idxsmalloc(2*nparts, -1, "main: bestdims"); xadj = idxmalloc(nn+1, "main: xadj"); adjncy = idxmalloc(50*nn, "main: adjncy"); /*======================================================================== * Read the initial mesh and setup the graph and contact information *========================================================================*/ msprintf(filename, "mien.%04D", fstep); fpin = GKfopen(filename, "rb", "main: mien"); fread(mien, sizeof(int), 4*ne, fpin); for (i=0; i<4*ne; i++) mien[i] = Flip_int32(mien[i]); GKfclose(fpin); msprintf(filename, "mxyz.%04D", fstep); fpin = GKfopen(filename, "rb", "main: mxyz"); fread(mxyz, sizeof(double), 3*nn, fpin); for (i=0; i<3*nn; i++) { ltmp = (long long int *)(mxyz+i); *ltmp = Flip_int64(*ltmp); } GKfclose(fpin); mprintf("%e %e %e\n", mxyz[3*0+0], mxyz[3*0+1], mxyz[3*0+2]); msprintf(filename, "mrng.%04D", fstep); fpin = GKfopen(filename, "rb", "main: mrng"); fread(mrng, sizeof(int), 4*ne, fpin); for (i=0; i<4*ne; i++) mrng[i] = Flip_int32(mrng[i]); GKfclose(fpin); /*======================================================================== * Determine which nodes are in the surface *========================================================================*/ iset(nn, 0, sflag); for (i=0; i<ne; i++) { if (mrng[4*i+0] > 0) { /* 1, 2, 3 */ sflag[mien[4*i+0]-1] = 1; sflag[mien[4*i+1]-1] = 1; sflag[mien[4*i+2]-1] = 1; } if (mrng[4*i+1] > 0) { /* 1, 2, 4 */ sflag[mien[4*i+0]-1] = 1; sflag[mien[4*i+1]-1] = 1; sflag[mien[4*i+3]-1] = 1; } if (mrng[4*i+2] > 0) { /* 2, 3, 4 */ sflag[mien[4*i+1]-1] = 1; sflag[mien[4*i+2]-1] = 1; sflag[mien[4*i+3]-1] = 1; } if (mrng[4*i+3] > 0) { /* 1, 3, 4 */ sflag[mien[4*i+0]-1] = 1; sflag[mien[4*i+2]-1] = 1; sflag[mien[4*i+3]-1] = 1; } } mprintf("Contact Nodes: %D of %D\n", isum(nn, sflag), nn); /*======================================================================== * Compute the FE partition *========================================================================*/ numflag = mien[idxargmin(4*ne, mien)]; METIS_MeshToNodal(&ne, &nn, mien, &etype, &numflag, xadj, adjncy); options[0] = 0; METIS_PartGraphVKway(&nn, xadj, adjncy, NULL, NULL, &wgtflag, &numflag, &nparts, options, &edgecut, fepart); mprintf("K-way partitioning Volume: %D\n", edgecut); /*======================================================================== * Get into the loop in which you go over the different configurations *========================================================================*/ for (istep=fstep; istep<=lstep; istep++) { msprintf(filename, "mxyz.%04D", istep); mprintf("Reading %s...............................................................\n", filename); fpin = GKfopen(filename, "rb", "main: mxyz"); fread(mxyz, sizeof(double), 3*nn, fpin); for (i=0; i<3*nn; i++) { ltmp = (long long int *)(mxyz+i); *ltmp = Flip_int64(*ltmp); } GKfclose(fpin); msprintf(filename, "mrng.%04D", istep); fpin = GKfopen(filename, "rb", "main: mrng"); fread(mrng, sizeof(int), 4*ne, fpin); for (i=0; i<4*ne; i++) mrng[i] = Flip_int32(mrng[i]); GKfclose(fpin); /* Determine which nodes are in the surface */ iset(nn, 0, sflag); for (i=0; i<ne; i++) { if (mrng[4*i+0] > 0) { /* 1, 2, 3 */ sflag[mien[4*i+0]-1] = 1; sflag[mien[4*i+1]-1] = 1; sflag[mien[4*i+2]-1] = 1; } if (mrng[4*i+1] > 0) { /* 1, 2, 4 */ sflag[mien[4*i+0]-1] = 1; sflag[mien[4*i+1]-1] = 1; sflag[mien[4*i+3]-1] = 1; } if (mrng[4*i+2] > 0) { /* 2, 3, 4 */ sflag[mien[4*i+1]-1] = 1; sflag[mien[4*i+2]-1] = 1; sflag[mien[4*i+3]-1] = 1; } if (mrng[4*i+3] > 0) { /* 1, 3, 4 */ sflag[mien[4*i+0]-1] = 1; sflag[mien[4*i+2]-1] = 1; sflag[mien[4*i+3]-1] = 1; } } mprintf("Contact Nodes: %D of %D\n", isum(nn, sflag), nn); /* Determine the bounding boxes of the surface elements */ for (nboxes=0, i=0; i<ne; i++) { if (mrng[4*i+0] > 0) { /* 1, 2, 3 */ u[0] = mien[4*i+0]-1; u[1] = mien[4*i+1]-1; u[2] = mien[4*i+2]-1; bxyz[6*nboxes+0] = bxyz[6*nboxes+3] = mxyz[3*u[0]+0]; bxyz[6*nboxes+1] = bxyz[6*nboxes+4] = mxyz[3*u[0]+1]; bxyz[6*nboxes+2] = bxyz[6*nboxes+5] = mxyz[3*u[0]+2]; for (j=1; j<3; j++) { for (dim=0; dim<3; dim++) { bxyz[6*nboxes+dim] = (bxyz[6*nboxes+dim] > mxyz[3*u[j]+dim] ? mxyz[3*u[j]+dim] : bxyz[6*nboxes+dim]); bxyz[6*nboxes+3+dim] = (bxyz[6*nboxes+3+dim] < mxyz[3*u[j]+dim] ? mxyz[3*u[j]+dim] : bxyz[6*nboxes+3+dim]); } } nboxes++; } if (mrng[4*i+1] > 0) { /* 1, 2, 4 */ u[0] = mien[4*i+0]-1; u[1] = mien[4*i+1]-1; u[2] = mien[4*i+3]-1; bxyz[6*nboxes+0] = bxyz[6*nboxes+3] = mxyz[3*u[0]+0]; bxyz[6*nboxes+1] = bxyz[6*nboxes+4] = mxyz[3*u[0]+1]; bxyz[6*nboxes+2] = bxyz[6*nboxes+5] = mxyz[3*u[0]+2]; for (j=1; j<3; j++) { for (dim=0; dim<3; dim++) { bxyz[6*nboxes+dim] = (bxyz[6*nboxes+dim] > mxyz[3*u[j]+dim] ? mxyz[3*u[j]+dim] : bxyz[6*nboxes+dim]); bxyz[6*nboxes+3+dim] = (bxyz[6*nboxes+3+dim] < mxyz[3*u[j]+dim] ? mxyz[3*u[j]+dim] : bxyz[6*nboxes+3+dim]); } } nboxes++; } if (mrng[4*i+2] > 0) { /* 2, 3, 4 */ u[0] = mien[4*i+1]-1; u[1] = mien[4*i+2]-1; u[2] = mien[4*i+3]-1; bxyz[6*nboxes+0] = bxyz[6*nboxes+3] = mxyz[3*u[0]+0]; bxyz[6*nboxes+1] = bxyz[6*nboxes+4] = mxyz[3*u[0]+1]; bxyz[6*nboxes+2] = bxyz[6*nboxes+5] = mxyz[3*u[0]+2]; for (j=1; j<3; j++) { for (dim=0; dim<3; dim++) { bxyz[6*nboxes+dim] = (bxyz[6*nboxes+dim] > mxyz[3*u[j]+dim] ? mxyz[3*u[j]+dim] : bxyz[6*nboxes+dim]); bxyz[6*nboxes+3+dim] = (bxyz[6*nboxes+3+dim] < mxyz[3*u[j]+dim] ? mxyz[3*u[j]+dim] : bxyz[6*nboxes+3+dim]); } } nboxes++; } if (mrng[4*i+3] > 0) { /* 1, 3, 4 */ u[0] = mien[4*i+0]-1; u[1] = mien[4*i+2]-1; u[2] = mien[4*i+3]-1; bxyz[6*nboxes+0] = bxyz[6*nboxes+3] = mxyz[3*u[0]+0]; bxyz[6*nboxes+1] = bxyz[6*nboxes+4] = mxyz[3*u[0]+1]; bxyz[6*nboxes+2] = bxyz[6*nboxes+5] = mxyz[3*u[0]+2]; for (j=1; j<3; j++) { for (dim=0; dim<3; dim++) { bxyz[6*nboxes+dim] = (bxyz[6*nboxes+dim] > mxyz[3*u[j]+dim] ? mxyz[3*u[j]+dim] : bxyz[6*nboxes+dim]); bxyz[6*nboxes+3+dim] = (bxyz[6*nboxes+3+dim] < mxyz[3*u[j]+dim] ? mxyz[3*u[j]+dim] : bxyz[6*nboxes+3+dim]); } } nboxes++; } } cinfo = METIS_PartSurfForContactRCB(&nn, mxyz, sflag, &nparts, part, bestdims); METIS_FindContacts(cinfo, &nboxes, bxyz, &nparts, &cntptr, &cntind); METIS_FreeContactInfo(cinfo); nchanges = 0; if (istep > fstep) { for (i=0; i<nn; i++) nchanges += (part[i] != oldpart[i] ? 1 : 0); } idxcopy(nn, part, oldpart); ncomm = ComputeMapCost(nn, nparts, fepart, part); mprintf("Contacting Elements: %D Indices: %D Nchanges: %D MapCost: %D\n", nboxes, cntptr[nboxes]-nboxes, nchanges, ncomm); gk_free((void **)&cntptr, &cntind, LTERM); } }
int main() { initStrings(); localizeStrings(PageLabels); localizeNewMenu(menu); if(!(OpenURLBase = IExec->OpenLibrary(OPENURLNAME, OPENURLVER))) return -1; if(!(IOpenURL = (struct OpenURLIFace*)IExec->GetInterface(OpenURLBase, "main", 1L, NULL))) return -1; RA_SetUpHook(idcmphook, IDCMPFunc, NULL); if((AppPort = IExec->AllocSysObjectTags(ASOT_PORT, TAG_DONE)) != NULL) { IExec->NewList(&list_Brow); IExec->NewList(&list_Mail); IExec->NewList(&list_FTPs); win = make_window(); edit_brow_win = make_edit_brow_win(); edit_mail_win = make_edit_mail_win(); edit_ftp_win = make_edit_ftp_win(); loadPrefs(URL_GetPrefs_Mode_InUse); // Set up inter-group label alignment iset(OBJ(OBJ_FTP_ALIGN1), LAYOUT_AlignLabels, OBJ(OBJ_FTP_ALIGN2)); iset(OBJ(OBJ_MAIL_ALIGN1), LAYOUT_AlignLabels, OBJ(OBJ_MAIL_ALIGN2)); iset(OBJ(OBJ_LBROWSER_BROW), ICA_TARGET, OBJ(OBJ_EDIT_BROW), ICA_MAP, lst2btn); if((window = RA_OpenWindow(win)) != NULL) { uint32 sigmask; BOOL done = FALSE; sigmask = iget(win, WINDOW_SigMask); while (!done) { uint32 siggot; siggot = IExec->Wait(sigmask); if (siggot & sigmask) { done = HandleInput_Main_Win(); HandleInput_Edit_Brow_Win(); HandleInput_Edit_Mail_Win(); HandleInput_Edit_FTP_Win(); } } } IIntuition->DisposeObject(edit_ftp_win); IIntuition->DisposeObject(edit_mail_win); IIntuition->DisposeObject(edit_brow_win); IIntuition->DisposeObject(win); // The hidden chooser isn't attached to anything, // so we must dispose of it ourselves... IIntuition->DisposeObject(OBJ(OBJ_HIDDEN_CHOOSER)); IListBrowser->FreeListBrowserList(&list_FTPs); IListBrowser->FreeListBrowserList(&list_Mail); IListBrowser->FreeListBrowserList(&list_Brow); IExec->FreeSysObject(ASOT_PORT, AppPort); } IExec->DropInterface((struct Interface*)IOpenURL); IExec->CloseLibrary(OpenURLBase); uninitStrings(); return 0; }