00001 
00012 #include "metislib.h"
00013 
00014 #define UNMATCHEDFOR2HOP  0.10  
00015                                   
00016 
00017 
00021 
00022 graph_t *CoarsenGraph(ctrl_t *ctrl, graph_t *graph)
00023 {
00024   idx_t i, eqewgts, level=0;
00025 
00026   IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->CoarsenTmr));
00027 
00028   
00029   for (eqewgts=1, i=1; i<graph->nedges; i++) {
00030     if (graph->adjwgt[0] != graph->adjwgt[i]) {
00031       eqewgts = 0;
00032       break;
00033     }
00034   }
00035 
00036   
00037   for (i=0; i<graph->ncon; i++)
00038     ctrl->maxvwgt[i] = 1.5*graph->tvwgt[i]/ctrl->CoarsenTo;
00039 
00040   do {
00041     IFSET(ctrl->dbglvl, METIS_DBG_COARSEN, PrintCGraphStats(ctrl, graph));
00042 
00043     
00044 
00045     if (graph->cmap == NULL)
00046       graph->cmap = imalloc(graph->nvtxs, "CoarsenGraph: graph->cmap");
00047 
00048     
00049     switch (ctrl->ctype) {
00050       case METIS_CTYPE_RM:
00051         Match_RM(ctrl, graph);
00052         break;
00053       case METIS_CTYPE_SHEM:
00054         if (eqewgts || graph->nedges == 0)
00055           Match_RM(ctrl, graph);
00056         else
00057           Match_SHEM(ctrl, graph);
00058         break;
00059       default:
00060         gk_errexit(SIGERR, "Unknown ctype: %d\n", ctrl->ctype);
00061     }
00062 
00063     graph = graph->coarser;
00064     eqewgts = 0;
00065     level++;
00066 
00067     ASSERT(CheckGraph(graph, 0, 1));
00068 
00069   } while (graph->nvtxs > ctrl->CoarsenTo && 
00070            graph->nvtxs < COARSEN_FRACTION*graph->finer->nvtxs && 
00071            graph->nedges > graph->nvtxs/2);
00072 
00073   IFSET(ctrl->dbglvl, METIS_DBG_COARSEN, PrintCGraphStats(ctrl, graph));
00074   IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->CoarsenTmr));
00075 
00076   return graph;
00077 }
00078 
00079 
00080 
00084 
00085 graph_t *CoarsenGraphNlevels(ctrl_t *ctrl, graph_t *graph, idx_t nlevels)
00086 {
00087   idx_t i, eqewgts, level;
00088 
00089   IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->CoarsenTmr));
00090 
00091   
00092   for (eqewgts=1, i=1; i<graph->nedges; i++) {
00093     if (graph->adjwgt[0] != graph->adjwgt[i]) {
00094       eqewgts = 0;
00095       break;
00096     }
00097   }
00098 
00099   
00100   for (i=0; i<graph->ncon; i++)
00101     ctrl->maxvwgt[i] = 1.5*graph->tvwgt[i]/ctrl->CoarsenTo;
00102 
00103   for (level=0; level<nlevels; level++) {
00104     IFSET(ctrl->dbglvl, METIS_DBG_COARSEN, PrintCGraphStats(ctrl, graph));
00105 
00106     
00107 
00108     if (graph->cmap == NULL)
00109       graph->cmap = imalloc(graph->nvtxs, "CoarsenGraph: graph->cmap");
00110 
00111     
00112     switch (ctrl->ctype) {
00113       case METIS_CTYPE_RM:
00114         Match_RM(ctrl, graph);
00115         break;
00116       case METIS_CTYPE_SHEM:
00117         if (eqewgts || graph->nedges == 0)
00118           Match_RM(ctrl, graph);
00119         else
00120           Match_SHEM(ctrl, graph);
00121         break;
00122       default:
00123         gk_errexit(SIGERR, "Unknown ctype: %d\n", ctrl->ctype);
00124     }
00125 
00126     graph = graph->coarser;
00127     eqewgts = 0;
00128 
00129     ASSERT(CheckGraph(graph, 0, 1));
00130 
00131     if (graph->nvtxs < ctrl->CoarsenTo || 
00132         graph->nvtxs > COARSEN_FRACTION*graph->finer->nvtxs || 
00133         graph->nedges < graph->nvtxs/2)
00134       break; 
00135   } 
00136 
00137   IFSET(ctrl->dbglvl, METIS_DBG_COARSEN, PrintCGraphStats(ctrl, graph));
00138   IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->CoarsenTmr));
00139 
00140   return graph;
00141 }
00142 
00143 
00144 
00148 
00149 idx_t Match_RM(ctrl_t *ctrl, graph_t *graph)
00150 {
00151   idx_t i, pi, ii, j, jj, jjinc, k, nvtxs, ncon, cnvtxs, maxidx, last_unmatched;
00152   idx_t *xadj, *vwgt, *adjncy, *adjwgt, *maxvwgt;
00153   idx_t *match, *cmap, *perm;
00154   size_t nunmatched=0;
00155 
00156   WCOREPUSH;
00157 
00158   IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->MatchTmr));
00159 
00160   nvtxs  = graph->nvtxs;
00161   ncon   = graph->ncon;
00162   xadj   = graph->xadj;
00163   vwgt   = graph->vwgt;
00164   adjncy = graph->adjncy;
00165   adjwgt = graph->adjwgt;
00166   cmap   = graph->cmap;
00167 
00168   maxvwgt  = ctrl->maxvwgt;
00169 
00170   match = iset(nvtxs, UNMATCHED, iwspacemalloc(ctrl, nvtxs));
00171   perm  = iwspacemalloc(ctrl, nvtxs);
00172 
00173   irandArrayPermute(nvtxs, perm, nvtxs/8, 1);
00174 
00175   for (cnvtxs=0, last_unmatched=0, pi=0; pi<nvtxs; pi++) {
00176     i = perm[pi];
00177 
00178     if (match[i] == UNMATCHED) {  
00179       maxidx = i;
00180 
00181       if ((ncon == 1 ? vwgt[i] < maxvwgt[0] : ivecle(ncon, vwgt+i*ncon, maxvwgt))) {
00182         
00183 
00184         if (xadj[i] == xadj[i+1]) {
00185           last_unmatched = gk_max(pi, last_unmatched)+1;
00186           for (; last_unmatched<nvtxs; last_unmatched++) {
00187             j = perm[last_unmatched];
00188             if (match[j] == UNMATCHED) {
00189               maxidx = j;
00190               break;
00191             }
00192           }
00193         }
00194         else {
00195           
00196           if (ncon == 1) {
00197             
00198             for (j=xadj[i]; j<xadj[i+1]; j++) {
00199               k = adjncy[j];
00200               if (match[k] == UNMATCHED && vwgt[i]+vwgt[k] <= maxvwgt[0]) {
00201                 maxidx = k;
00202                 break;
00203               }
00204             }
00205 
00206             
00207             if (maxidx == i && 3*vwgt[i] < maxvwgt[0]) {
00208               nunmatched++;
00209               maxidx = UNMATCHED;
00210             }
00211           }
00212           else {
00213             
00214             for (j=xadj[i]; j<xadj[i+1]; j++) {
00215               k = adjncy[j];
00216               if (match[k] == UNMATCHED && 
00217                   ivecaxpylez(ncon, 1, vwgt+i*ncon, vwgt+k*ncon, maxvwgt)) {
00218                 maxidx = k;
00219                 break;
00220               }
00221             }
00222 
00223             
00224             if (maxidx == i && ivecaxpylez(ncon, 2, vwgt+i*ncon, vwgt+i*ncon, maxvwgt)) {
00225               nunmatched++;
00226               maxidx = UNMATCHED;
00227             }
00228           }
00229         }
00230       }
00231 
00232       if (maxidx != UNMATCHED) {
00233         cmap[i]  = cmap[maxidx] = cnvtxs++;
00234         match[i] = maxidx;
00235         match[maxidx] = i;
00236       }
00237     }
00238   }
00239 
00240   
00241 
00242   
00243   if (!ctrl->no2hop && nunmatched > UNMATCHEDFOR2HOP*nvtxs) 
00244     cnvtxs = Match_2Hop(ctrl, graph, perm, match, cnvtxs, nunmatched);
00245 
00246 
00247   
00248 
00249   for (cnvtxs=0, i=0; i<nvtxs; i++) {
00250     if (match[i] == UNMATCHED) {
00251       match[i] = i;
00252       cmap[i]  = cnvtxs++;
00253     }
00254     else {
00255       if (i <= match[i]) 
00256         cmap[i] = cmap[match[i]] = cnvtxs++;
00257     }
00258   }
00259 
00260   IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->MatchTmr));
00261 
00262   CreateCoarseGraph(ctrl, graph, cnvtxs, match);
00263 
00264   WCOREPOP;
00265 
00266   return cnvtxs;
00267 }
00268 
00269 
00270 
00275 
00276 idx_t Match_SHEM(ctrl_t *ctrl, graph_t *graph)
00277 {
00278   idx_t i, pi, ii, j, jj, jjinc, k, nvtxs, ncon, cnvtxs, maxidx, maxwgt, 
00279         last_unmatched, avgdegree;
00280   idx_t *xadj, *vwgt, *adjncy, *adjwgt, *maxvwgt;
00281   idx_t *match, *cmap, *degrees, *perm, *tperm;
00282   size_t nunmatched=0;
00283 
00284   WCOREPUSH;
00285 
00286   IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->MatchTmr));
00287 
00288   nvtxs  = graph->nvtxs;
00289   ncon   = graph->ncon;
00290   xadj   = graph->xadj;
00291   vwgt   = graph->vwgt;
00292   adjncy = graph->adjncy;
00293   adjwgt = graph->adjwgt;
00294   cmap   = graph->cmap;
00295 
00296   maxvwgt  = ctrl->maxvwgt;
00297 
00298   match   = iset(nvtxs, UNMATCHED, iwspacemalloc(ctrl, nvtxs));
00299   perm    = iwspacemalloc(ctrl, nvtxs);
00300   tperm   = iwspacemalloc(ctrl, nvtxs);
00301   degrees = iwspacemalloc(ctrl, nvtxs);
00302 
00303   irandArrayPermute(nvtxs, tperm, nvtxs/8, 1);
00304 
00305   avgdegree = 0.7*(xadj[nvtxs]/nvtxs);
00306   for (i=0; i<nvtxs; i++) 
00307     degrees[i] = (xadj[i+1]-xadj[i] > avgdegree ? avgdegree : xadj[i+1]-xadj[i]);
00308   BucketSortKeysInc(ctrl, nvtxs, avgdegree, degrees, tperm, perm);
00309 
00310   for (cnvtxs=0, last_unmatched=0, pi=0; pi<nvtxs; pi++) {
00311     i = perm[pi];
00312 
00313     if (match[i] == UNMATCHED) {  
00314       maxidx = i;
00315       maxwgt = -1;
00316 
00317       if ((ncon == 1 ? vwgt[i] < maxvwgt[0] : ivecle(ncon, vwgt+i*ncon, maxvwgt))) {
00318         
00319 
00320         if (xadj[i] == xadj[i+1]) { 
00321           last_unmatched = gk_max(pi, last_unmatched)+1;
00322           for (; last_unmatched<nvtxs; last_unmatched++) {
00323             j = perm[last_unmatched];
00324             if (match[j] == UNMATCHED) {
00325               maxidx = j;
00326               break;
00327             }
00328           }
00329         }
00330         else {
00331           
00332           if (ncon == 1) {
00333             
00334             for (j=xadj[i]; j<xadj[i+1]; j++) {
00335               k = adjncy[j];
00336               if (match[k] == UNMATCHED && 
00337                   maxwgt < adjwgt[j] && vwgt[i]+vwgt[k] <= maxvwgt[0]) {
00338                 maxidx = k;
00339                 maxwgt = adjwgt[j];
00340               }
00341             }
00342 
00343             
00344             if (maxidx == i && 3*vwgt[i] < maxvwgt[0]) {
00345               nunmatched++;
00346               maxidx = UNMATCHED;
00347             }
00348           }
00349           else {
00350             
00351             for (j=xadj[i]; j<xadj[i+1]; j++) {
00352               k = adjncy[j];
00353               if (match[k] == UNMATCHED && 
00354                   ivecaxpylez(ncon, 1, vwgt+i*ncon, vwgt+k*ncon, maxvwgt) &&
00355                   (maxwgt < adjwgt[j] || 
00356                    (maxwgt == adjwgt[j] && 
00357                     BetterVBalance(ncon, graph->invtvwgt, vwgt+i*ncon, 
00358                         vwgt+maxidx*ncon, vwgt+k*ncon)))) {
00359                 maxidx = k;
00360                 maxwgt = adjwgt[j];
00361               }
00362             }
00363 
00364             
00365             if (maxidx == i && ivecaxpylez(ncon, 2, vwgt+i*ncon, vwgt+i*ncon, maxvwgt)) {
00366               nunmatched++;
00367               maxidx = UNMATCHED;
00368             }
00369           }
00370         }
00371       }
00372 
00373       if (maxidx != UNMATCHED) {
00374         cmap[i]  = cmap[maxidx] = cnvtxs++;
00375         match[i] = maxidx;
00376         match[maxidx] = i;
00377       }
00378     }
00379   }
00380 
00381   
00382 
00383   
00384   if (!ctrl->no2hop && nunmatched > UNMATCHEDFOR2HOP*nvtxs) 
00385     cnvtxs = Match_2Hop(ctrl, graph, perm, match, cnvtxs, nunmatched);
00386 
00387 
00388   
00389 
00390   for (cnvtxs=0, i=0; i<nvtxs; i++) {
00391     if (match[i] == UNMATCHED) {
00392       match[i] = i;
00393       cmap[i] = cnvtxs++;
00394     }
00395     else {
00396       if (i <= match[i]) 
00397         cmap[i] = cmap[match[i]] = cnvtxs++;
00398     }
00399   }
00400 
00401   IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->MatchTmr));
00402 
00403   CreateCoarseGraph(ctrl, graph, cnvtxs, match);
00404 
00405   WCOREPOP;
00406 
00407   return cnvtxs;
00408 }
00409 
00410 
00411 
00414 
00415 idx_t Match_2Hop(ctrl_t *ctrl, graph_t *graph, idx_t *perm, idx_t *match, 
00416           idx_t cnvtxs, size_t nunmatched)
00417 {
00418 
00419   cnvtxs = Match_2HopAny(ctrl, graph, perm, match, cnvtxs, &nunmatched, 2);
00420   cnvtxs = Match_2HopAll(ctrl, graph, perm, match, cnvtxs, &nunmatched, 64);
00421   if (nunmatched > 1.5*UNMATCHEDFOR2HOP*graph->nvtxs) 
00422     cnvtxs = Match_2HopAny(ctrl, graph, perm, match, cnvtxs, &nunmatched, 3);
00423   if (nunmatched > 2.0*UNMATCHEDFOR2HOP*graph->nvtxs) 
00424     cnvtxs = Match_2HopAny(ctrl, graph, perm, match, cnvtxs, &nunmatched, graph->nvtxs);
00425 
00426   return cnvtxs;
00427 }
00428 
00429 
00430 
00436 
00437 idx_t Match_2HopAny(ctrl_t *ctrl, graph_t *graph, idx_t *perm, idx_t *match, 
00438           idx_t cnvtxs, size_t *r_nunmatched, size_t maxdegree)
00439 {
00440   idx_t i, pi, ii, j, jj, k, nvtxs;
00441   idx_t *xadj, *adjncy, *colptr, *rowind;
00442   idx_t *cmap;
00443   size_t nunmatched;
00444 
00445   IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->Aux3Tmr));
00446 
00447   nvtxs  = graph->nvtxs;
00448   xadj   = graph->xadj;
00449   adjncy = graph->adjncy;
00450   cmap   = graph->cmap;
00451 
00452   nunmatched = *r_nunmatched;
00453 
00454   
00455 
00456   
00457   WCOREPUSH;
00458   colptr = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs+1));
00459   for (i=0; i<nvtxs; i++) {
00460     if (match[i] == UNMATCHED && xadj[i+1]-xadj[i] < maxdegree) {
00461       for (j=xadj[i]; j<xadj[i+1]; j++)
00462         colptr[adjncy[j]]++;
00463     }
00464   }
00465   MAKECSR(i, nvtxs, colptr);
00466 
00467   rowind = iwspacemalloc(ctrl, colptr[nvtxs]);
00468   for (pi=0; pi<nvtxs; pi++) {
00469     i = perm[pi];
00470     if (match[i] == UNMATCHED && xadj[i+1]-xadj[i] < maxdegree) {
00471       for (j=xadj[i]; j<xadj[i+1]; j++)
00472         rowind[colptr[adjncy[j]]++] = i;
00473     }
00474   }
00475   SHIFTCSR(i, nvtxs, colptr);
00476 
00477   
00478   for (pi=0; pi<nvtxs; pi++) {
00479     i = perm[pi];
00480     if (colptr[i+1]-colptr[i] < 2)
00481       continue;
00482 
00483     for (jj=colptr[i+1], j=colptr[i]; j<jj; j++) {
00484       if (match[rowind[j]] == UNMATCHED) {
00485         for (jj--; jj>j; jj--) {
00486           if (match[rowind[jj]] == UNMATCHED) {
00487             cmap[rowind[j]] = cmap[rowind[jj]] = cnvtxs++;
00488             match[rowind[j]]  = rowind[jj];
00489             match[rowind[jj]] = rowind[j];
00490             nunmatched -= 2;
00491             break;
00492           }
00493         }
00494       }
00495     }
00496   }
00497   WCOREPOP;
00498 
00499   
00500 
00501   IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->Aux3Tmr));
00502 
00503   *r_nunmatched = nunmatched;
00504   return cnvtxs;
00505 }
00506 
00507 
00508 
00515 
00516 idx_t Match_2HopAll(ctrl_t *ctrl, graph_t *graph, idx_t *perm, idx_t *match, 
00517           idx_t cnvtxs, size_t *r_nunmatched, size_t maxdegree)
00518 {
00519   idx_t i, pi, pk, ii, j, jj, k, nvtxs, mask, idegree;
00520   idx_t *xadj, *adjncy;
00521   idx_t *cmap, *mark;
00522   ikv_t *keys;
00523   size_t nunmatched, ncand;
00524 
00525   IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->Aux3Tmr));
00526 
00527   nvtxs  = graph->nvtxs;
00528   xadj   = graph->xadj;
00529   adjncy = graph->adjncy;
00530   cmap   = graph->cmap;
00531 
00532   nunmatched = *r_nunmatched;
00533   mask = IDX_MAX/maxdegree;
00534 
00535   
00536 
00537   WCOREPUSH;
00538 
00539   
00540   keys = ikvwspacemalloc(ctrl, nunmatched);
00541   for (ncand=0, pi=0; pi<nvtxs; pi++) {
00542     i = perm[pi];
00543     idegree = xadj[i+1]-xadj[i];
00544     if (match[i] == UNMATCHED && idegree > 1 && idegree < maxdegree) {
00545       for (k=0, j=xadj[i]; j<xadj[i+1]; j++) 
00546         k += adjncy[j]%mask;
00547       keys[ncand].val = i;
00548       keys[ncand].key = (k%mask)*maxdegree + idegree;
00549       ncand++;
00550     }
00551   }
00552   ikvsorti(ncand, keys);
00553 
00554   mark = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs));
00555   for (pi=0; pi<ncand; pi++) {
00556     i = keys[pi].val;
00557     if (match[i] != UNMATCHED)
00558       continue;
00559 
00560     for (j=xadj[i]; j<xadj[i+1]; j++)
00561       mark[adjncy[j]] = i;
00562 
00563     for (pk=pi+1; pk<ncand; pk++) {
00564       k = keys[pk].val;
00565       if (match[k] != UNMATCHED)
00566         continue;
00567 
00568       if (keys[pi].key != keys[pk].key)
00569         break;
00570       if (xadj[i+1]-xadj[i] != xadj[k+1]-xadj[k])
00571         break;
00572 
00573       for (jj=xadj[k]; jj<xadj[k+1]; jj++) {
00574         if (mark[adjncy[jj]] != i)
00575           break;
00576       }
00577       if (jj == xadj[k+1]) {
00578         cmap[i] = cmap[k] = cnvtxs++;
00579         match[i] = k;
00580         match[k] = i;
00581         nunmatched -= 2;
00582         break;
00583       }
00584     }
00585   }
00586   WCOREPOP;
00587 
00588   
00589 
00590   IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->Aux3Tmr));
00591 
00592   *r_nunmatched = nunmatched;
00593   return cnvtxs;
00594 }
00595 
00596 
00597 
00600 
00601 void PrintCGraphStats(ctrl_t *ctrl, graph_t *graph)
00602 {
00603   idx_t i;
00604 
00605   printf("%10"PRIDX" %10"PRIDX" %10"PRIDX" [%"PRIDX"] [", 
00606       graph->nvtxs, graph->nedges, isum(graph->nedges, graph->adjwgt, 1), ctrl->CoarsenTo);
00607 
00608   for (i=0; i<graph->ncon; i++)
00609     printf(" %8"PRIDX":%8"PRIDX, ctrl->maxvwgt[i], graph->tvwgt[i]);
00610   printf(" ]\n");
00611 }
00612 
00613 
00614 
00620 
00621 void CreateCoarseGraph(ctrl_t *ctrl, graph_t *graph, idx_t cnvtxs, 
00622          idx_t *match)
00623 {
00624   idx_t j, jj, k, kk, l, m, istart, iend, nvtxs, nedges, ncon, cnedges, 
00625         v, u, mask, dovsize;
00626   idx_t *xadj, *vwgt, *vsize, *adjncy, *adjwgt;
00627   idx_t *cmap, *htable;
00628   idx_t *cxadj, *cvwgt, *cvsize, *cadjncy, *cadjwgt;
00629   graph_t *cgraph;
00630 
00631   dovsize = (ctrl->objtype == METIS_OBJTYPE_VOL ? 1 : 0);
00632 
00633   
00634   mask = HTLENGTH;
00635   if (cnvtxs < 2*mask || graph->nedges/graph->nvtxs > mask/20) { 
00636     CreateCoarseGraphNoMask(ctrl, graph, cnvtxs, match);
00637     return;
00638   }
00639 
00640   nvtxs = graph->nvtxs;
00641   xadj  = graph->xadj;
00642   for (v=0; v<nvtxs; v++) {
00643     if (xadj[v+1]-xadj[v] > (mask>>3)) {
00644       CreateCoarseGraphNoMask(ctrl, graph, cnvtxs, match);
00645       return;
00646     }
00647   }
00648 
00649 
00650   WCOREPUSH;
00651 
00652   IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->ContractTmr));
00653 
00654   ncon    = graph->ncon;
00655   vwgt    = graph->vwgt;
00656   vsize   = graph->vsize;
00657   adjncy  = graph->adjncy;
00658   adjwgt  = graph->adjwgt;
00659   cmap    = graph->cmap;
00660 
00661   
00662   cgraph   = SetupCoarseGraph(graph, cnvtxs, dovsize);
00663   cxadj    = cgraph->xadj;
00664   cvwgt    = cgraph->vwgt;
00665   cvsize   = cgraph->vsize;
00666   cadjncy  = cgraph->adjncy;
00667   cadjwgt  = cgraph->adjwgt;
00668 
00669   htable = iset(gk_min(cnvtxs+1, mask+1), -1, iwspacemalloc(ctrl, mask+1)); 
00670 
00671   cxadj[0] = cnvtxs = cnedges = 0;
00672   for (v=0; v<nvtxs; v++) {
00673     if ((u = match[v]) < v)
00674       continue;
00675 
00676     ASSERT(cmap[v] == cnvtxs);
00677     ASSERT(cmap[match[v]] == cnvtxs);
00678 
00679     if (ncon == 1)
00680       cvwgt[cnvtxs] = vwgt[v];
00681     else
00682       icopy(ncon, vwgt+v*ncon, cvwgt+cnvtxs*ncon);
00683 
00684     if (dovsize)
00685       cvsize[cnvtxs] = vsize[v];
00686 
00687     nedges = 0;
00688 
00689     istart = xadj[v];
00690     iend   = xadj[v+1];
00691     for (j=istart; j<iend; j++) {
00692       k  = cmap[adjncy[j]];
00693       kk = k&mask;
00694       if ((m = htable[kk]) == -1) {
00695         cadjncy[nedges] = k;
00696         cadjwgt[nedges] = adjwgt[j];
00697         htable[kk] = nedges++;
00698       }
00699       else if (cadjncy[m] == k) {
00700         cadjwgt[m] += adjwgt[j];
00701       }
00702       else {
00703         for (jj=0; jj<nedges; jj++) {
00704           if (cadjncy[jj] == k) {
00705             cadjwgt[jj] += adjwgt[j];
00706             break;
00707           }
00708         }
00709         if (jj == nedges) {
00710           cadjncy[nedges]   = k;
00711           cadjwgt[nedges++] = adjwgt[j];
00712         }
00713       }
00714     }
00715 
00716     if (v != u) { 
00717       if (ncon == 1)
00718         cvwgt[cnvtxs] += vwgt[u];
00719       else
00720         iaxpy(ncon, 1, vwgt+u*ncon, 1, cvwgt+cnvtxs*ncon, 1);
00721 
00722       if (dovsize)
00723         cvsize[cnvtxs] += vsize[u];
00724 
00725       istart = xadj[u];
00726       iend   = xadj[u+1];
00727       for (j=istart; j<iend; j++) {
00728         k  = cmap[adjncy[j]];
00729         kk = k&mask;
00730         if ((m = htable[kk]) == -1) {
00731           cadjncy[nedges] = k;
00732           cadjwgt[nedges] = adjwgt[j];
00733           htable[kk]      = nedges++;
00734         }
00735         else if (cadjncy[m] == k) {
00736           cadjwgt[m] += adjwgt[j];
00737         }
00738         else {
00739           for (jj=0; jj<nedges; jj++) {
00740             if (cadjncy[jj] == k) {
00741               cadjwgt[jj] += adjwgt[j];
00742               break;
00743             }
00744           }
00745           if (jj == nedges) {
00746             cadjncy[nedges]   = k;
00747             cadjwgt[nedges++] = adjwgt[j];
00748           }
00749         }
00750       }
00751 
00752       
00753       jj = htable[cnvtxs&mask];
00754       if (jj >= 0 && cadjncy[jj] != cnvtxs) {
00755         for (jj=0; jj<nedges; jj++) {
00756           if (cadjncy[jj] == cnvtxs) 
00757             break;
00758         }
00759       }
00760       
00761       if (jj >= 0 && jj < nedges && cadjncy[jj] == cnvtxs) { 
00762         cadjncy[jj] = cadjncy[--nedges];
00763         cadjwgt[jj] = cadjwgt[nedges];
00764       }
00765     }
00766 
00767     
00768     for (j=0; j<nedges; j++)
00769       htable[cadjncy[j]&mask] = -1;  
00770     htable[cnvtxs&mask] = -1;
00771 
00772     cnedges         += nedges;
00773     cxadj[++cnvtxs]  = cnedges;
00774     cadjncy         += nedges;
00775     cadjwgt         += nedges;
00776   }
00777 
00778   cgraph->nedges = cnedges;
00779 
00780   for (j=0; j<ncon; j++) {
00781     cgraph->tvwgt[j]    = isum(cgraph->nvtxs, cgraph->vwgt+j, ncon);
00782     cgraph->invtvwgt[j] = 1.0/(cgraph->tvwgt[j] > 0 ? cgraph->tvwgt[j] : 1);
00783   }
00784 
00785 
00786   ReAdjustMemory(ctrl, graph, cgraph);
00787 
00788   IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->ContractTmr));
00789 
00790   WCOREPOP;
00791 }
00792 
00793 
00794 
00799 
00800 void CreateCoarseGraphNoMask(ctrl_t *ctrl, graph_t *graph, idx_t cnvtxs, 
00801          idx_t *match)
00802 {
00803   idx_t j, k, m, istart, iend, nvtxs, nedges, ncon, cnedges, v, u, dovsize;
00804   idx_t *xadj, *vwgt, *vsize, *adjncy, *adjwgt;
00805   idx_t *cmap, *htable;
00806   idx_t *cxadj, *cvwgt, *cvsize, *cadjncy, *cadjwgt;
00807   graph_t *cgraph;
00808 
00809   WCOREPUSH;
00810 
00811   dovsize = (ctrl->objtype == METIS_OBJTYPE_VOL ? 1 : 0);
00812 
00813   IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->ContractTmr));
00814 
00815   nvtxs   = graph->nvtxs;
00816   ncon    = graph->ncon;
00817   xadj    = graph->xadj;
00818   vwgt    = graph->vwgt;
00819   vsize   = graph->vsize;
00820   adjncy  = graph->adjncy;
00821   adjwgt  = graph->adjwgt;
00822   cmap    = graph->cmap;
00823 
00824 
00825   
00826   cgraph = SetupCoarseGraph(graph, cnvtxs, dovsize);
00827   cxadj    = cgraph->xadj;
00828   cvwgt    = cgraph->vwgt;
00829   cvsize   = cgraph->vsize;
00830   cadjncy  = cgraph->adjncy;
00831   cadjwgt  = cgraph->adjwgt;
00832 
00833   htable = iset(cnvtxs, -1, iwspacemalloc(ctrl, cnvtxs));
00834 
00835   cxadj[0] = cnvtxs = cnedges = 0;
00836   for (v=0; v<nvtxs; v++) {
00837     if ((u = match[v]) < v)
00838       continue;
00839 
00840     ASSERT(cmap[v] == cnvtxs);
00841     ASSERT(cmap[match[v]] == cnvtxs);
00842 
00843     if (ncon == 1)
00844       cvwgt[cnvtxs] = vwgt[v];
00845     else
00846       icopy(ncon, vwgt+v*ncon, cvwgt+cnvtxs*ncon);
00847 
00848     if (dovsize)
00849       cvsize[cnvtxs] = vsize[v];
00850 
00851     nedges = 0;
00852 
00853     istart = xadj[v];
00854     iend   = xadj[v+1];
00855     for (j=istart; j<iend; j++) {
00856       k = cmap[adjncy[j]];
00857       if ((m = htable[k]) == -1) {
00858         cadjncy[nedges] = k;
00859         cadjwgt[nedges] = adjwgt[j];
00860         htable[k] = nedges++;
00861       }
00862       else {
00863         cadjwgt[m] += adjwgt[j];
00864       }
00865     }
00866 
00867     if (v != u) { 
00868       if (ncon == 1)
00869         cvwgt[cnvtxs] += vwgt[u];
00870       else
00871         iaxpy(ncon, 1, vwgt+u*ncon, 1, cvwgt+cnvtxs*ncon, 1);
00872 
00873       if (dovsize)
00874         cvsize[cnvtxs] += vsize[u];
00875 
00876       istart = xadj[u];
00877       iend   = xadj[u+1];
00878       for (j=istart; j<iend; j++) {
00879         k = cmap[adjncy[j]];
00880         if ((m = htable[k]) == -1) {
00881           cadjncy[nedges] = k;
00882           cadjwgt[nedges] = adjwgt[j];
00883           htable[k] = nedges++;
00884         }
00885         else {
00886           cadjwgt[m] += adjwgt[j];
00887         }
00888       }
00889 
00890       
00891       if ((j = htable[cnvtxs]) != -1) {
00892         ASSERT(cadjncy[j] == cnvtxs);
00893         cadjncy[j]        = cadjncy[--nedges];
00894         cadjwgt[j]        = cadjwgt[nedges];
00895         htable[cnvtxs] = -1;
00896       }
00897     }
00898 
00899     
00900     for (j=0; j<nedges; j++)
00901       htable[cadjncy[j]] = -1;  
00902 
00903     cnedges         += nedges;
00904     cxadj[++cnvtxs]  = cnedges;
00905     cadjncy         += nedges;
00906     cadjwgt         += nedges;
00907   }
00908 
00909   cgraph->nedges = cnedges;
00910 
00911   for (j=0; j<ncon; j++) {
00912     cgraph->tvwgt[j]    = isum(cgraph->nvtxs, cgraph->vwgt+j, ncon);
00913     cgraph->invtvwgt[j] = 1.0/(cgraph->tvwgt[j] > 0 ? cgraph->tvwgt[j] : 1);
00914   }
00915 
00916   ReAdjustMemory(ctrl, graph, cgraph);
00917 
00918   IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->ContractTmr));
00919 
00920   WCOREPOP;
00921 }
00922 
00923 
00924 
00931 
00932 void CreateCoarseGraphPerm(ctrl_t *ctrl, graph_t *graph, idx_t cnvtxs, 
00933          idx_t *match, idx_t *perm)
00934 {
00935   idx_t i, j, jj, k, kk, l, m, istart, iend, nvtxs, nedges, ncon, cnedges, 
00936         v, u, mask, dovsize;
00937   idx_t *xadj, *vwgt, *vsize, *adjncy, *adjwgt;
00938   idx_t *cmap, *htable;
00939   idx_t *cxadj, *cvwgt, *cvsize, *cadjncy, *cadjwgt;
00940   graph_t *cgraph;
00941 
00942   WCOREPUSH;
00943 
00944   IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->ContractTmr));
00945 
00946   dovsize = (ctrl->objtype == METIS_OBJTYPE_VOL ? 1 : 0);
00947 
00948   mask = HTLENGTH;
00949 
00950   nvtxs   = graph->nvtxs;
00951   ncon    = graph->ncon;
00952   xadj    = graph->xadj;
00953   vwgt    = graph->vwgt;
00954   vsize   = graph->vsize;
00955   adjncy  = graph->adjncy;
00956   adjwgt  = graph->adjwgt;
00957   cmap    = graph->cmap;
00958 
00959   
00960   cgraph   = SetupCoarseGraph(graph, cnvtxs, dovsize);
00961   cxadj    = cgraph->xadj;
00962   cvwgt    = cgraph->vwgt;
00963   cvsize   = cgraph->vsize;
00964   cadjncy  = cgraph->adjncy;
00965   cadjwgt  = cgraph->adjwgt;
00966 
00967   htable = iset(mask+1, -1, iwspacemalloc(ctrl, mask+1)); 
00968 
00969   cxadj[0] = cnvtxs = cnedges = 0;
00970   for (i=0; i<nvtxs; i++) {
00971     v = perm[i];
00972     if (cmap[v] != cnvtxs) 
00973       continue;
00974 
00975     u = match[v];
00976     if (ncon == 1)
00977       cvwgt[cnvtxs] = vwgt[v];
00978     else
00979       icopy(ncon, vwgt+v*ncon, cvwgt+cnvtxs*ncon);
00980 
00981     if (dovsize)
00982       cvsize[cnvtxs] = vsize[v];
00983 
00984     nedges = 0;
00985 
00986     istart = xadj[v];
00987     iend = xadj[v+1];
00988     for (j=istart; j<iend; j++) {
00989       k  = cmap[adjncy[j]];
00990       kk = k&mask;
00991       if ((m = htable[kk]) == -1) {
00992         cadjncy[nedges] = k;
00993         cadjwgt[nedges] = adjwgt[j];
00994         htable[kk] = nedges++;
00995       }
00996       else if (cadjncy[m] == k) {
00997         cadjwgt[m] += adjwgt[j];
00998       }
00999       else {
01000         for (jj=0; jj<nedges; jj++) {
01001           if (cadjncy[jj] == k) {
01002             cadjwgt[jj] += adjwgt[j];
01003             break;
01004           }
01005         }
01006         if (jj == nedges) {
01007           cadjncy[nedges] = k;
01008           cadjwgt[nedges++] = adjwgt[j];
01009         }
01010       }
01011     }
01012 
01013     if (v != u) { 
01014       if (ncon == 1)
01015         cvwgt[cnvtxs] += vwgt[u];
01016       else
01017         iaxpy(ncon, 1, vwgt+u*ncon, 1, cvwgt+cnvtxs*ncon, 1);
01018 
01019       if (dovsize)
01020         cvsize[cnvtxs] += vsize[u];
01021 
01022       istart = xadj[u];
01023       iend = xadj[u+1];
01024       for (j=istart; j<iend; j++) {
01025         k  = cmap[adjncy[j]];
01026         kk = k&mask;
01027         if ((m = htable[kk]) == -1) {
01028           cadjncy[nedges] = k;
01029           cadjwgt[nedges] = adjwgt[j];
01030           htable[kk] = nedges++;
01031         }
01032         else if (cadjncy[m] == k) {
01033           cadjwgt[m] += adjwgt[j];
01034         }
01035         else {
01036           for (jj=0; jj<nedges; jj++) {
01037             if (cadjncy[jj] == k) {
01038               cadjwgt[jj] += adjwgt[j];
01039               break;
01040             }
01041           }
01042           if (jj == nedges) {
01043             cadjncy[nedges] = k;
01044             cadjwgt[nedges++] = adjwgt[j];
01045           }
01046         }
01047       }
01048 
01049       
01050       jj = htable[cnvtxs&mask];
01051       if (jj >= 0 && cadjncy[jj] != cnvtxs) {
01052         for (jj=0; jj<nedges; jj++) {
01053           if (cadjncy[jj] == cnvtxs) 
01054             break;
01055         }
01056       }
01057       if (jj >= 0 && cadjncy[jj] == cnvtxs) { 
01058         cadjncy[jj] = cadjncy[--nedges];
01059         cadjwgt[jj] = cadjwgt[nedges];
01060       }
01061     }
01062 
01063     for (j=0; j<nedges; j++)
01064       htable[cadjncy[j]&mask] = -1;  
01065     htable[cnvtxs&mask] = -1;
01066 
01067     cnedges += nedges;
01068     cxadj[++cnvtxs] = cnedges;
01069     cadjncy += nedges;
01070     cadjwgt += nedges;
01071   }
01072 
01073   cgraph->nedges = cnedges;
01074 
01075   for (i=0; i<ncon; i++) {
01076     cgraph->tvwgt[i]    = isum(cgraph->nvtxs, cgraph->vwgt+i, ncon);
01077     cgraph->invtvwgt[i] = 1.0/(cgraph->tvwgt[i] > 0 ? cgraph->tvwgt[i] : 1);
01078   }
01079 
01080 
01081   ReAdjustMemory(ctrl, graph, cgraph);
01082 
01083   IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->ContractTmr));
01084 
01085   WCOREPOP;
01086 }
01087 
01088 
01089 
01092 
01093 graph_t *SetupCoarseGraph(graph_t *graph, idx_t cnvtxs, idx_t dovsize)
01094 {
01095   graph_t *cgraph;
01096 
01097   cgraph = CreateGraph();
01098 
01099   cgraph->nvtxs = cnvtxs;
01100   cgraph->ncon  = graph->ncon;
01101 
01102   cgraph->finer  = graph;
01103   graph->coarser = cgraph;
01104 
01105 
01106   
01107   cgraph->xadj     = imalloc(cnvtxs+1, "SetupCoarseGraph: xadj");
01108   cgraph->adjncy   = imalloc(graph->nedges,   "SetupCoarseGraph: adjncy");
01109   cgraph->adjwgt   = imalloc(graph->nedges,   "SetupCoarseGraph: adjwgt");
01110   cgraph->vwgt     = imalloc(cgraph->ncon*cnvtxs, "SetupCoarseGraph: vwgt");
01111   cgraph->tvwgt    = imalloc(cgraph->ncon, "SetupCoarseGraph: tvwgt");
01112   cgraph->invtvwgt = rmalloc(cgraph->ncon, "SetupCoarseGraph: invtvwgt");
01113 
01114   if (dovsize)
01115     cgraph->vsize = imalloc(cnvtxs,   "SetupCoarseGraph: vsize");
01116 
01117   return cgraph;
01118 }
01119 
01120 
01121 
01125 
01126 void ReAdjustMemory(ctrl_t *ctrl, graph_t *graph, graph_t *cgraph) 
01127 {
01128   if (cgraph->nedges > 10000 && cgraph->nedges < 0.9*graph->nedges) {
01129     cgraph->adjncy = irealloc(cgraph->adjncy, cgraph->nedges, "ReAdjustMemory: adjncy");
01130     cgraph->adjwgt = irealloc(cgraph->adjwgt, cgraph->nedges, "ReAdjustMemory: adjwgt");
01131   }
01132 }