00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 #include "metislib.h"
00016 
00017 
00018 
00027 
00028 int METIS_NodeNDP(idx_t nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt,
00029            idx_t npes, idx_t *options, idx_t *perm, idx_t *iperm, idx_t *sizes) 
00030 {
00031   idx_t i, ii, j, l, nnvtxs=0;
00032   graph_t *graph;
00033   ctrl_t *ctrl;
00034   idx_t *cptr, *cind;
00035 
00036   ctrl = SetupCtrl(METIS_OP_OMETIS, options, 1, 3, NULL, NULL);
00037   if (!ctrl) return METIS_ERROR_INPUT;
00038 
00039   IFSET(ctrl->dbglvl, METIS_DBG_TIME, InitTimers(ctrl));
00040   IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->TotalTmr));
00041 
00042   
00043 
00044   if (ctrl->compress) {
00045     cptr = imalloc(nvtxs+1, "OMETIS: cptr");
00046     cind = imalloc(nvtxs, "OMETIS: cind");
00047 
00048     graph = CompressGraph(ctrl, nvtxs, xadj, adjncy, vwgt, cptr, cind);
00049     if (graph == NULL) {
00050       
00051       gk_free((void **)&cptr, &cind, LTERM);
00052       ctrl->compress = 0;
00053     }
00054     else {
00055       nnvtxs = graph->nvtxs;
00056     }
00057   }
00058 
00059   
00060   if (ctrl->compress == 0) 
00061     graph = SetupGraph(ctrl, nvtxs, 1, xadj, adjncy, vwgt, NULL, NULL);
00062 
00063 
00064   
00065   AllocateWorkSpace(ctrl, graph);
00066 
00067 
00068   
00069   iset(2*npes-1, 0, sizes);
00070   MlevelNestedDissectionP(ctrl, graph, iperm, graph->nvtxs, npes, 0, sizes);
00071 
00072 
00073   
00074   if (ctrl->compress) { 
00075     
00076     for (i=0; i<nnvtxs; i++)
00077       perm[iperm[i]] = i; 
00078     for (l=ii=0; ii<nnvtxs; ii++) {
00079       i = perm[ii];
00080       for (j=cptr[i]; j<cptr[i+1]; j++)
00081         iperm[cind[j]] = l++;
00082     }
00083 
00084     gk_free((void **)&cptr, &cind, LTERM);
00085   }
00086 
00087 
00088   for (i=0; i<nvtxs; i++)
00089     perm[iperm[i]] = i;
00090 
00091   IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->TotalTmr));
00092   IFSET(ctrl->dbglvl, METIS_DBG_TIME, PrintTimers(ctrl));
00093 
00094   
00095   FreeCtrl(&ctrl);
00096 
00097   return METIS_OK;
00098 }
00099 
00100 
00101 
00104 
00105 void MlevelNestedDissectionP(ctrl_t *ctrl, graph_t *graph, idx_t *order, 
00106          idx_t lastvtx, idx_t npes, idx_t cpos, idx_t *sizes)
00107 {
00108   idx_t i, j, nvtxs, nbnd;
00109   idx_t *label, *bndind;
00110   graph_t *lgraph, *rgraph;
00111 
00112   nvtxs = graph->nvtxs;
00113 
00114   if (nvtxs == 0) {
00115     FreeGraph(&graph);
00116     return;
00117   }
00118 
00119   MlevelNodeBisectionMultiple(ctrl, graph);
00120 
00121   IFSET(ctrl->dbglvl, METIS_DBG_SEPINFO, 
00122       printf("Nvtxs: %6"PRIDX", [%6"PRIDX" %6"PRIDX" %6"PRIDX"]\n", 
00123         graph->nvtxs, graph->pwgts[0], graph->pwgts[1], graph->pwgts[2]));
00124 
00125   if (cpos < npes-1) {
00126     sizes[2*npes-2-cpos]       = graph->pwgts[2];
00127     sizes[2*npes-2-(2*cpos+1)] = graph->pwgts[1];
00128     sizes[2*npes-2-(2*cpos+2)] = graph->pwgts[0];
00129   }
00130 
00131   
00132   nbnd   = graph->nbnd;
00133   bndind = graph->bndind;
00134   label  = graph->label;
00135   for (i=0; i<nbnd; i++) 
00136     order[label[bndind[i]]] = --lastvtx;
00137 
00138   SplitGraphOrder(ctrl, graph, &lgraph, &rgraph);
00139 
00140   
00141   FreeGraph(&graph);
00142 
00143   if ((lgraph->nvtxs > MMDSWITCH || 2*cpos+2 < npes-1) && lgraph->nedges > 0) 
00144     MlevelNestedDissectionP(ctrl, lgraph, order, lastvtx-rgraph->nvtxs, npes, 2*cpos+2, sizes);
00145   else {
00146     MMDOrder(ctrl, lgraph, order, lastvtx-rgraph->nvtxs); 
00147     FreeGraph(&lgraph);
00148   }
00149   if ((rgraph->nvtxs > MMDSWITCH || 2*cpos+1 < npes-1) && rgraph->nedges > 0) 
00150     MlevelNestedDissectionP(ctrl, rgraph, order, lastvtx, npes, 2*cpos+1, sizes);
00151   else {
00152     MMDOrder(ctrl, rgraph, order, lastvtx); 
00153     FreeGraph(&rgraph);
00154   }
00155 }
00156 
00157 
00158 
00160 
00161 int METIS_ComputeVertexSeparator(idx_t *nvtxs, idx_t *xadj, idx_t *adjncy, 
00162            idx_t *vwgt, idx_t *options, idx_t *r_sepsize, idx_t *part) 
00163 {
00164   idx_t i, j;
00165   graph_t *graph;
00166   ctrl_t *ctrl;
00167 
00168   if ((ctrl = SetupCtrl(METIS_OP_OMETIS, options, 1, 3, NULL, NULL)) == NULL)
00169     return METIS_ERROR_INPUT;
00170 
00171   InitRandom(ctrl->seed);
00172 
00173   graph = SetupGraph(ctrl, *nvtxs, 1, xadj, adjncy, vwgt, NULL, NULL);
00174 
00175   AllocateWorkSpace(ctrl, graph);
00176 
00177   
00178 
00179  
00180   ctrl->CoarsenTo = 100;
00181 
00182   MlevelNodeBisectionMultiple(ctrl, graph);
00183 
00184   *r_sepsize = graph->pwgts[2];
00185   icopy(*nvtxs, graph->where, part);
00186 
00187   FreeGraph(&graph);
00188 
00189   FreeCtrl(&ctrl);
00190 
00191   return METIS_OK;
00192 }
00193 
00194 
00195 
00198 
00199 int METIS_NodeRefine(idx_t nvtxs, idx_t *xadj, idx_t *vwgt, idx_t *adjncy, 
00200            idx_t *where, idx_t *hmarker, real_t ubfactor)
00201 {
00202   graph_t *graph;
00203   ctrl_t *ctrl;
00204 
00205   
00206   ctrl = SetupCtrl(METIS_OP_OMETIS, NULL, 1, 3, NULL, NULL);
00207   if (!ctrl) return METIS_ERROR_INPUT;
00208 
00209   
00210   graph = SetupGraph(ctrl, nvtxs, 1, xadj, adjncy, vwgt, NULL, NULL);
00211 
00212   
00213   AllocateWorkSpace(ctrl, graph);
00214 
00215   
00216   Allocate2WayNodePartitionMemory(ctrl, graph);
00217   icopy(nvtxs, where, graph->where);
00218 
00219   Compute2WayNodePartitionParams(ctrl, graph);
00220 
00221   FM_2WayNodeRefine1SidedP(ctrl, graph, hmarker, ubfactor, 10); 
00222   
00223 
00224   icopy(nvtxs, graph->where, where);
00225 
00226   FreeGraph(&graph);
00227   FreeCtrl(&ctrl);
00228 
00229   return METIS_OK;
00230 }
00231 
00232 
00233 
00236 
00237 void FM_2WayNodeRefine1SidedP(ctrl_t *ctrl, graph_t *graph, 
00238           idx_t *hmarker, real_t ubfactor, idx_t npasses)
00239 {
00240   idx_t i, ii, j, k, jj, kk, nvtxs, nbnd, nswaps, nmind, nbad, qsize;
00241   idx_t *xadj, *vwgt, *adjncy, *where, *pwgts, *edegrees, *bndind, *bndptr;
00242   idx_t *mptr, *mind, *swaps, *inqueue;
00243   rpq_t *queue; 
00244   nrinfo_t *rinfo;
00245   idx_t higain, oldgain, mincut, initcut, mincutorder;  
00246   idx_t pass, from, to, limit;
00247   idx_t badmaxpwgt, mindiff, newdiff;
00248 
00249   WCOREPUSH;
00250 
00251   ASSERT(graph->mincut == graph->pwgts[2]);
00252 
00253   nvtxs  = graph->nvtxs;
00254   xadj   = graph->xadj;
00255   adjncy = graph->adjncy;
00256   vwgt   = graph->vwgt;
00257 
00258   bndind = graph->bndind;
00259   bndptr = graph->bndptr;
00260   where  = graph->where;
00261   pwgts  = graph->pwgts;
00262   rinfo  = graph->nrinfo;
00263 
00264   queue = rpqCreate(nvtxs);
00265       
00266   inqueue = iset(nvtxs, -1, iwspacemalloc(ctrl, nvtxs));
00267   swaps   = iwspacemalloc(ctrl, nvtxs);
00268   mptr    = iwspacemalloc(ctrl, nvtxs+1);
00269   mind    = iwspacemalloc(ctrl, 2*nvtxs);
00270 
00271   badmaxpwgt = (idx_t)(ubfactor*gk_max(pwgts[0], pwgts[1]));
00272 
00273   IFSET(ctrl->dbglvl, METIS_DBG_REFINE,
00274     printf("Partitions-N1: [%6"PRIDX" %6"PRIDX"] Nv-Nb[%6"PRIDX" %6"PRIDX"] "
00275            "MaxPwgt[%6"PRIDX"]. ISep: %6"PRIDX"\n", 
00276            pwgts[0], pwgts[1], graph->nvtxs, graph->nbnd, badmaxpwgt, 
00277            graph->mincut));
00278 
00279   to = (pwgts[0] < pwgts[1] ? 1 : 0);
00280   for (pass=0; pass<npasses; pass++) {
00281     from = to; 
00282     to   = (from+1)%2;
00283 
00284     rpqReset(queue);
00285 
00286     mincutorder = -1;
00287     initcut = mincut = graph->mincut;
00288     nbnd = graph->nbnd;
00289 
00290     
00291     irandArrayPermute(nbnd, swaps, nbnd, 1);
00292     for (ii=0; ii<nbnd; ii++) {
00293       i = bndind[swaps[ii]];
00294       ASSERT(where[i] == 2);
00295       if (hmarker[i] == -1 || hmarker[i] == to) {
00296         rpqInsert(queue, i, vwgt[i]-rinfo[i].edegrees[from]);
00297         inqueue[i] = pass;
00298       }
00299     }
00300     qsize = rpqLength(queue);
00301 
00302     ASSERT(CheckNodeBnd(graph, nbnd));
00303     ASSERT(CheckNodePartitionParams(graph));
00304 
00305     limit = nbnd;
00306 
00307     
00308 
00309 
00310     mptr[0] = nmind = nbad = 0;
00311     mindiff = abs(pwgts[0]-pwgts[1]);
00312     for (nswaps=0; nswaps<nvtxs; nswaps++) {
00313       if ((higain = rpqGetTop(queue)) == -1) 
00314         break;
00315 
00316       ASSERT(bndptr[higain] != -1);
00317 
00318       
00319 
00320       if (nmind + xadj[higain+1]-xadj[higain] >= 2*nvtxs-1)
00321         break;
00322 
00323       inqueue[higain] = -1;
00324 
00325       if (pwgts[to]+vwgt[higain] > badmaxpwgt) { 
00326         if (nbad++ > limit) 
00327           break; 
00328         else {
00329           nswaps--;
00330           continue;  
00331         }
00332       }
00333 
00334       pwgts[2] -= (vwgt[higain]-rinfo[higain].edegrees[from]);
00335 
00336       newdiff = abs(pwgts[to]+vwgt[higain] - (pwgts[from]-rinfo[higain].edegrees[from]));
00337       if (pwgts[2] < mincut || (pwgts[2] == mincut && newdiff < mindiff)) {
00338         mincut      = pwgts[2];
00339         mincutorder = nswaps;
00340         mindiff     = newdiff;
00341         nbad        = 0;
00342       }
00343       else {
00344         if (nbad++ > limit) {
00345           pwgts[2] += (vwgt[higain]-rinfo[higain].edegrees[from]);
00346           break; 
00347         }
00348       }
00349 
00350       BNDDelete(nbnd, bndind, bndptr, higain);
00351       pwgts[to] += vwgt[higain];
00352       where[higain] = to;
00353       swaps[nswaps] = higain;  
00354 
00355 
00356       
00357 
00358 
00359       for (j=xadj[higain]; j<xadj[higain+1]; j++) {
00360         k = adjncy[j];
00361         if (where[k] == 2) { 
00362           rinfo[k].edegrees[to] += vwgt[higain];
00363         }
00364         else if (where[k] == from) { 
00365           ASSERTP(bndptr[k] == -1, ("%"PRIDX" %"PRIDX" %"PRIDX"\n", k, bndptr[k], where[k]));
00366           BNDInsert(nbnd, bndind, bndptr, k);
00367 
00368           mind[nmind++] = k;  
00369           where[k]      = 2;
00370           pwgts[from]  -= vwgt[k];
00371 
00372           edegrees = rinfo[k].edegrees;
00373           edegrees[0] = edegrees[1] = 0;
00374           for (jj=xadj[k]; jj<xadj[k+1]; jj++) {
00375             kk = adjncy[jj];
00376             if (where[kk] != 2) 
00377               edegrees[where[kk]] += vwgt[kk];
00378             else {
00379               oldgain = vwgt[kk]-rinfo[kk].edegrees[from];
00380               rinfo[kk].edegrees[from] -= vwgt[k];
00381 
00382               
00383               if (inqueue[kk] == pass)
00384                 rpqUpdate(queue, kk, oldgain+vwgt[k]); 
00385             }
00386           }
00387 
00388           
00389           if (hmarker[k] == -1 || hmarker[k] == to) {
00390             rpqInsert(queue, k, vwgt[k]-edegrees[from]);
00391             inqueue[k] = pass;
00392           }
00393         }
00394       }
00395       mptr[nswaps+1] = nmind;
00396 
00397 
00398       IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO,
00399             printf("Moved %6"PRIDX" to %3"PRIDX", Gain: %5"PRIDX" [%5"PRIDX"] \t[%5"PRIDX" %5"PRIDX" %5"PRIDX"] [%3"PRIDX" %2"PRIDX"]\n", 
00400                    higain, to, (vwgt[higain]-rinfo[higain].edegrees[from]), 
00401                    vwgt[higain], pwgts[0], pwgts[1], pwgts[2], nswaps, limit));
00402 
00403     }
00404 
00405 
00406     
00407 
00408 
00409     for (nswaps--; nswaps>mincutorder; nswaps--) {
00410       higain = swaps[nswaps];
00411 
00412       ASSERT(CheckNodePartitionParams(graph));
00413       ASSERT(where[higain] == to);
00414 
00415       INC_DEC(pwgts[2], pwgts[to], vwgt[higain]);
00416       where[higain] = 2;
00417       BNDInsert(nbnd, bndind, bndptr, higain);
00418 
00419       edegrees = rinfo[higain].edegrees;
00420       edegrees[0] = edegrees[1] = 0;
00421       for (j=xadj[higain]; j<xadj[higain+1]; j++) {
00422         k = adjncy[j];
00423         if (where[k] == 2) 
00424           rinfo[k].edegrees[to] -= vwgt[higain];
00425         else
00426           edegrees[where[k]] += vwgt[k];
00427       }
00428 
00429       
00430       for (j=mptr[nswaps]; j<mptr[nswaps+1]; j++) {
00431         k = mind[j];
00432         ASSERT(where[k] == 2);
00433         where[k] = from;
00434         INC_DEC(pwgts[from], pwgts[2], vwgt[k]);
00435         BNDDelete(nbnd, bndind, bndptr, k);
00436         for (jj=xadj[k]; jj<xadj[k+1]; jj++) {
00437           kk = adjncy[jj];
00438           if (where[kk] == 2) 
00439             rinfo[kk].edegrees[from] += vwgt[k];
00440         }
00441       }
00442     }
00443 
00444     ASSERT(mincut == pwgts[2]);
00445 
00446     IFSET(ctrl->dbglvl, METIS_DBG_REFINE,
00447       printf("\tMinimum sep: %6"PRIDX" at %5"PRIDX", PWGTS: [%6"PRIDX" %6"PRIDX"], NBND: %6"PRIDX", QSIZE: %6"PRIDX"\n", 
00448           mincut, mincutorder, pwgts[0], pwgts[1], nbnd, qsize));
00449 
00450     graph->mincut = mincut;
00451     graph->nbnd   = nbnd;
00452 
00453     if (pass%2 == 1 && (mincutorder == -1 || mincut >= initcut))
00454       break;
00455   }
00456 
00457   rpqDestroy(queue);
00458 
00459   WCOREPOP;
00460 }
00461 
00462 
00463 
00466 
00467 void FM_2WayNodeRefine2SidedP(ctrl_t *ctrl, graph_t *graph, 
00468           idx_t *hmarker, real_t ubfactor, idx_t npasses)
00469 {
00470   idx_t i, ii, j, k, jj, kk, nvtxs, nbnd, nswaps, nmind;
00471   idx_t *xadj, *vwgt, *adjncy, *where, *pwgts, *edegrees, *bndind, *bndptr;
00472   idx_t *mptr, *mind, *moved, *swaps;
00473   rpq_t *queues[2]; 
00474   nrinfo_t *rinfo;
00475   idx_t higain, oldgain, mincut, initcut, mincutorder;  
00476   idx_t pass, to, other, limit;
00477   idx_t badmaxpwgt, mindiff, newdiff;
00478   idx_t u[2], g[2];
00479 
00480   WCOREPUSH;
00481 
00482   nvtxs  = graph->nvtxs;
00483   xadj   = graph->xadj;
00484   adjncy = graph->adjncy;
00485   vwgt   = graph->vwgt;
00486 
00487   bndind = graph->bndind;
00488   bndptr = graph->bndptr;
00489   where  = graph->where;
00490   pwgts  = graph->pwgts;
00491   rinfo  = graph->nrinfo;
00492 
00493   queues[0] = rpqCreate(nvtxs);
00494   queues[1] = rpqCreate(nvtxs);
00495 
00496   moved = iwspacemalloc(ctrl, nvtxs);
00497   swaps = iwspacemalloc(ctrl, nvtxs);
00498   mptr  = iwspacemalloc(ctrl, nvtxs+1);
00499   mind  = iwspacemalloc(ctrl, 2*nvtxs);
00500 
00501   IFSET(ctrl->dbglvl, METIS_DBG_REFINE,
00502     printf("Partitions: [%6"PRIDX" %6"PRIDX"] Nv-Nb[%6"PRIDX" %6"PRIDX"]. ISep: %6"PRIDX"\n", pwgts[0], pwgts[1], graph->nvtxs, graph->nbnd, graph->mincut));
00503 
00504   badmaxpwgt = (idx_t)(ubfactor*gk_max(pwgts[0], pwgts[1]));
00505 
00506   for (pass=0; pass<npasses; pass++) {
00507     iset(nvtxs, -1, moved);
00508     rpqReset(queues[0]);
00509     rpqReset(queues[1]);
00510 
00511     mincutorder = -1;
00512     initcut = mincut = graph->mincut;
00513     nbnd = graph->nbnd;
00514 
00515     
00516     irandArrayPermute(nbnd, swaps, nbnd, 1);
00517     for (ii=0; ii<nbnd; ii++) {
00518       i = bndind[swaps[ii]];
00519       ASSERT(where[i] == 2);
00520       if (hmarker[i] == -1) {
00521         rpqInsert(queues[0], i, vwgt[i]-rinfo[i].edegrees[1]);
00522         rpqInsert(queues[1], i, vwgt[i]-rinfo[i].edegrees[0]);
00523         moved[i] = -5;
00524       }
00525       else if (hmarker[i] != 2) {
00526         rpqInsert(queues[hmarker[i]], i, vwgt[i]-rinfo[i].edegrees[(hmarker[i]+1)%2]);
00527         moved[i] = -(10+hmarker[i]);
00528       }
00529     }
00530 
00531     ASSERT(CheckNodeBnd(graph, nbnd));
00532     ASSERT(CheckNodePartitionParams(graph));
00533 
00534     limit = nbnd;
00535 
00536     
00537 
00538 
00539     mptr[0] = nmind = 0;
00540     mindiff = abs(pwgts[0]-pwgts[1]);
00541     to = (pwgts[0] < pwgts[1] ? 0 : 1);
00542     for (nswaps=0; nswaps<nvtxs; nswaps++) {
00543       u[0] = rpqSeeTopVal(queues[0]);  
00544       u[1] = rpqSeeTopVal(queues[1]);
00545       if (u[0] != -1 && u[1] != -1) {
00546         g[0] = vwgt[u[0]]-rinfo[u[0]].edegrees[1];
00547         g[1] = vwgt[u[1]]-rinfo[u[1]].edegrees[0];
00548 
00549         to = (g[0] > g[1] ? 0 : (g[0] < g[1] ? 1 : pass%2)); 
00550 
00551         if (pwgts[to]+vwgt[u[to]] > badmaxpwgt) 
00552           to = (to+1)%2;
00553       }
00554       else if (u[0] == -1 && u[1] == -1) {
00555         break;
00556       }
00557       else if (u[0] != -1 && pwgts[0]+vwgt[u[0]] <= badmaxpwgt) {
00558         to = 0;
00559       }
00560       else if (u[1] != -1 && pwgts[1]+vwgt[u[1]] <= badmaxpwgt) {
00561         to = 1;
00562       }
00563       else
00564         break;
00565 
00566       other = (to+1)%2;
00567 
00568       higain = rpqGetTop(queues[to]);
00569 
00570       
00571       if (moved[higain] == -5) 
00572         rpqDelete(queues[other], higain);
00573 
00574       ASSERT(bndptr[higain] != -1);
00575 
00576       
00577 
00578       if (nmind + xadj[higain+1]-xadj[higain] >= 2*nvtxs-1)
00579         break;
00580 
00581       pwgts[2] -= (vwgt[higain]-rinfo[higain].edegrees[other]);
00582 
00583       newdiff = abs(pwgts[to]+vwgt[higain] - (pwgts[other]-rinfo[higain].edegrees[other]));
00584       if (pwgts[2] < mincut || (pwgts[2] == mincut && newdiff < mindiff)) {
00585         mincut      = pwgts[2];
00586         mincutorder = nswaps;
00587         mindiff     = newdiff;
00588       }
00589       else {
00590         if (nswaps - mincutorder > limit) {
00591           pwgts[2] += (vwgt[higain]-rinfo[higain].edegrees[other]);
00592           break; 
00593         }
00594       }
00595 
00596       BNDDelete(nbnd, bndind, bndptr, higain);
00597       pwgts[to] += vwgt[higain];
00598       where[higain] = to;
00599       moved[higain] = nswaps;
00600       swaps[nswaps] = higain;  
00601 
00602 
00603       
00604 
00605 
00606       for (j=xadj[higain]; j<xadj[higain+1]; j++) {
00607         k = adjncy[j];
00608         if (where[k] == 2) { 
00609           oldgain = vwgt[k]-rinfo[k].edegrees[to];
00610           rinfo[k].edegrees[to] += vwgt[higain];
00611           if (moved[k] == -5 || moved[k] == -(10+other)) 
00612             rpqUpdate(queues[other], k, oldgain-vwgt[higain]);
00613         }
00614         else if (where[k] == other) { 
00615           ASSERTP(bndptr[k] == -1, ("%"PRIDX" %"PRIDX" %"PRIDX"\n", k, bndptr[k], where[k]));
00616           BNDInsert(nbnd, bndind, bndptr, k);
00617 
00618           mind[nmind++] = k;  
00619           where[k] = 2;
00620           pwgts[other] -= vwgt[k];
00621 
00622           edegrees = rinfo[k].edegrees;
00623           edegrees[0] = edegrees[1] = 0;
00624           for (jj=xadj[k]; jj<xadj[k+1]; jj++) {
00625             kk = adjncy[jj];
00626             if (where[kk] != 2) 
00627               edegrees[where[kk]] += vwgt[kk];
00628             else {
00629               oldgain = vwgt[kk]-rinfo[kk].edegrees[other];
00630               rinfo[kk].edegrees[other] -= vwgt[k];
00631               if (moved[kk] == -5 || moved[kk] == -(10+to))
00632                 rpqUpdate(queues[to], kk, oldgain+vwgt[k]);
00633             }
00634           }
00635 
00636           
00637           if (moved[k] == -1 && (hmarker[k] == -1 || hmarker[k] == to)) {
00638             rpqInsert(queues[to], k, vwgt[k]-edegrees[other]);
00639             moved[k] = -(10+to);
00640           }
00641 #ifdef FULLMOVES  
00642           if (moved[k] == -1) {
00643             if (hmarker[k] == -1) {
00644               rpqInsert(queues[0], k, vwgt[k]-edegrees[1]);
00645               rpqInsert(queues[1], k, vwgt[k]-edegrees[0]);
00646               moved[k] = -5;
00647             }
00648             else if (hmarker[k] != 2) {
00649               rpqInsert(queues[hmarker[k]], k, vwgt[k]-edegrees[(hmarker[k]+1)%2]);
00650               moved[k] = -(10+hmarker[k]);
00651             }
00652           }
00653 #endif
00654         }
00655       }
00656       mptr[nswaps+1] = nmind;
00657 
00658       IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO,
00659             printf("Moved %6"PRIDX" to %3"PRIDX", Gain: %5"PRIDX" [%5"PRIDX"] "
00660                    "[%4"PRIDX" %4"PRIDX"] \t[%5"PRIDX" %5"PRIDX" %5"PRIDX"]\n", 
00661                    higain, to, g[to], g[other], vwgt[u[to]], vwgt[u[other]], 
00662                    pwgts[0], pwgts[1], pwgts[2]));
00663 
00664     }
00665 
00666 
00667     
00668 
00669 
00670     for (nswaps--; nswaps>mincutorder; nswaps--) {
00671       higain = swaps[nswaps];
00672 
00673       ASSERT(CheckNodePartitionParams(graph));
00674 
00675       to = where[higain];
00676       other = (to+1)%2;
00677       INC_DEC(pwgts[2], pwgts[to], vwgt[higain]);
00678       where[higain] = 2;
00679       BNDInsert(nbnd, bndind, bndptr, higain);
00680 
00681       edegrees = rinfo[higain].edegrees;
00682       edegrees[0] = edegrees[1] = 0;
00683       for (j=xadj[higain]; j<xadj[higain+1]; j++) {
00684         k = adjncy[j];
00685         if (where[k] == 2) 
00686           rinfo[k].edegrees[to] -= vwgt[higain];
00687         else
00688           edegrees[where[k]] += vwgt[k];
00689       }
00690 
00691       
00692       for (j=mptr[nswaps]; j<mptr[nswaps+1]; j++) {
00693         k = mind[j];
00694         ASSERT(where[k] == 2);
00695         where[k] = other;
00696         INC_DEC(pwgts[other], pwgts[2], vwgt[k]);
00697         BNDDelete(nbnd, bndind, bndptr, k);
00698         for (jj=xadj[k]; jj<xadj[k+1]; jj++) {
00699           kk = adjncy[jj];
00700           if (where[kk] == 2) 
00701             rinfo[kk].edegrees[other] += vwgt[k];
00702         }
00703       }
00704     }
00705 
00706     ASSERT(mincut == pwgts[2]);
00707 
00708     IFSET(ctrl->dbglvl, METIS_DBG_REFINE,
00709       printf("\tMinimum sep: %6"PRIDX" at %5"PRIDX", PWGTS: [%6"PRIDX" %6"PRIDX"], NBND: %6"PRIDX"\n", mincut, mincutorder, pwgts[0], pwgts[1], nbnd));
00710 
00711     graph->mincut = mincut;
00712     graph->nbnd = nbnd;
00713 
00714     if (mincutorder == -1 || mincut >= initcut)
00715       break;
00716   }
00717 
00718   rpqDestroy(queues[0]);
00719   rpqDestroy(queues[1]);
00720 
00721   WCOREPOP;
00722 }
00723