/************************************************************************* * This function is the entry point for ONCMETIS **************************************************************************/ void METIS_NodeND(int *nvtxs, idxtype *xadj, idxtype *adjncy, int *numflag, int *options, idxtype *perm, idxtype *iperm) { int i, ii, j, l, wflag, nflag; GraphType graph; CtrlType ctrl; idxtype *cptr, *cind, *piperm; if (*numflag == 1) Change2CNumbering(*nvtxs, xadj, adjncy); if (options[0] == 0) { /* Use the default parameters */ ctrl.CType = ONMETIS_CTYPE; ctrl.IType = ONMETIS_ITYPE; ctrl.RType = ONMETIS_RTYPE; ctrl.dbglvl = ONMETIS_DBGLVL; ctrl.oflags = ONMETIS_OFLAGS; ctrl.pfactor = ONMETIS_PFACTOR; ctrl.nseps = ONMETIS_NSEPS; } else { ctrl.CType = options[OPTION_CTYPE]; ctrl.IType = options[OPTION_ITYPE]; ctrl.RType = options[OPTION_RTYPE]; ctrl.dbglvl = options[OPTION_DBGLVL]; ctrl.oflags = options[OPTION_OFLAGS]; ctrl.pfactor = options[OPTION_PFACTOR]; ctrl.nseps = options[OPTION_NSEPS]; } if (ctrl.nseps < 1) ctrl.nseps = 1; ctrl.optype = OP_ONMETIS; ctrl.CoarsenTo = 100; IFSET(ctrl.dbglvl, DBG_TIME, InitTimers(&ctrl)); IFSET(ctrl.dbglvl, DBG_TIME, starttimer(ctrl.TotalTmr)); InitRandom(-1); if (ctrl.pfactor > 0) { /*============================================================ * Prune the dense columns ==============================================================*/ piperm = idxmalloc(*nvtxs, "ONMETIS: piperm"); PruneGraph(&ctrl, &graph, *nvtxs, xadj, adjncy, piperm, (float)(0.1*ctrl.pfactor)); } else if (ctrl.oflags&OFLAG_COMPRESS) { /*============================================================ * Compress the graph ==============================================================*/ cptr = idxmalloc(*nvtxs+1, "ONMETIS: cptr"); cind = idxmalloc(*nvtxs, "ONMETIS: cind"); CompressGraph(&ctrl, &graph, *nvtxs, xadj, adjncy, cptr, cind); if (graph.nvtxs >= COMPRESSION_FRACTION*(*nvtxs)) { ctrl.oflags--; /* We actually performed no compression */ GKfree((void**)&cptr, &cind, LTERM); } else if (2*graph.nvtxs < *nvtxs && ctrl.nseps == 1) ctrl.nseps = 2; } else { SetUpGraph(&graph, OP_ONMETIS, *nvtxs, 1, xadj, adjncy, NULL, NULL, 0); } /*============================================================= * Do the nested dissection ordering --=============================================================*/ ctrl.maxvwgt = 1.5*(idxsum(graph.nvtxs, graph.vwgt)/ctrl.CoarsenTo); AllocateWorkSpace(&ctrl, &graph, 2); if (ctrl.oflags&OFLAG_CCMP) MlevelNestedDissectionCC(&ctrl, &graph, iperm, ORDER_UNBALANCE_FRACTION, graph.nvtxs); else MlevelNestedDissection(&ctrl, &graph, iperm, ORDER_UNBALANCE_FRACTION, graph.nvtxs); FreeWorkSpace(&ctrl, &graph); if (ctrl.pfactor > 0) { /* Order any prunned vertices */ if (graph.nvtxs < *nvtxs) { idxcopy(graph.nvtxs, iperm, perm); /* Use perm as an auxiliary array */ for (i=0; i<graph.nvtxs; i++) iperm[piperm[i]] = perm[i]; for (i=graph.nvtxs; i<*nvtxs; i++) iperm[piperm[i]] = i; } GKfree((void**)&piperm, LTERM); } else if (ctrl.oflags&OFLAG_COMPRESS) { /* Uncompress the ordering */ if (graph.nvtxs < COMPRESSION_FRACTION*(*nvtxs)) { /* construct perm from iperm */ for (i=0; i<graph.nvtxs; i++) perm[iperm[i]] = i; for (l=ii=0; ii<graph.nvtxs; ii++) { i = perm[ii]; for (j=cptr[i]; j<cptr[i+1]; j++) iperm[cind[j]] = l++; } } GKfree((void**)&cptr, &cind, LTERM); } for (i=0; i<*nvtxs; i++) perm[iperm[i]] = i; IFSET(ctrl.dbglvl, DBG_TIME, stoptimer(ctrl.TotalTmr)); IFSET(ctrl.dbglvl, DBG_TIME, PrintTimers(&ctrl)); if (*numflag == 1) Change2FNumberingOrder(*nvtxs, xadj, adjncy, perm, iperm); }
/************************************************************************* * This function is the entry point for PWMETIS that accepts exact weights * for the target partitions **************************************************************************/ void METIS_mCPartGraphRecursive2(int *nvtxs, int *ncon, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, int *wgtflag, int *numflag, int *nparts, float *tpwgts, int *options, int *edgecut, idxtype *part) { int i, j; GraphType graph; CtrlType ctrl; float *mytpwgts; float avgwgt; if (*numflag == 1) Change2CNumbering(*nvtxs, xadj, adjncy); SetUpGraph(&graph, OP_PMETIS, *nvtxs, *ncon, xadj, adjncy, vwgt, adjwgt, *wgtflag); graph.npwgts = NULL; mytpwgts = fmalloc(*nparts, "mytpwgts"); scopy(*nparts, tpwgts, mytpwgts); if (options[0] == 0) { /* Use the default parameters */ ctrl.CType = McPMETIS_CTYPE; ctrl.IType = McPMETIS_ITYPE; ctrl.RType = McPMETIS_RTYPE; ctrl.dbglvl = McPMETIS_DBGLVL; } else { ctrl.CType = options[OPTION_CTYPE]; ctrl.IType = options[OPTION_ITYPE]; ctrl.RType = options[OPTION_RTYPE]; ctrl.dbglvl = options[OPTION_DBGLVL]; } ctrl.optype = OP_PMETIS; ctrl.CoarsenTo = 100; ctrl.nmaxvwgt = 1.5/(1.0*ctrl.CoarsenTo); InitRandom(options[7]); AllocateWorkSpace(&ctrl, &graph, *nparts); IFSET(ctrl.dbglvl, DBG_TIME, InitTimers(&ctrl)); IFSET(ctrl.dbglvl, DBG_TIME, starttimer(ctrl.TotalTmr)); ASSERT(CheckGraph(&graph)); *edgecut = MCMlevelRecursiveBisection2(&ctrl, &graph, *nparts, mytpwgts, part, 1.000, 0); /* { idxtype wgt[2048], minwgt, maxwgt, sumwgt; printf("nvtxs: %d, nparts: %d, ncon: %d\n", graph.nvtxs, *nparts, *ncon); for (i=0; i<(*nparts)*(*ncon); i++) wgt[i] = 0; for (i=0; i<graph.nvtxs; i++) for (j=0; j<*ncon; j++) wgt[part[i]*(*ncon)+j] += vwgt[i*(*ncon)+j]; for (j=0; j<*ncon; j++) { minwgt = maxwgt = sumwgt = 0; for (i=0; i<(*nparts); i++) { minwgt = (wgt[i*(*ncon)+j] < wgt[minwgt*(*ncon)+j]) ? i : minwgt; maxwgt = (wgt[i*(*ncon)+j] > wgt[maxwgt*(*ncon)+j]) ? i : maxwgt; sumwgt += wgt[i*(*ncon)+j]; } avgwgt = (float)sumwgt / (float)*nparts; printf("min: %5d, max: %5d, avg: %5.2f, balance: %6.3f\n", wgt[minwgt*(*ncon)+j], wgt[maxwgt*(*ncon)+j], avgwgt, (float)wgt[maxwgt*(*ncon)+j] / avgwgt); } printf("\n"); } */ IFSET(ctrl.dbglvl, DBG_TIME, stoptimer(ctrl.TotalTmr)); IFSET(ctrl.dbglvl, DBG_TIME, PrintTimers(&ctrl)); FreeWorkSpace(&ctrl, &graph); GKfree((void *)&mytpwgts, LTERM); if (*numflag == 1) Change2FNumbering(*nvtxs, xadj, adjncy, part); }
/************************************************************************* * This function is the entry point for the node ND code for ParMETIS **************************************************************************/ void METIS_NodeNDP(int nvtxs, idxtype *xadj, idxtype *adjncy, int npes, int *options, idxtype *perm, idxtype *iperm, idxtype *sizes) { int i, ii, j, l, wflag, nflag; GraphType graph; CtrlType ctrl; idxtype *cptr, *cind; if (options[0] == 0) { /* Use the default parameters */ ctrl.CType = ONMETIS_CTYPE; ctrl.IType = ONMETIS_ITYPE; ctrl.RType = ONMETIS_RTYPE; ctrl.dbglvl = ONMETIS_DBGLVL; ctrl.oflags = ONMETIS_OFLAGS; ctrl.pfactor = ONMETIS_PFACTOR; ctrl.nseps = ONMETIS_NSEPS; } else { ctrl.CType = options[OPTION_CTYPE]; ctrl.IType = options[OPTION_ITYPE]; ctrl.RType = options[OPTION_RTYPE]; ctrl.dbglvl = options[OPTION_DBGLVL]; ctrl.oflags = options[OPTION_OFLAGS]; ctrl.pfactor = options[OPTION_PFACTOR]; ctrl.nseps = options[OPTION_NSEPS]; } if (ctrl.nseps < 1) ctrl.nseps = 1; ctrl.optype = OP_ONMETIS; ctrl.CoarsenTo = 100; IFSET(ctrl.dbglvl, DBG_TIME, InitTimers(&ctrl)); IFSET(ctrl.dbglvl, DBG_TIME, starttimer(ctrl.TotalTmr)); InitRandom(-1); if (ctrl.oflags&OFLAG_COMPRESS) { /*============================================================ * Compress the graph ==============================================================*/ cptr = idxmalloc(nvtxs+1, "ONMETIS: cptr"); cind = idxmalloc(nvtxs, "ONMETIS: cind"); CompressGraph(&ctrl, &graph, nvtxs, xadj, adjncy, cptr, cind); if (graph.nvtxs >= COMPRESSION_FRACTION*(nvtxs)) { ctrl.oflags--; /* We actually performed no compression */ GKfree(&cptr, &cind, LTERM); } else if (2*graph.nvtxs < nvtxs && ctrl.nseps == 1) ctrl.nseps = 2; } else { SetUpGraph(&graph, OP_ONMETIS, nvtxs, 1, xadj, adjncy, NULL, NULL, 0); } /*============================================================= * Do the nested dissection ordering --=============================================================*/ ctrl.maxvwgt = 1.5*(idxsum(graph.nvtxs, graph.vwgt)/ctrl.CoarsenTo); AllocateWorkSpace(&ctrl, &graph, 2); idxset(2*npes-1, 0, sizes); MlevelNestedDissectionP(&ctrl, &graph, iperm, graph.nvtxs, npes, 0, sizes); FreeWorkSpace(&ctrl, &graph); if (ctrl.oflags&OFLAG_COMPRESS) { /* Uncompress the ordering */ if (graph.nvtxs < COMPRESSION_FRACTION*(nvtxs)) { /* construct perm from iperm */ for (i=0; i<graph.nvtxs; i++) perm[iperm[i]] = i; for (l=ii=0; ii<graph.nvtxs; ii++) { i = perm[ii]; for (j=cptr[i]; j<cptr[i+1]; j++) iperm[cind[j]] = l++; } } GKfree(&cptr, &cind, LTERM); } for (i=0; i<nvtxs; i++) perm[iperm[i]] = i; IFSET(ctrl.dbglvl, DBG_TIME, stoptimer(ctrl.TotalTmr)); IFSET(ctrl.dbglvl, DBG_TIME, PrintTimers(&ctrl)); }
void mlmclWithGraph(GraphType *graph,idxtype* indices,Options opt) { GraphType *cgraph,*t; int nvtxs=graph->nvtxs; CtrlType ctrl; int levels=0; Matrix *M=NULL; int ct = ctrl.CoarsenTo = opt.coarsenTo, runMcl=0; ctrl.CType=opt.matchType; /* if ( nvtxs > 50000 ) ctrl.CType = MATCH_POWERLAW_FC; */ ctrl.optype=OP_KMETIS; // ctrl.maxvwgt = (int) round( ((ct>100)?nvtxs/100: nvtxs/ct)); // ctrl.maxvwgt = (ctrl.maxvwgt > 5000 ) ? 5000 : ctrl.maxvwgt ; ctrl.dbglvl=1; if ( ct < 5 ) ctrl.maxvwgt = (int) ceil( (1.5*nvtxs)/ct ); else if ( ct <= 100 ) ctrl.maxvwgt = (int) ceil( (2.0*nvtxs)/ct ); else if ( ct > 100 ) { // we can allow some imbalance here. ctrl.maxvwgt = (int) ceil( 10.0 * nvtxs/ct ); } my_AllocateWorkSpace(&ctrl,graph); cgraph = Coarsen2Way(&ctrl,graph); FreeWorkSpace(&ctrl, graph); // printf( "Coarsen time:%.2f\n",gettimer(ctrl.CoarsenTmr) ); for(levels=0,t=cgraph;t->finer!=NULL;t=t->finer,levels++); printf("Coarsened %d levels\n", levels); printf("Number of vertices in coarsest graph:%d\n", cgraph->nvtxs); // printf("In lib/mlmcl.c: penalty_power:%.1f\n", opt.penalty_power); fflush(stdout); while ( cgraph != NULL ) { Matrix *M0, *Mnew; int iters; // dump_graph(cgraph); M0=setupCanonicalMatrix(cgraph->nvtxs, cgraph->nedges, cgraph->xadj, cgraph->adjncy, cgraph->adjwgt, opt.ncutify); if ( cgraph->coarser != NULL ) { // if this is not the original graph, then we don't // need the adjacency information in the graph // anymore. M0 is what we want, and we have it, so we // can free cgraph->gdata. GKfree( (void**)&(cgraph->gdata), LTERM); } if ( cgraph->coarser == NULL ) { // if this is the coarsest graph, flow matrix is same as // the transition matrix. M=M0; // dumpMatrix(M); } if (cgraph->finer == NULL) iters=opt.num_last_iter; else iters=opt.iter_per_level; if ( cgraph->coarser == NULL ) {; //printRow(M,35); //printRow(M,36); } Mnew=dprmcl(M,M0,cgraph, opt, iters, levels); // M would have been freed in mclForMultiLevel, so no // need to free it here. /* if ( M0 != NULL ) { freeMatrix(M0); } */ if ( cgraph->coarser == NULL ) { //printRow(Mnew,35); //printRow(Mnew,36); } if ( runMcl > 0 && cgraph->finer == NULL ) { /* run original mcl so that the matrix moves closer to * convergence */ M=dprmcl(Mnew,Mnew,cgraph, opt, iters/2,levels); /* Mnew would not have been freed in mclForMultiLevel * above. */ freeMatrix(Mnew); } else { M=Mnew; } if ( cgraph->finer != NULL ) { int nnzRefinedGraph = 2*M->nnz; if ( ctrl.CType == MATCH_POWERLAW_FC ) { int ii; nnzRefinedGraph = 0; for ( ii=0; ii<cgraph->finer->nvtxs; ii++ ) { int tx=cgraph->finer->cmap[ii]; nnzRefinedGraph += M->xadj[tx+1]-M->xadj[tx]; } } else if ( ctrl.CType == MATCH_HASH && levels <= 3 ) { int ii; nnzRefinedGraph=0; for ( ii=0; ii<cgraph->nvtxs; ii++ ) { nnzRefinedGraph += cgraph->vwgt[ii] * (M->xadj[ii+1] - M->xadj[ii]); } } // dumpMatrix(M); Mnew=propagateFlow(M,cgraph,cgraph->finer,nnzRefinedGraph); // dumpMatrix(Mnew); if ( M != NULL ) { freeMatrix(M); } M=Mnew; } cgraph=cgraph->finer; // These two didn't get freed earlier, when we freed // gdata. if ( cgraph != NULL ) { GKfree( (void**)&(cgraph->coarser->vwgt), (void**)&(cgraph->coarser->rmap1), LTERM); } levels--; printf("Done level %d\n", levels+1); fflush(stdout); } getAttractorsForAll(M); idxcopy(nvtxs, M->attractors, indices); /* int nClusters = 0; wgttype minWgt = 0; idxtype *ret = getNodesToComponentMap(M, &nClusters, minWgt); idxcopy(nvtxs, ret, indices); free(ret); */ freeMatrix(M); }