⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sfm.c

📁 多层权核k均值算法
💻 C
📖 第 1 页 / 共 3 页
字号:
* one-way version **************************************************************************/void FM_2WayNodeRefine_OneSided(CtrlType *ctrl, GraphType *graph, float ubfactor, int npasses){  int i, ii, j, k, jj, kk, nvtxs, nbnd, nswaps, nmind;  idxtype *xadj, *vwgt, *adjncy, *where, *pwgts, *edegrees, *bndind, *bndptr;  idxtype *mptr, *mind, *swaps, *perm;  PQueueType parts;   NRInfoType *rinfo;  int higain, oldgain, mincut, initcut, mincutorder;	  int pass, to, other, limit;  int badmaxpwgt, mindiff, newdiff;  nvtxs = graph->nvtxs;  xadj = graph->xadj;  adjncy = graph->adjncy;  vwgt = graph->vwgt;  bndind = graph->bndind;  bndptr = graph->bndptr;  where = graph->where;  pwgts = graph->pwgts;  rinfo = graph->nrinfo;  PQueueInit(ctrl, &parts, nvtxs, ComputeMaxNodeGain(nvtxs, xadj, adjncy, vwgt));  perm = idxwspacemalloc(ctrl, nvtxs);  swaps = idxwspacemalloc(ctrl, nvtxs);  mptr = idxwspacemalloc(ctrl, nvtxs);  mind = idxwspacemalloc(ctrl, nvtxs+1);  IFSET(ctrl->dbglvl, DBG_REFINE,    printf("Partitions-N1: [%6d %6d] Nv-Nb[%6d %6d]. ISep: %6d\n", pwgts[0], pwgts[1], graph->nvtxs, graph->nbnd, graph->mincut));  badmaxpwgt = (int)(ubfactor*(pwgts[0]+pwgts[1]+pwgts[2])/2);  to = (pwgts[0] < pwgts[1] ? 1 : 0);  for (pass=0; pass<npasses; pass++) {    other = to;     to = (to+1)%2;    PQueueReset(&parts);    mincutorder = -1;    initcut = mincut = graph->mincut;    nbnd = graph->nbnd;    RandomPermute(nbnd, perm, 1);    for (ii=0; ii<nbnd; ii++) {      i = bndind[perm[ii]];      ASSERT(where[i] == 2);      PQueueInsert(&parts, i, vwgt[i]-rinfo[i].edegrees[other]);    }    ASSERT(CheckNodeBnd(graph, nbnd));    ASSERT(CheckNodePartitionParams(graph));    limit = (ctrl->oflags&OFLAG_COMPRESS ? amin(5*nbnd, 400) : amin(2*nbnd, 300));    /******************************************************    * Get into the FM loop    *******************************************************/    mptr[0] = nmind = 0;    mindiff = abs(pwgts[0]-pwgts[1]);    for (nswaps=0; nswaps<nvtxs; nswaps++) {      if ((higain = PQueueGetMax(&parts)) == -1)        break;      ASSERT(bndptr[higain] != -1);      if (pwgts[to]+vwgt[higain] > badmaxpwgt)        break;  /* No point going any further. Balance will be bad */      pwgts[2] -= (vwgt[higain]-rinfo[higain].edegrees[other]);      newdiff = abs(pwgts[to]+vwgt[higain] - (pwgts[other]-rinfo[higain].edegrees[other]));      if (pwgts[2] < mincut || (pwgts[2] == mincut && newdiff < mindiff)) {        mincut = pwgts[2];        mincutorder = nswaps;        mindiff = newdiff;      }      else {        if (nswaps - mincutorder > limit) {          pwgts[2] += (vwgt[higain]-rinfo[higain].edegrees[other]);          break; /* No further improvement, break out */        }      }      BNDDelete(nbnd, bndind, bndptr, higain);      pwgts[to] += vwgt[higain];      where[higain] = to;      swaps[nswaps] = higain;        /**********************************************************      * Update the degrees of the affected nodes      ***********************************************************/      for (j=xadj[higain]; j<xadj[higain+1]; j++) {        k = adjncy[j];        if (where[k] == 2) { /* For the in-separator vertices modify their edegree[to] */          rinfo[k].edegrees[to] += vwgt[higain];        }        else if (where[k] == other) { /* This vertex is pulled into the separator */          ASSERTP(bndptr[k] == -1, ("%d %d %d\n", k, bndptr[k], where[k]));          BNDInsert(nbnd, bndind, bndptr, k);          mind[nmind++] = k;  /* Keep track for rollback */          where[k] = 2;          pwgts[other] -= vwgt[k];          edegrees = rinfo[k].edegrees;          edegrees[0] = edegrees[1] = 0;          for (jj=xadj[k]; jj<xadj[k+1]; jj++) {            kk = adjncy[jj];            if (where[kk] != 2)               edegrees[where[kk]] += vwgt[kk];            else {              oldgain = vwgt[kk]-rinfo[kk].edegrees[other];              rinfo[kk].edegrees[other] -= vwgt[k];              /* Since the moves are one-sided this vertex has not been moved yet */              PQueueUpdateUp(&parts, kk, oldgain, oldgain+vwgt[k]);             }          }          /* Insert the new vertex into the priority queue. Safe due to one-sided moves */          PQueueInsert(&parts, k, vwgt[k]-edegrees[other]);        }      }      mptr[nswaps+1] = nmind;      IFSET(ctrl->dbglvl, DBG_MOVEINFO,            printf("Moved %6d to %3d, Gain: %5d [%5d] \t[%5d %5d %5d] [%3d %2d]\n",                        higain, to, (vwgt[higain]-rinfo[higain].edegrees[other]), vwgt[higain], pwgts[0], pwgts[1], pwgts[2], nswaps, limit));    }    /****************************************************************    * Roll back computation     *****************************************************************/    for (nswaps--; nswaps>mincutorder; nswaps--) {      higain = swaps[nswaps];      ASSERT(CheckNodePartitionParams(graph));      ASSERT(where[higain] == to);      INC_DEC(pwgts[2], pwgts[to], vwgt[higain]);      where[higain] = 2;      BNDInsert(nbnd, bndind, bndptr, higain);      edegrees = rinfo[higain].edegrees;      edegrees[0] = edegrees[1] = 0;      for (j=xadj[higain]; j<xadj[higain+1]; j++) {        k = adjncy[j];        if (where[k] == 2)           rinfo[k].edegrees[to] -= vwgt[higain];        else          edegrees[where[k]] += vwgt[k];      }      /* Push nodes out of the separator */      for (j=mptr[nswaps]; j<mptr[nswaps+1]; j++) {        k = mind[j];        ASSERT(where[k] == 2);        where[k] = other;        INC_DEC(pwgts[other], pwgts[2], vwgt[k]);        BNDDelete(nbnd, bndind, bndptr, k);        for (jj=xadj[k]; jj<xadj[k+1]; jj++) {          kk = adjncy[jj];          if (where[kk] == 2)             rinfo[kk].edegrees[other] += vwgt[k];        }      }    }    ASSERT(mincut == pwgts[2]);    IFSET(ctrl->dbglvl, DBG_REFINE,      printf("\tMinimum sep: %6d at %5d, PWGTS: [%6d %6d], NBND: %6d\n", mincut, mincutorder, pwgts[0], pwgts[1], nbnd));    graph->mincut = mincut;    graph->nbnd = nbnd;    if (pass%2 == 1 && (mincutorder == -1 || mincut >= initcut))      break;  }  PQueueFree(ctrl, &parts);  idxwspacefree(ctrl, nvtxs+1);  idxwspacefree(ctrl, nvtxs);  idxwspacefree(ctrl, nvtxs);  idxwspacefree(ctrl, nvtxs);}/************************************************************************** This function performs a node-based FM refinement **************************************************************************/void FM_2WayNodeBalance(CtrlType *ctrl, GraphType *graph, float ubfactor){  int i, ii, j, k, jj, kk, nvtxs, nbnd, nswaps;  idxtype *xadj, *vwgt, *adjncy, *where, *pwgts, *edegrees, *bndind, *bndptr;  idxtype *perm, *moved;  PQueueType parts;   NRInfoType *rinfo;  int higain, oldgain;	  int pass, to, other;  nvtxs = graph->nvtxs;  xadj = graph->xadj;  adjncy = graph->adjncy;  vwgt = graph->vwgt;  bndind = graph->bndind;  bndptr = graph->bndptr;  where = graph->where;  pwgts = graph->pwgts;  rinfo = graph->nrinfo;  if (abs(pwgts[0]-pwgts[1]) < (int)((ubfactor-1.0)*(pwgts[0]+pwgts[1])))    return;  if (abs(pwgts[0]-pwgts[1]) < 3*idxsum(nvtxs, vwgt)/nvtxs)    return;  to = (pwgts[0] < pwgts[1] ? 0 : 1);   other = (to+1)%2;  PQueueInit(ctrl, &parts, nvtxs, ComputeMaxNodeGain(nvtxs, xadj, adjncy, vwgt));  perm = idxwspacemalloc(ctrl, nvtxs);  moved = idxset(nvtxs, -1, idxwspacemalloc(ctrl, nvtxs));  IFSET(ctrl->dbglvl, DBG_REFINE,    printf("Partitions: [%6d %6d] Nv-Nb[%6d %6d]. ISep: %6d [B]\n", pwgts[0], pwgts[1], graph->nvtxs, graph->nbnd, graph->mincut));  nbnd = graph->nbnd;  RandomPermute(nbnd, perm, 1);  for (ii=0; ii<nbnd; ii++) {    i = bndind[perm[ii]];    ASSERT(where[i] == 2);    PQueueInsert(&parts, i, vwgt[i]-rinfo[i].edegrees[other]);  }  ASSERT(CheckNodeBnd(graph, nbnd));  ASSERT(CheckNodePartitionParams(graph));  /******************************************************  * Get into the FM loop  *******************************************************/  for (nswaps=0; nswaps<nvtxs; nswaps++) {    if ((higain = PQueueGetMax(&parts)) == -1)      break;    moved[higain] = 1;    if (pwgts[other] - rinfo[higain].edegrees[other] < (pwgts[0]+pwgts[1])/2)       continue;#ifdef XXX    if (pwgts[other] - rinfo[higain].edegrees[other] < pwgts[to]+vwgt[higain])       break;#endif    ASSERT(bndptr[higain] != -1);    pwgts[2] -= (vwgt[higain]-rinfo[higain].edegrees[other]);    BNDDelete(nbnd, bndind, bndptr, higain);    pwgts[to] += vwgt[higain];    where[higain] = to;    IFSET(ctrl->dbglvl, DBG_MOVEINFO,          printf("Moved %6d to %3d, Gain: %3d, \t[%5d %5d %5d]\n", higain, to, vwgt[higain]-rinfo[higain].edegrees[other], pwgts[0], pwgts[1], pwgts[2]));    /**********************************************************    * Update the degrees of the affected nodes    ***********************************************************/    for (j=xadj[higain]; j<xadj[higain+1]; j++) {      k = adjncy[j];      if (where[k] == 2) { /* For the in-separator vertices modify their edegree[to] */        rinfo[k].edegrees[to] += vwgt[higain];      }      else if (where[k] == other) { /* This vertex is pulled into the separator */        ASSERTP(bndptr[k] == -1, ("%d %d %d\n", k, bndptr[k], where[k]));        BNDInsert(nbnd, bndind, bndptr, k);        where[k] = 2;        pwgts[other] -= vwgt[k];        edegrees = rinfo[k].edegrees;        edegrees[0] = edegrees[1] = 0;        for (jj=xadj[k]; jj<xadj[k+1]; jj++) {          kk = adjncy[jj];          if (where[kk] != 2)             edegrees[where[kk]] += vwgt[kk];          else {            ASSERT(bndptr[kk] != -1);            oldgain = vwgt[kk]-rinfo[kk].edegrees[other];            rinfo[kk].edegrees[other] -= vwgt[k];            if (moved[kk] == -1)              PQueueUpdateUp(&parts, kk, oldgain, oldgain+vwgt[k]);          }        }        /* Insert the new vertex into the priority queue */        PQueueInsert(&parts, k, vwgt[k]-edegrees[other]);      }    }    if (pwgts[to] > pwgts[other])      break;  }  IFSET(ctrl->dbglvl, DBG_REFINE,    printf("\tBalanced sep: %6d at %4d, PWGTS: [%6d %6d], NBND: %6d\n", pwgts[2], nswaps, pwgts[0], pwgts[1], nbnd));  graph->mincut = pwgts[2];  graph->nbnd = nbnd;  PQueueFree(ctrl, &parts);  idxwspacefree(ctrl, nvtxs);  idxwspacefree(ctrl, nvtxs);}/************************************************************************** This function computes the maximum possible gain for a vertex**************************************************************************/int ComputeMaxNodeGain(int nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt){  int i, j, k, max;  max = 0;  for (j=xadj[0]; j<xadj[1]; j++)    max += vwgt[adjncy[j]];  for (i=1; i<nvtxs; i++) {    for (k=0, j=xadj[i]; j<xadj[i+1]; j++)      k += vwgt[adjncy[j]];    if (max < k)      max = k;  }  return max;}   

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -