/************************************************************************* * This function is the entry point for KMETIS **************************************************************************/ void *METIS_PartGraphForContact(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, double *xyzcoords, idxtype *sflag, idxtype *numflag, idxtype *nparts, idxtype *options, idxtype *edgecut, idxtype *part) { idxtype i, j, ii, dim, ncon, wgtflag, mcnumflag, nnodes, nlnodes, nclean, naclean, ndirty, maxdepth, rwgtflag, rnumflag; idxtype *mcvwgt, *dtpart, *marker, *leafpart; idxtype *adjwgt; float rubvec[2], lbvec[2]; GraphType graph, *cgraph; ContactInfoType *cinfo; DKeyValueType *xyzcand[3]; if (*numflag == 1) Change2CNumbering(*nvtxs, xadj, adjncy); /*--------------------------------------------------------------------- * Allocate memory for the contact info type *---------------------------------------------------------------------*/ cinfo = (ContactInfoType *)gk_malloc(sizeof(ContactInfoType), "METIS_PartGraphForContact: cinfo"); cinfo->leafptr = idxsmalloc(*nvtxs+1, 0, "METIS_PartGraphForContact: leafptr"); cinfo->leafind = idxsmalloc(*nvtxs, 0, "METIS_PartGraphForContact: leafind"); cinfo->leafwgt = idxsmalloc(*nvtxs, 0, "METIS_PartGraphForContact: leafwgt"); cinfo->part = idxsmalloc(*nvtxs, 0, "METIS_PartGraphForContact: part"); leafpart = cinfo->leafpart = idxmalloc(*nvtxs, "METIS_PartGraphForContact: leafpart"); cinfo->dtree = (DTreeNodeType *)gk_malloc(sizeof(DTreeNodeType)*(*nvtxs), "METIS_PartGraphForContact: cinfo->dtree"); cinfo->nvtxs = *nvtxs; /*--------------------------------------------------------------------- * Compute the initial k-way partitioning *---------------------------------------------------------------------*/ mcvwgt = idxsmalloc(2*(*nvtxs), 0, "METIS_PartGraphForContact: mcvwgt"); for (i=0; i<*nvtxs; i++) { mcvwgt[2*i+0] = 1; mcvwgt[2*i+1] = (sflag[i] == 0 ? 0 : 1); } adjwgt = idxmalloc(xadj[*nvtxs], "METIS_PartGraphForContact: adjwgt"); for (i=0; i<*nvtxs; i++) { for (j=xadj[i]; j<xadj[i+1]; j++) adjwgt[j] = (sflag[i] && sflag[adjncy[j]] ? 5 : 1); } rubvec[0] = 1.03; rubvec[1] = 1.05; ncon = 2; mcnumflag = 0; wgtflag = 1; METIS_mCPartGraphKway(nvtxs, &ncon, xadj, adjncy, mcvwgt, adjwgt, &wgtflag, &mcnumflag, nparts, rubvec, options, edgecut, part); /* The following is just for stat reporting purposes */ SetUpGraph(&graph, OP_KMETIS, *nvtxs, 2, xadj, adjncy, mcvwgt, NULL, 0); graph.vwgt = mcvwgt; ComputePartitionBalance(&graph, *nparts, part, lbvec); mprintf(" %D-way Edge-Cut: %7D, Balance: %5.2f %5.2f\n", *nparts, ComputeCut(&graph, part), lbvec[0], lbvec[1]); /*--------------------------------------------------------------------- * Induce the decission tree *---------------------------------------------------------------------*/ dtpart = idxmalloc(*nvtxs, "METIS_PartGraphForContact: dtpart"); marker = idxsmalloc(*nvtxs, 0, "METIS_PartGraphForContact: marker"); for (dim=0; dim<3; dim++) { xyzcand[dim] = (DKeyValueType *)gk_malloc(sizeof(DKeyValueType)*(*nvtxs), "METIS_PartGraphForContact: xyzcand[dim]"); for (i=0; i<*nvtxs; i++) { xyzcand[dim][i].key = xyzcoords[3*i+dim]; xyzcand[dim][i].val = i; } idkeysort(*nvtxs, xyzcand[dim]); } nnodes = nlnodes = nclean = naclean = ndirty = maxdepth = 0; InduceDecissionTree(*nvtxs, xyzcand, sflag, *nparts, part, *nvtxs/(20*(*nparts)), *nvtxs/(20*(*nparts)*(*nparts)), 0.90, &nnodes, &nlnodes, cinfo->dtree, leafpart, dtpart, &nclean, &naclean, &ndirty, &maxdepth, marker); mprintf("NNodes: %5D, NLNodes: %5D, NClean: %5D, NAClean: %5D, NDirty: %5D, MaxDepth: %3D\n", nnodes, nlnodes, nclean, naclean, ndirty, maxdepth); /*--------------------------------------------------------------------- * Create the tree-induced coarse graph and refine it *---------------------------------------------------------------------*/ cgraph = CreatePartitionGraphForContact(*nvtxs, xadj, adjncy, mcvwgt, adjwgt, nlnodes, leafpart); for (i=0; i<*nvtxs; i++) part[leafpart[i]] = dtpart[i]; ComputePartitionBalance(cgraph, *nparts, part, lbvec); mprintf(" %D-way Edge-Cut: %7D, Balance: %5.2f %5.2f\n", *nparts, ComputeCut(cgraph, part), lbvec[0], lbvec[1]); rwgtflag = 3; rnumflag = 0; METIS_mCRefineGraphKway(&(cgraph->nvtxs), &ncon, cgraph->xadj, cgraph->adjncy, cgraph->vwgt, cgraph->adjwgt, &rwgtflag, &rnumflag, nparts, rubvec, options, edgecut, part); ComputePartitionBalance(cgraph, *nparts, part, lbvec); mprintf(" %D-way Edge-Cut: %7D, Balance: %5.2f %5.2f\n", *nparts, ComputeCut(cgraph, part), lbvec[0], lbvec[1]); /*--------------------------------------------------------------------- * Use that to compute the partition of the original graph *---------------------------------------------------------------------*/ idxcopy(cgraph->nvtxs, part, dtpart); for (i=0; i<*nvtxs; i++) part[i] = dtpart[leafpart[i]]; ComputePartitionBalance(&graph, *nparts, part, lbvec); idxset(*nvtxs, 1, graph.vwgt); mprintf(" %D-way Edge-Cut: %7D, Volume: %7D, Balance: %5.2f %5.2f\n", *nparts, ComputeCut(&graph, part), ComputeVolume(&graph, part), lbvec[0], lbvec[1]); /*--------------------------------------------------------------------- * Induce the final decission tree *---------------------------------------------------------------------*/ nnodes = nlnodes = nclean = naclean = ndirty = maxdepth = 0; InduceDecissionTree(*nvtxs, xyzcand, sflag, *nparts, part, *nvtxs/((40)*(*nparts)), 1, 1.00, &nnodes, &nlnodes, cinfo->dtree, leafpart, dtpart, &nclean, &naclean, &ndirty, &maxdepth, marker); mprintf("NNodes: %5D, NLNodes: %5D, NClean: %5D, NAClean: %5D, NDirty: %5D, MaxDepth: %3D\n", nnodes, nlnodes, nclean, naclean, ndirty, maxdepth); /*--------------------------------------------------------------------- * Populate the remaining fields of the cinfo data structure *---------------------------------------------------------------------*/ cinfo->nnodes = nnodes; cinfo->nleafs = nlnodes; idxcopy(*nvtxs, part, cinfo->part); BuildDTLeafContents(cinfo, sflag); CheckDTree(*nvtxs, xyzcoords, part, cinfo); gk_free((void **)&mcvwgt, &dtpart, &xyzcand[0], &xyzcand[1], &xyzcand[2], &marker, &adjwgt, LTERM); if (*numflag == 1) Change2FNumbering(*nvtxs, xadj, adjncy, part); return (void *)cinfo; }
/************************************************************************* * Let the game begin **************************************************************************/ main(int argc, char *argv[]) { int i, nparts, options[10]; idxtype *part; float rubvec[MAXNCON], lbvec[MAXNCON]; GraphType graph; char filename[256]; int numflag = 0, wgtflag = 0, edgecut; timer TOTALTmr, METISTmr, IOTmr; if (argc != 3) { printf("Usage: %s <GraphFile> <Nparts>\n",argv[0]); exit(0); } strcpy(filename, argv[1]); nparts = atoi(argv[2]); if (nparts < 2) { printf("The number of partitions should be greater than 1!\n"); exit(0); } cleartimer(TOTALTmr); cleartimer(METISTmr); cleartimer(IOTmr); starttimer(TOTALTmr); starttimer(IOTmr); ReadGraph(&graph, filename, &wgtflag); if (graph.nvtxs <= 0) { printf("Empty graph. Nothing to do.\n"); exit(0); } stoptimer(IOTmr); printf("**********************************************************************\n"); printf("%s", METISTITLE); printf("Graph Information ---------------------------------------------------\n"); printf(" Name: %s, #Vertices: %d, #Edges: %d, #Parts: %d\n", filename, graph.nvtxs, graph.nedges/2, nparts); if (graph.ncon > 1) printf(" Balancing Constraints: %d\n", graph.ncon); printf("\nK-way Partitioning... -----------------------------------------------\n"); part = idxmalloc(graph.nvtxs, "main: part"); options[0] = 0; starttimer(METISTmr); if (graph.ncon == 1) { METIS_PartGraphKway(&graph.nvtxs, graph.xadj, graph.adjncy, graph.vwgt, graph.adjwgt, &wgtflag, &numflag, &nparts, options, &edgecut, part); } else { for (i=0; i<graph.ncon; i++) rubvec[i] = HORIZONTAL_IMBALANCE; METIS_mCPartGraphKway(&graph.nvtxs, &graph.ncon, graph.xadj, graph.adjncy, graph.vwgt, graph.adjwgt, &wgtflag, &numflag, &nparts, rubvec, options, &edgecut, part); } stoptimer(METISTmr); ComputePartitionBalance(&graph, nparts, part, lbvec); printf(" %d-way Edge-Cut: %7d, Balance: ", nparts, edgecut); for (i=0; i<graph.ncon; i++) printf("%5.2f ", lbvec[i]); printf("\n"); starttimer(IOTmr); WritePartition(filename, part, graph.nvtxs, nparts); stoptimer(IOTmr); stoptimer(TOTALTmr); printf("\nTiming Information --------------------------------------------------\n"); printf(" I/O: \t\t %7.3f\n", gettimer(IOTmr)); printf(" Partitioning: \t\t %7.3f (KMETIS time)\n", gettimer(METISTmr)); printf(" Total: \t\t %7.3f\n", gettimer(TOTALTmr)); printf("**********************************************************************\n"); GKfree(&graph.xadj, &graph.adjncy, &graph.vwgt, &graph.adjwgt, &part, LTERM); }
/************************************************************************* * multi-level weighted kernel k-means main function **************************************************************************/ Graclus normalizedCut(char* filename, int nparts) { Graclus ncData; int options[11]; idxtype *part; // cluster result stored in array part float rubvec[MAXNCON], lbvec[MAXNCON]; GraphType graph; int numflag = 0, wgtflag = 0, edgecut, chain_length = 0; int no_args = 1, levels = 0; no_args = 0; if (nparts < 2) { printf("The number of partitions should be greater than 1!\n"); exit(0); } ReadGraph(&graph, filename, &wgtflag); if (graph.nvtxs <= 0) { puts("Empty graph. Nothing to do.\n"); exit(0); } levels = amax((graph.nvtxs)/(40*log2_metis(nparts)), 20*(nparts)); // if(graph.ncon > 1) // printf(" Balancing Constraints: %d\n", graph.ncon); part = idxmalloc(graph.nvtxs, "main: part"); options[0] = 0; // printf("#Clusters: %d\n", nparts); if (graph.ncon == 1) { MLKKM_PartGraphKway(&graph.nvtxs, graph.xadj, graph.adjncy, graph.vwgt, graph.adjwgt, &wgtflag, &numflag, &nparts, &chain_length, options, &edgecut, part, levels); } else { int i; for (i = 0; i < graph.ncon; i++) rubvec[i] = HORIZONTAL_IMBALANCE; } ComputePartitionBalance(&graph, nparts, part, lbvec); ComputeNCut(&graph, part, nparts); //for(int i = 0; i < graph.nvtxs; i++) printf("%d\n", part[i]); //int clusterNum = graph.nvtxs; ncData.part = part; ncData.clusterNum = graph.nvtxs; //GKfree((void **) &graph.xadj, (void **) &graph.adjncy, (void **) &graph.vwgt, (void **) &graph.adjwgt, (void **) &part, LTERM); GKfree((void **) &graph.xadj, (void **) &graph.adjncy, (void **) &graph.vwgt, (void **) &graph.adjwgt, LTERM); return ncData; }