00001 
00011 #include "metislib.h"
00012 
00013 
00014 
00017 
00018 void ComputeSubDomainGraph(ctrl_t *ctrl, graph_t *graph)
00019 {
00020   idx_t i, ii, j, pid, other, nparts, nvtxs, nnbrs;
00021   idx_t *xadj, *adjncy, *adjwgt, *where;
00022   idx_t *pptr, *pind;
00023   idx_t nads=0, *vadids, *vadwgts;
00024 
00025   WCOREPUSH;
00026 
00027   nvtxs  = graph->nvtxs;
00028   xadj   = graph->xadj;
00029   adjncy = graph->adjncy;
00030   adjwgt = graph->adjwgt;
00031   where  = graph->where;
00032 
00033   nparts = ctrl->nparts; 
00034 
00035   vadids  = ctrl->pvec1;
00036   vadwgts = iset(nparts, 0, ctrl->pvec2);
00037 
00038   pptr = iwspacemalloc(ctrl, nparts+1);
00039   pind = iwspacemalloc(ctrl, nvtxs);
00040   iarray2csr(nvtxs, nparts, where, pptr, pind);
00041 
00042   for (pid=0; pid<nparts; pid++) {
00043     switch (ctrl->objtype) {
00044       case METIS_OBJTYPE_CUT:
00045         {
00046           ckrinfo_t *rinfo;
00047           cnbr_t *nbrs;
00048 
00049           rinfo = graph->ckrinfo;
00050           for (nads=0, ii=pptr[pid]; ii<pptr[pid+1]; ii++) {
00051             i = pind[ii];
00052             ASSERT(pid == where[i]);
00053       
00054             if (rinfo[i].ed > 0) {
00055               nnbrs = rinfo[i].nnbrs;
00056               nbrs  = ctrl->cnbrpool + rinfo[i].inbr;
00057       
00058               for (j=0; j<nnbrs; j++) {
00059                 other = nbrs[j].pid;
00060                 if (vadwgts[other] == 0)
00061                   vadids[nads++] = other;
00062                 vadwgts[other] += nbrs[j].ed;
00063               }
00064             }
00065           }
00066         }
00067         break;
00068 
00069       case METIS_OBJTYPE_VOL:
00070         {
00071           vkrinfo_t *rinfo;
00072           vnbr_t *nbrs;
00073 
00074           rinfo = graph->vkrinfo;
00075           for (nads=0, ii=pptr[pid]; ii<pptr[pid+1]; ii++) {
00076             i = pind[ii];
00077             ASSERT(pid == where[i]);
00078       
00079             if (rinfo[i].ned > 0) {
00080               nnbrs = rinfo[i].nnbrs;
00081               nbrs  = ctrl->vnbrpool + rinfo[i].inbr;
00082       
00083               for (j=0; j<nnbrs; j++) {
00084                 other = nbrs[j].pid;
00085                 if (vadwgts[other] == 0)
00086                   vadids[nads++] = other;
00087                 vadwgts[other] += nbrs[j].ned;
00088               }
00089             }
00090           }
00091         }
00092         break;
00093 
00094       default:
00095         gk_errexit(SIGERR, "Unknown objtype: %d\n", ctrl->objtype);
00096     }
00097 
00098     
00099     if (ctrl->maxnads[pid] < nads) {
00100       ctrl->maxnads[pid] = 2*nads;
00101       ctrl->adids[pid]   = irealloc(ctrl->adids[pid], ctrl->maxnads[pid], 
00102                                "ComputeSubDomainGraph: adids[pid]");
00103       ctrl->adwgts[pid]  = irealloc(ctrl->adwgts[pid], ctrl->maxnads[pid], 
00104                                "ComputeSubDomainGraph: adids[pid]");
00105     }
00106 
00107     ctrl->nads[pid] = nads;
00108     for (j=0; j<nads; j++) {
00109       ctrl->adids[pid][j]  = vadids[j];
00110       ctrl->adwgts[pid][j] = vadwgts[vadids[j]];
00111 
00112       vadwgts[vadids[j]] = 0;
00113     }
00114   }
00115       
00116   WCOREPOP;
00117 }
00118 
00119 
00120 
00133 
00134 void UpdateEdgeSubDomainGraph(ctrl_t *ctrl, idx_t u, idx_t v, idx_t ewgt, 
00135          idx_t *r_maxndoms)
00136 {
00137   idx_t i, j, nads;
00138 
00139   if (ewgt == 0)
00140     return;
00141 
00142   for (i=0; i<2; i++) {
00143     nads = ctrl->nads[u];
00144     
00145     for (j=0; j<nads; j++) {
00146       if (ctrl->adids[u][j] == v) {
00147         ctrl->adwgts[u][j] += ewgt;
00148         break;
00149       }
00150     }
00151 
00152     if (j == nads) {
00153       
00154       ASSERT(ewgt > 0);
00155       if (ctrl->maxnads[u] == nads) {
00156         ctrl->maxnads[u] = 2*(nads+1);
00157         ctrl->adids[u]   = irealloc(ctrl->adids[u], ctrl->maxnads[u], 
00158                                "IncreaseEdgeSubDomainGraph: adids[pid]");
00159         ctrl->adwgts[u]  = irealloc(ctrl->adwgts[u], ctrl->maxnads[u], 
00160                                "IncreaseEdgeSubDomainGraph: adids[pid]");
00161       }
00162       ctrl->adids[u][nads]  = v;
00163       ctrl->adwgts[u][nads] = ewgt;
00164       nads++;
00165       if (r_maxndoms != NULL && nads > *r_maxndoms) {
00166         printf("You just increased the maxndoms: %"PRIDX" %"PRIDX"\n", 
00167             nads, *r_maxndoms);
00168         *r_maxndoms = nads;
00169       }
00170     }
00171     else {
00172       
00173       ASSERT(ctrl->adwgts[u][j] >= 0);
00174       if (ctrl->adwgts[u][j] == 0) {
00175         ctrl->adids[u][j]  = ctrl->adids[u][nads-1];
00176         ctrl->adwgts[u][j] = ctrl->adwgts[u][nads-1];
00177         nads--;
00178         if (r_maxndoms != NULL && nads+1 == *r_maxndoms)
00179           *r_maxndoms = ctrl->nads[iargmax(ctrl->nparts, ctrl->nads)];
00180       }
00181     }
00182     ctrl->nads[u] = nads;
00183 
00184     SWAP(u, v, j);
00185   }
00186 }
00187 
00188 
00189 
00191 
00192 void EliminateSubDomainEdges(ctrl_t *ctrl, graph_t *graph)
00193 {
00194   idx_t i, ii, j, k, ncon, nparts, scheme, pid_from, pid_to, me, other, nvtxs, 
00195         total, max, avg, totalout, nind=0, ncand=0, ncand2, target, target2, 
00196         nadd, bestnadd=0;
00197   idx_t min, move, *cpwgt;
00198   idx_t *xadj, *adjncy, *vwgt, *adjwgt, *pwgts, *where, *maxpwgt, 
00199         *mypmat, *otherpmat, *kpmat, *ind;
00200   idx_t *nads, **adids, **adwgts;
00201   ikv_t *cand, *cand2;
00202   ipq_t queue;
00203   real_t *tpwgts, badfactor=1.4;
00204   idx_t *pptr, *pind;
00205   idx_t *vmarker=NULL, *pmarker=NULL, *modind=NULL;  
00206 
00207   WCOREPUSH;
00208 
00209   nvtxs  = graph->nvtxs;
00210   ncon   = graph->ncon;
00211   xadj   = graph->xadj;
00212   adjncy = graph->adjncy;
00213   vwgt   = graph->vwgt;
00214   adjwgt = (ctrl->objtype == METIS_OBJTYPE_VOL ? NULL : graph->adjwgt);
00215 
00216   where = graph->where;
00217   pwgts = graph->pwgts;  
00218 
00219   nparts = ctrl->nparts;
00220   tpwgts = ctrl->tpwgts;
00221 
00222   cpwgt     = iwspacemalloc(ctrl, ncon);
00223   maxpwgt   = iwspacemalloc(ctrl, nparts*ncon);
00224   ind       = iwspacemalloc(ctrl, nvtxs);
00225   otherpmat = iset(nparts, 0, iwspacemalloc(ctrl, nparts));
00226 
00227   cand  = ikvwspacemalloc(ctrl, nparts);
00228   cand2 = ikvwspacemalloc(ctrl, nparts);
00229 
00230   pptr = iwspacemalloc(ctrl, nparts+1);
00231   pind = iwspacemalloc(ctrl, nvtxs);
00232   iarray2csr(nvtxs, nparts, where, pptr, pind);
00233 
00234   if (ctrl->objtype == METIS_OBJTYPE_VOL) {
00235     
00236     modind  = iwspacemalloc(ctrl, nvtxs);
00237     vmarker = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs));
00238     pmarker = iset(nparts, -1, iwspacemalloc(ctrl, nparts));
00239   }
00240 
00241 
00242   
00243   ComputeSubDomainGraph(ctrl, graph);
00244 
00245   nads   = ctrl->nads;
00246   adids  = ctrl->adids;
00247   adwgts = ctrl->adwgts;
00248 
00249   mypmat = iset(nparts, 0, ctrl->pvec1);
00250   kpmat  = iset(nparts, 0, ctrl->pvec2);
00251 
00252   
00253   for (i=0; i<nparts; i++) {
00254     for (j=0; j<ncon; j++)
00255       maxpwgt[i*ncon+j] = 
00256           (ncon == 1 ? 1.25 : 1.025)*tpwgts[i]*graph->tvwgt[j]*ctrl->ubfactors[j];
00257   }
00258 
00259   ipqInit(&queue, nparts);
00260 
00261   
00262   while (1) {
00263     total = isum(nparts, nads, 1);
00264     avg   = total/nparts;
00265     max   = nads[iargmax(nparts, nads)];
00266 
00267     IFSET(ctrl->dbglvl, METIS_DBG_CONNINFO, 
00268           printf("Adjacent Subdomain Stats: Total: %3"PRIDX", "
00269                  "Max: %3"PRIDX"[%zu], Avg: %3"PRIDX"\n", 
00270                  total, max, iargmax(nparts, nads), avg)); 
00271 
00272     if (max < badfactor*avg)
00273       break;
00274 
00275     
00276     ipqReset(&queue);
00277     for (i=0; i<nparts; i++) {
00278       if (nads[i] >= avg + (max-avg)/2)
00279         ipqInsert(&queue, i, nads[i]);
00280     }
00281 
00282     move = 0;
00283     while ((me = ipqGetTop(&queue)) != -1) {
00284       totalout = isum(nads[me], adwgts[me], 1);
00285 
00286       for (ncand2=0, i=0; i<nads[me]; i++) {
00287         mypmat[adids[me][i]] = adwgts[me][i];
00288 
00289         
00290         if (2*nads[me]*adwgts[me][i] < totalout) {
00291           cand2[ncand2].val   = adids[me][i];
00292           cand2[ncand2++].key = adwgts[me][i];
00293         }
00294       }
00295 
00296       IFSET(ctrl->dbglvl, METIS_DBG_CONNINFO, 
00297             printf("Me: %"PRIDX", Degree: %4"PRIDX", TotalOut: %"PRIDX",\n", 
00298                 me, nads[me], totalout));
00299 
00300       
00301       ikvsorti(ncand2, cand2);
00302 
00303       
00304 
00305 
00306 
00307 
00308 
00309 
00310       target = target2 = -1;
00311       for (scheme=0; scheme<2; scheme++) {
00312         for (min=0; min<ncand2; min++) {
00313           other = cand2[min].val;
00314 
00315           
00316 
00317 
00318           if (scheme == 0) {
00319             pid_from = other;
00320             pid_to   = me;
00321           }
00322           else {
00323             pid_from  = me;
00324             pid_to    = other;
00325           }
00326   
00327           
00328           for (nind=0, ii=pptr[pid_from]; ii<pptr[pid_from+1]; ii++) {
00329             i = pind[ii];
00330             ASSERT(where[i] == pid_from);
00331             for (j=xadj[i]; j<xadj[i+1]; j++) {
00332               if (where[adjncy[j]] == pid_to) {
00333                 ind[nind++] = i;
00334                 break;
00335               }
00336             }
00337           }
00338   
00339           
00340 
00341           iset(ncon, 0, cpwgt);
00342           for (ncand=0, ii=0; ii<nind; ii++) {
00343             i = ind[ii];
00344             iaxpy(ncon, 1, vwgt+i*ncon, 1, cpwgt, 1);
00345     
00346             for (j=xadj[i]; j<xadj[i+1]; j++) {
00347               if ((k = where[adjncy[j]]) == pid_from)
00348                 continue;
00349               if (otherpmat[k] == 0)
00350                 cand[ncand++].val = k;
00351               otherpmat[k] += (adjwgt ? adjwgt[j] : 1);
00352             }
00353           }
00354     
00355           for (i=0; i<ncand; i++) {
00356             cand[i].key = otherpmat[cand[i].val];
00357             ASSERT(cand[i].key > 0);
00358           }
00359 
00360           ikvsortd(ncand, cand);
00361     
00362           IFSET(ctrl->dbglvl, METIS_DBG_CONNINFO, 
00363                 printf("\tMinOut: %4"PRIDX", to: %3"PRIDX", TtlWgt: %5"PRIDX"[#:%"PRIDX"]\n", 
00364                     mypmat[other], other, isum(ncon, cpwgt, 1), nind));
00365 
00366           
00367 
00368 
00369           for (i=0; i<ncand; i++) {
00370             k = cand[i].val;
00371     
00372             if (mypmat[k] > 0) {
00373               
00374               if (!ivecaxpylez(ncon, 1, cpwgt, pwgts+k*ncon, maxpwgt+k*ncon))
00375                 continue;
00376     
00377               
00378               for (j=0; j<nads[k]; j++) 
00379                 kpmat[adids[k][j]] = adwgts[k][j];
00380     
00381               
00382 
00383 
00384               for (j=0; j<nparts; j++) {
00385                 if (otherpmat[j] > 0 && kpmat[j] == 0 && nads[j]+1 >= nads[me]) 
00386                   break;
00387               }
00388   
00389               
00390 
00391               if (j == nparts) { 
00392                 for (nadd=0, j=0; j<nparts; j++) {
00393                   if (otherpmat[j] > 0 && kpmat[j] == 0)
00394                     nadd++;
00395                 }
00396     
00397                 IFSET(ctrl->dbglvl, METIS_DBG_CONNINFO, 
00398                       printf("\t\tto=%"PRIDX", nadd=%"PRIDX", %"PRIDX"\n", k, nadd, nads[k]));
00399     
00400                 if (nads[k]+nadd < nads[me]) {
00401                   if (target2 == -1 || nads[target2]+bestnadd > nads[k]+nadd ||
00402                       (nads[target2]+bestnadd == nads[k]+nadd && bestnadd > nadd)) {
00403                     target2  = k;
00404                     bestnadd = nadd;
00405                   }
00406                 }
00407   
00408                 if (nadd == 0) 
00409                   target = k;
00410               }
00411 
00412               
00413               for (j=0; j<nads[k]; j++) 
00414                 kpmat[adids[k][j]] = 0;
00415             }
00416 
00417             if (target != -1)
00418               break;
00419           }
00420 
00421           
00422           for (i=0; i<ncand; i++) 
00423             otherpmat[cand[i].val] = 0;
00424 
00425           if (target == -1 && target2 != -1)
00426             target = target2;
00427     
00428           if (target != -1) {
00429             IFSET(ctrl->dbglvl, METIS_DBG_CONNINFO, 
00430                 printf("\t\tScheme: %"PRIDX". Moving to %"PRIDX"\n", scheme, target));
00431             move = 1;
00432             break;
00433           }
00434         }
00435 
00436         if (target != -1)
00437           break;  
00438       }
00439 
00440       
00441       for (i=0; i<nads[me]; i++) 
00442         mypmat[adids[me][i]] = 0;
00443 
00444       
00445 
00446       if (target != -1) {
00447         switch (ctrl->objtype) {
00448           case METIS_OBJTYPE_CUT:
00449             MoveGroupMinConnForCut(ctrl, graph, target, nind, ind);
00450             break;
00451           case METIS_OBJTYPE_VOL:
00452             MoveGroupMinConnForVol(ctrl, graph, target, nind, ind, vmarker, 
00453                 pmarker, modind);
00454             break;
00455           default:
00456             gk_errexit(SIGERR, "Unknown objtype of %d\n", ctrl->objtype);
00457         }
00458 
00459         
00460         iarray2csr(nvtxs, nparts, where, pptr, pind);
00461       }
00462     }
00463 
00464     if (move == 0)
00465       break;
00466   }
00467 
00468   ipqFree(&queue);
00469 
00470   WCOREPOP;
00471 }
00472 
00473 
00474 
00476 
00477 void MoveGroupMinConnForCut(ctrl_t *ctrl, graph_t *graph, idx_t to, idx_t nind, 
00478          idx_t *ind)
00479 {
00480   idx_t i, ii, j, jj, k, l, nvtxs, nbnd, from, me;
00481   idx_t *xadj, *adjncy, *adjwgt, *where, *bndptr, *bndind;
00482   ckrinfo_t *myrinfo;
00483   cnbr_t *mynbrs;
00484 
00485   nvtxs  = graph->nvtxs;
00486   xadj   = graph->xadj;
00487   adjncy = graph->adjncy;
00488   adjwgt = graph->adjwgt;
00489 
00490   where  = graph->where;
00491   bndptr = graph->bndptr;
00492   bndind = graph->bndind;
00493 
00494   nbnd = graph->nbnd;
00495 
00496   while (--nind>=0) {
00497     i    = ind[nind];
00498     from = where[i];
00499 
00500     myrinfo = graph->ckrinfo+i;
00501     if (myrinfo->inbr == -1) {
00502       myrinfo->inbr  = cnbrpoolGetNext(ctrl, xadj[i+1]-xadj[i]+1);
00503       myrinfo->nnbrs = 0;
00504     }
00505     mynbrs = ctrl->cnbrpool + myrinfo->inbr;
00506 
00507     
00508     for (k=0; k<myrinfo->nnbrs; k++) {
00509       if (mynbrs[k].pid == to)
00510         break;
00511     }
00512     if (k == myrinfo->nnbrs) {
00513       ASSERT(k < xadj[i+1]-xadj[i]);
00514       mynbrs[k].pid = to;
00515       mynbrs[k].ed  = 0;
00516       myrinfo->nnbrs++;
00517     }
00518 
00519     
00520     iaxpy(graph->ncon,  1, graph->vwgt+i*graph->ncon, 1, graph->pwgts+to*graph->ncon,   1);
00521     iaxpy(graph->ncon, -1, graph->vwgt+i*graph->ncon, 1, graph->pwgts+from*graph->ncon, 1);
00522 
00523     
00524     graph->mincut -= mynbrs[k].ed-myrinfo->id;
00525 
00526     
00527     UpdateEdgeSubDomainGraph(ctrl, from, to, myrinfo->id-mynbrs[k].ed, NULL);
00528 
00529     
00530     UpdateMovedVertexInfoAndBND(i, from, k, to, myrinfo, mynbrs, where, nbnd, 
00531         bndptr, bndind, BNDTYPE_REFINE);
00532 
00533     
00534     for (j=xadj[i]; j<xadj[i+1]; j++) {
00535       ii = adjncy[j];
00536       me = where[ii];
00537       myrinfo = graph->ckrinfo+ii;
00538 
00539       UpdateAdjacentVertexInfoAndBND(ctrl, ii, xadj[ii+1]-xadj[ii], me,
00540           from, to, myrinfo, adjwgt[j], nbnd, bndptr, bndind, BNDTYPE_REFINE);
00541 
00542       
00543 
00544       if (me != from && me != to) {
00545         UpdateEdgeSubDomainGraph(ctrl, from, me, -adjwgt[j], NULL);
00546         UpdateEdgeSubDomainGraph(ctrl, to, me, adjwgt[j], NULL);
00547       }
00548     }
00549   }
00550 
00551   ASSERT(ComputeCut(graph, where) == graph->mincut);
00552 
00553   graph->nbnd = nbnd;
00554 
00555 }
00556 
00557 
00558 
00560 
00561 void MoveGroupMinConnForVol(ctrl_t *ctrl, graph_t *graph, idx_t to, idx_t nind, 
00562          idx_t *ind, idx_t *vmarker, idx_t *pmarker, idx_t *modind)
00563 {
00564   idx_t i, ii, j, jj, k, l, nvtxs, from, me, other, xgain, ewgt;
00565   idx_t *xadj, *vsize, *adjncy, *where;
00566   vkrinfo_t *myrinfo, *orinfo;
00567   vnbr_t *mynbrs, *onbrs;
00568 
00569   nvtxs  = graph->nvtxs;
00570   xadj   = graph->xadj;
00571   vsize  = graph->vsize;
00572   adjncy = graph->adjncy;
00573   where  = graph->where;
00574 
00575   while (--nind>=0) {
00576     i    = ind[nind];
00577     from = where[i];
00578 
00579     myrinfo = graph->vkrinfo+i;
00580     if (myrinfo->inbr == -1) {
00581       myrinfo->inbr  = vnbrpoolGetNext(ctrl, xadj[i+1]-xadj[i]+1);
00582       myrinfo->nnbrs = 0;
00583     }
00584     mynbrs = ctrl->vnbrpool + myrinfo->inbr;
00585 
00586     xgain = (myrinfo->nid == 0 && myrinfo->ned > 0 ? vsize[i] : 0);
00587 
00588     
00589     
00590     
00591     
00592     for (k=0; k<myrinfo->nnbrs; k++) {
00593       if (mynbrs[k].pid == to)
00594         break;
00595     }
00596 
00597     if (k == myrinfo->nnbrs) {
00598       
00599 
00600       if (myrinfo->nid > 0)
00601         xgain -= vsize[i];
00602 
00603       
00604       for (j=xadj[i]; j<xadj[i+1]; j++) {
00605         ii     = adjncy[j];
00606         other  = where[ii];
00607         orinfo = graph->vkrinfo+ii;
00608         onbrs  = ctrl->vnbrpool + orinfo->inbr;
00609         ASSERT(other != to)
00610 
00611         
00612 
00613         if (from == other) {
00614           
00615           for (l=0; l<orinfo->nnbrs; l++) {
00616             if (onbrs[l].pid == to)
00617               break;
00618           }
00619           if (l == orinfo->nnbrs) 
00620             xgain -= vsize[ii];
00621         }
00622         else {
00623           
00624           for (l=0; l<orinfo->nnbrs; l++) {
00625             if (onbrs[l].pid == to)
00626               break;
00627           }
00628           if (l == orinfo->nnbrs) 
00629             xgain -= vsize[ii];
00630 
00631           
00632           for (l=0; l<orinfo->nnbrs; l++) {
00633             if (onbrs[l].pid == from && onbrs[l].ned == 1) {
00634               xgain += vsize[ii];
00635               break;
00636             }
00637           }
00638         }
00639       }
00640       graph->minvol -= xgain;
00641       graph->mincut -= -myrinfo->nid;
00642       ewgt = myrinfo->nid;
00643     }
00644     else {
00645       graph->minvol -= (xgain + mynbrs[k].gv);
00646       graph->mincut -= mynbrs[k].ned-myrinfo->nid;
00647       ewgt = myrinfo->nid-mynbrs[k].ned;
00648     }
00649 
00650     
00651     where[i] = to;
00652     iaxpy(graph->ncon,  1, graph->vwgt+i*graph->ncon, 1, graph->pwgts+to*graph->ncon,   1);
00653     iaxpy(graph->ncon, -1, graph->vwgt+i*graph->ncon, 1, graph->pwgts+from*graph->ncon, 1);
00654 
00655     
00656     UpdateEdgeSubDomainGraph(ctrl, from, to, ewgt, NULL);
00657 
00658     
00659     for (j=xadj[i]; j<xadj[i+1]; j++) {
00660       me = where[adjncy[j]];
00661       if (me != from && me != to) {
00662         UpdateEdgeSubDomainGraph(ctrl, from, me, -1, NULL);
00663         UpdateEdgeSubDomainGraph(ctrl, to, me, 1, NULL);
00664       }
00665     }
00666 
00667     
00668     KWayVolUpdate(ctrl, graph, i, from, to, NULL, NULL, NULL, NULL,
00669         NULL, BNDTYPE_REFINE, vmarker, pmarker, modind);
00670 
00671     
00672   }
00673   ASSERT(ComputeCut(graph, where) == graph->mincut);
00674   ASSERTP(ComputeVolume(graph, where) == graph->minvol, 
00675       ("%"PRIDX" %"PRIDX"\n", ComputeVolume(graph, where), graph->minvol));
00676 
00677 }
00678 
00679 
00680 
00682 
00683 void PrintSubDomainGraph(graph_t *graph, idx_t nparts, idx_t *where)
00684 {
00685   idx_t i, j, k, me, nvtxs, total, max;
00686   idx_t *xadj, *adjncy, *adjwgt, *pmat;
00687 
00688   nvtxs  = graph->nvtxs;
00689   xadj   = graph->xadj;
00690   adjncy = graph->adjncy;
00691   adjwgt = graph->adjwgt;
00692 
00693   pmat = ismalloc(nparts*nparts, 0, "ComputeSubDomainGraph: pmat");
00694 
00695   for (i=0; i<nvtxs; i++) {
00696     me = where[i];
00697     for (j=xadj[i]; j<xadj[i+1]; j++) {
00698       k = adjncy[j];
00699       if (where[k] != me) 
00700         pmat[me*nparts+where[k]] += adjwgt[j];
00701     }
00702   }
00703 
00704   
00705   total = max = 0;
00706   for (i=0; i<nparts; i++) {
00707     for (k=0, j=0; j<nparts; j++) {
00708       if (pmat[i*nparts+j] > 0)
00709         k++;
00710     }
00711     total += k;
00712 
00713     if (k > max)
00714       max = k;
00715 
00716 
00717 
00718 
00719 
00720 
00721 
00722 
00723   }
00724   printf("Total adjacent subdomains: %"PRIDX", Max: %"PRIDX"\n", total, max);
00725 
00726   gk_free((void **)&pmat, LTERM);
00727 }
00728 
00729