00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <metis.h>
00017
00018
00019
00020
00021
00022 void METIS_PartGraphRecursive(int *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt,
00023 idxtype *adjwgt, int *wgtflag, int *numflag, int *nparts,
00024 int *options, int *edgecut, idxtype *part)
00025 {
00026 int i;
00027 floattype *tpwgts;
00028
00029 tpwgts = fmalloc(*nparts, "KMETIS: tpwgts");
00030 for (i=0; i<*nparts; i++)
00031 tpwgts[i] = 1.0/(1.0*(*nparts));
00032
00033 METIS_WPartGraphRecursive(nvtxs, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts,
00034 tpwgts, options, edgecut, part);
00035
00036 free(tpwgts);
00037 }
00038
00039
00040
00041
00042
00043
00044
00045 void METIS_WPartGraphRecursive(int *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt,
00046 idxtype *adjwgt, int *wgtflag, int *numflag, int *nparts,
00047 floattype *tpwgts, int *options, int *edgecut, idxtype *part)
00048 {
00049 int i, j;
00050 GraphType graph;
00051 CtrlType ctrl;
00052 floattype *mytpwgts;
00053
00054 if (*numflag == 1)
00055 Change2CNumbering(*nvtxs, xadj, adjncy);
00056
00057 SetUpGraph(&graph, OP_PMETIS, *nvtxs, 1, xadj, adjncy, vwgt, adjwgt, *wgtflag);
00058
00059 if (options[0] == 0) {
00060 ctrl.CType = PMETIS_CTYPE;
00061 ctrl.IType = PMETIS_ITYPE;
00062 ctrl.RType = PMETIS_RTYPE;
00063 ctrl.dbglvl = PMETIS_DBGLVL;
00064 }
00065 else {
00066 ctrl.CType = options[OPTION_CTYPE];
00067 ctrl.IType = options[OPTION_ITYPE];
00068 ctrl.RType = options[OPTION_RTYPE];
00069 ctrl.dbglvl = options[OPTION_DBGLVL];
00070 }
00071 ctrl.optype = OP_PMETIS;
00072 ctrl.CoarsenTo = 20;
00073 ctrl.maxvwgt = 1.5*(idxsum(*nvtxs, graph.vwgt)/ctrl.CoarsenTo);
00074
00075 mytpwgts = fmalloc(*nparts, "PWMETIS: mytpwgts");
00076 for (i=0; i<*nparts; i++)
00077 mytpwgts[i] = tpwgts[i];
00078
00079 InitRandom(-1);
00080
00081 AllocateWorkSpace(&ctrl, &graph, *nparts);
00082
00083 IFSET(ctrl.dbglvl, DBG_TIME, InitTimers(&ctrl));
00084 IFSET(ctrl.dbglvl, DBG_TIME, starttimer(ctrl.TotalTmr));
00085
00086 *edgecut = MlevelRecursiveBisection(&ctrl, &graph, *nparts, part, mytpwgts, 1.000, 0);
00087
00088 IFSET(ctrl.dbglvl, DBG_TIME, stoptimer(ctrl.TotalTmr));
00089 IFSET(ctrl.dbglvl, DBG_TIME, PrintTimers(&ctrl));
00090
00091 FreeWorkSpace(&ctrl, &graph);
00092 free(mytpwgts);
00093
00094 if (*numflag == 1)
00095 Change2FNumbering(*nvtxs, xadj, adjncy, part);
00096 }
00097
00098
00099
00100
00101
00102
00103 int MlevelRecursiveBisection(CtrlType *ctrl, GraphType *graph, int nparts, idxtype *part, floattype *tpwgts, floattype ubfactor, int fpart)
00104 {
00105 int i, j, nvtxs, cut, tvwgt, tpwgts2[2];
00106 idxtype *label, *where;
00107 GraphType lgraph, rgraph;
00108 floattype wsum;
00109
00110 nvtxs = graph->nvtxs;
00111 if (nvtxs == 0) {
00112 printf("\t***Cannot bisect a graph with 0 vertices!\n\t***You are trying to partition a graph into too many parts!\n");
00113 return 0;
00114 }
00115
00116
00117 tvwgt = idxsum(nvtxs, graph->vwgt);
00118 tpwgts2[0] = tvwgt*ssum(nparts/2, tpwgts);
00119 tpwgts2[1] = tvwgt-tpwgts2[0];
00120
00121 MlevelEdgeBisection(ctrl, graph, tpwgts2, ubfactor);
00122 cut = graph->mincut;
00123
00124
00125
00126 label = graph->label;
00127 where = graph->where;
00128 for (i=0; i<nvtxs; i++)
00129 part[label[i]] = where[i] + fpart;
00130
00131 if (nparts > 2) {
00132 SplitGraphPart(ctrl, graph, &lgraph, &rgraph);
00133
00134 }
00135
00136
00137
00138 GKfree(&graph->gdata, &graph->rdata, &graph->label, LTERM);
00139
00140
00141 wsum = ssum(nparts/2, tpwgts);
00142 sscale(nparts/2, 1.0/wsum, tpwgts);
00143 sscale(nparts-nparts/2, 1.0/(1.0-wsum), tpwgts+nparts/2);
00144
00145
00146
00147
00148
00149
00150
00151 if (nparts > 3) {
00152 cut += MlevelRecursiveBisection(ctrl, &lgraph, nparts/2, part, tpwgts, ubfactor, fpart);
00153 cut += MlevelRecursiveBisection(ctrl, &rgraph, nparts-nparts/2, part, tpwgts+nparts/2, ubfactor, fpart+nparts/2);
00154 }
00155 else if (nparts == 3) {
00156 cut += MlevelRecursiveBisection(ctrl, &rgraph, nparts-nparts/2, part, tpwgts+nparts/2, ubfactor, fpart+nparts/2);
00157 GKfree(&lgraph.gdata, &lgraph.label, LTERM);
00158 }
00159
00160 return cut;
00161
00162 }
00163
00164
00165
00166
00167
00168 void MlevelEdgeBisection(CtrlType *ctrl, GraphType *graph, int *tpwgts, floattype ubfactor)
00169 {
00170 GraphType *cgraph;
00171
00172 cgraph = Coarsen2Way(ctrl, graph);
00173
00174 Init2WayPartition(ctrl, cgraph, tpwgts, ubfactor);
00175
00176 Refine2Way(ctrl, graph, cgraph, tpwgts, ubfactor);
00177
00178
00179
00180
00181
00182 }
00183
00184
00185
00186
00187
00188
00189
00190 void SplitGraphPart(CtrlType *ctrl, GraphType *graph, GraphType *lgraph, GraphType *rgraph)
00191 {
00192 int i, j, k, kk, l, istart, iend, mypart, nvtxs, ncon, snvtxs[2], snedges[2], sum;
00193 idxtype *xadj, *vwgt, *adjncy, *adjwgt, *adjwgtsum, *label, *where, *bndptr;
00194 idxtype *sxadj[2], *svwgt[2], *sadjncy[2], *sadjwgt[2], *sadjwgtsum[2], *slabel[2];
00195 idxtype *rename;
00196 idxtype *auxadjncy, *auxadjwgt;
00197 floattype *nvwgt, *snvwgt[2], *npwgts;
00198
00199
00200 IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->SplitTmr));
00201
00202 nvtxs = graph->nvtxs;
00203 ncon = graph->ncon;
00204 xadj = graph->xadj;
00205 vwgt = graph->vwgt;
00206 nvwgt = graph->nvwgt;
00207 adjncy = graph->adjncy;
00208 adjwgt = graph->adjwgt;
00209 adjwgtsum = graph->adjwgtsum;
00210 label = graph->label;
00211 where = graph->where;
00212 bndptr = graph->bndptr;
00213 npwgts = graph->npwgts;
00214
00215 ASSERT(bndptr != NULL);
00216
00217 rename = idxwspacemalloc(ctrl, nvtxs);
00218
00219 snvtxs[0] = snvtxs[1] = snedges[0] = snedges[1] = 0;
00220 for (i=0; i<nvtxs; i++) {
00221 k = where[i];
00222 rename[i] = snvtxs[k]++;
00223 snedges[k] += xadj[i+1]-xadj[i];
00224 }
00225
00226 SetUpSplitGraph(graph, lgraph, snvtxs[0], snedges[0]);
00227 sxadj[0] = lgraph->xadj;
00228 svwgt[0] = lgraph->vwgt;
00229 snvwgt[0] = lgraph->nvwgt;
00230 sadjwgtsum[0] = lgraph->adjwgtsum;
00231 sadjncy[0] = lgraph->adjncy;
00232 sadjwgt[0] = lgraph->adjwgt;
00233 slabel[0] = lgraph->label;
00234
00235 SetUpSplitGraph(graph, rgraph, snvtxs[1], snedges[1]);
00236 sxadj[1] = rgraph->xadj;
00237 svwgt[1] = rgraph->vwgt;
00238 snvwgt[1] = rgraph->nvwgt;
00239 sadjwgtsum[1] = rgraph->adjwgtsum;
00240 sadjncy[1] = rgraph->adjncy;
00241 sadjwgt[1] = rgraph->adjwgt;
00242 slabel[1] = rgraph->label;
00243
00244 snvtxs[0] = snvtxs[1] = snedges[0] = snedges[1] = 0;
00245 sxadj[0][0] = sxadj[1][0] = 0;
00246 for (i=0; i<nvtxs; i++) {
00247 mypart = where[i];
00248 sum = adjwgtsum[i];
00249
00250 istart = xadj[i];
00251 iend = xadj[i+1];
00252 if (bndptr[i] == -1) {
00253 auxadjncy = sadjncy[mypart] + snedges[mypart] - istart;
00254 auxadjwgt = sadjwgt[mypart] + snedges[mypart] - istart;
00255 for(j=istart; j<iend; j++) {
00256 auxadjncy[j] = adjncy[j];
00257 auxadjwgt[j] = adjwgt[j];
00258 }
00259 snedges[mypart] += iend-istart;
00260 }
00261 else {
00262 auxadjncy = sadjncy[mypart];
00263 auxadjwgt = sadjwgt[mypart];
00264 l = snedges[mypart];
00265 for (j=istart; j<iend; j++) {
00266 k = adjncy[j];
00267 if (where[k] == mypart) {
00268 auxadjncy[l] = k;
00269 auxadjwgt[l++] = adjwgt[j];
00270 }
00271 else {
00272 sum -= adjwgt[j];
00273 }
00274 }
00275 snedges[mypart] = l;
00276 }
00277
00278 if (ncon == 1)
00279 svwgt[mypart][snvtxs[mypart]] = vwgt[i];
00280 else {
00281 for (kk=0; kk<ncon; kk++)
00282 snvwgt[mypart][snvtxs[mypart]*ncon+kk] = nvwgt[i*ncon+kk]/npwgts[mypart*ncon+kk];
00283 }
00284
00285 sadjwgtsum[mypart][snvtxs[mypart]] = sum;
00286 slabel[mypart][snvtxs[mypart]] = label[i];
00287 sxadj[mypart][++snvtxs[mypart]] = snedges[mypart];
00288 }
00289
00290 for (mypart=0; mypart<2; mypart++) {
00291 iend = sxadj[mypart][snvtxs[mypart]];
00292 auxadjncy = sadjncy[mypart];
00293 for (i=0; i<iend; i++)
00294 auxadjncy[i] = rename[auxadjncy[i]];
00295 }
00296
00297 lgraph->nedges = snedges[0];
00298 rgraph->nedges = snedges[1];
00299
00300 IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->SplitTmr));
00301
00302 idxwspacefree(ctrl, nvtxs);
00303 }
00304
00305
00306
00307
00308
00309 void SetUpSplitGraph(GraphType *graph, GraphType *sgraph, int snvtxs, int snedges)
00310 {
00311 InitGraph(sgraph);
00312 sgraph->nvtxs = snvtxs;
00313 sgraph->nedges = snedges;
00314 sgraph->ncon = graph->ncon;
00315
00316
00317 if (graph->ncon == 1) {
00318 sgraph->gdata = idxmalloc(4*snvtxs+1 + 2*snedges, "SetUpSplitGraph: gdata");
00319
00320 sgraph->xadj = sgraph->gdata;
00321 sgraph->vwgt = sgraph->gdata + snvtxs+1;
00322 sgraph->adjwgtsum = sgraph->gdata + 2*snvtxs+1;
00323 sgraph->cmap = sgraph->gdata + 3*snvtxs+1;
00324 sgraph->adjncy = sgraph->gdata + 4*snvtxs+1;
00325 sgraph->adjwgt = sgraph->gdata + 4*snvtxs+1 + snedges;
00326 }
00327 else {
00328 sgraph->gdata = idxmalloc(3*snvtxs+1 + 2*snedges, "SetUpSplitGraph: gdata");
00329
00330 sgraph->xadj = sgraph->gdata;
00331 sgraph->adjwgtsum = sgraph->gdata + snvtxs+1;
00332 sgraph->cmap = sgraph->gdata + 2*snvtxs+1;
00333 sgraph->adjncy = sgraph->gdata + 3*snvtxs+1;
00334 sgraph->adjwgt = sgraph->gdata + 3*snvtxs+1 + snedges;
00335
00336 sgraph->nvwgt = fmalloc(graph->ncon*snvtxs, "SetUpSplitGraph: nvwgt");
00337 }
00338
00339 sgraph->label = idxmalloc(snvtxs, "SetUpSplitGraph: sgraph->label");
00340 }
00341