/************************************************************************* * This function takes a graph and produces a bisection of it **************************************************************************/ void MlevelNestedDissection(CtrlType *ctrl, GraphType *graph, idxtype *order, float ubfactor, int lastvtx) { int i, j, nvtxs, nbnd, tvwgt, tpwgts2[2]; idxtype *label, *bndind; GraphType lgraph, rgraph; nvtxs = graph->nvtxs; /* Determine the weights of the partitions */ tvwgt = idxsum(nvtxs, graph->vwgt); tpwgts2[0] = tvwgt/2; tpwgts2[1] = tvwgt-tpwgts2[0]; switch (ctrl->optype) { case OP_OEMETIS: MlevelEdgeBisection(ctrl, graph, tpwgts2, ubfactor); IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->SepTmr)); ConstructMinCoverSeparator(ctrl, graph, ubfactor); IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->SepTmr)); break; case OP_ONMETIS: MlevelNodeBisectionMultiple(ctrl, graph, tpwgts2, ubfactor); IFSET(ctrl->dbglvl, DBG_SEPINFO, printf("Nvtxs: %6d, [%6d %6d %6d]\n", graph->nvtxs, graph->pwgts[0], graph->pwgts[1], graph->pwgts[2])); break; } /* Order the nodes in the separator */ nbnd = graph->nbnd; bndind = graph->bndind; label = graph->label; for (i=0; i<nbnd; i++) order[label[bndind[i]]] = --lastvtx; SplitGraphOrder(ctrl, graph, &lgraph, &rgraph); /* Free the memory of the top level graph */ /*GKfree(&graph->gdata, &graph->rdata, &graph->label, LTERM);*/ GKfree3((void **)&graph->gdata, (void**)&graph->rdata, (void **)&graph->label); if (rgraph.nvtxs > MMDSWITCH) MlevelNestedDissection(ctrl, &rgraph, order, ubfactor, lastvtx); else { MMDOrder(ctrl, &rgraph, order, lastvtx); /*GKfree(&rgraph.gdata, &rgraph.rdata, &rgraph.label, LTERM);*/ GKfree3((void**)&rgraph.gdata, (void**)&rgraph.rdata, (void**)&rgraph.label); } if (lgraph.nvtxs > MMDSWITCH) MlevelNestedDissection(ctrl, &lgraph, order, ubfactor, lastvtx-rgraph.nvtxs); else { MMDOrder(ctrl, &lgraph, order, lastvtx-rgraph.nvtxs); /*GKfree(&lgraph.gdata, &lgraph.rdata, &lgraph.label, LTERM);*/ GKfree3((void**)&lgraph.gdata, (void**)&lgraph.rdata, (void**)&lgraph.label); } }
/************************************************************************* * This function is the entry point for ONWMETIS. It requires weights on the * vertices. It is for the case that the matrix has been pre-compressed. **************************************************************************/ void METIS_EdgeComputeSeparator(int *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, int *options, int *sepsize, idxtype *part) { int i, j, tvwgt, tpwgts[2]; GraphType graph; CtrlType ctrl; SetUpGraph(&graph, OP_ONMETIS, *nvtxs, 1, xadj, adjncy, vwgt, adjwgt, 3); tvwgt = idxsum(*nvtxs, graph.vwgt); if (options[0] == 0) { /* Use the default parameters */ ctrl.CType = ONMETIS_CTYPE; ctrl.IType = ONMETIS_ITYPE; ctrl.RType = ONMETIS_RTYPE; ctrl.dbglvl = ONMETIS_DBGLVL; } else { ctrl.CType = options[OPTION_CTYPE]; ctrl.IType = options[OPTION_ITYPE]; ctrl.RType = options[OPTION_RTYPE]; ctrl.dbglvl = options[OPTION_DBGLVL]; } ctrl.oflags = 0; ctrl.pfactor = 0; ctrl.nseps = 5; ctrl.optype = OP_OEMETIS; ctrl.CoarsenTo = amin(100, *nvtxs-1); ctrl.maxvwgt = 1.5*tvwgt/ctrl.CoarsenTo; InitRandom(options[7]); AllocateWorkSpace(&ctrl, &graph, 2); /*============================================================ * Perform the bisection *============================================================*/ tpwgts[0] = tvwgt/2; tpwgts[1] = tvwgt-tpwgts[0]; MlevelEdgeBisection(&ctrl, &graph, tpwgts, 1.05); ConstructMinCoverSeparator(&ctrl, &graph, 1.05); *sepsize = graph.pwgts[2]; idxcopy(*nvtxs, graph.where, part); GKfree((void**)&graph.gdata, &graph.rdata, &graph.label, LTERM); FreeWorkSpace(&ctrl, &graph); }