00001
00012 #include "metislib.h"
00013
00014
00015
00017
00018 int METIS_PartGraphKway(idx_t *nvtxs, idx_t *ncon, idx_t *xadj, idx_t *adjncy,
00019 idx_t *vwgt, idx_t *vsize, idx_t *adjwgt, idx_t *nparts,
00020 real_t *tpwgts, real_t *ubvec, idx_t *options, idx_t *objval,
00021 idx_t *part)
00022 {
00023 int sigrval=0, renumber=0;
00024 graph_t *graph;
00025 ctrl_t *ctrl;
00026
00027
00028 if (!gk_malloc_init())
00029 return METIS_ERROR_MEMORY;
00030
00031 gk_sigtrap();
00032
00033 if ((sigrval = gk_sigcatch()) != 0)
00034 goto SIGTHROW;
00035
00036
00037
00038 ctrl = SetupCtrl(METIS_OP_KMETIS, options, *ncon, *nparts, tpwgts, ubvec);
00039 if (!ctrl) {
00040 gk_siguntrap();
00041 return METIS_ERROR_INPUT;
00042 }
00043
00044
00045 if (ctrl->numflag == 1) {
00046 Change2CNumbering(*nvtxs, xadj, adjncy);
00047 renumber = 1;
00048 }
00049
00050
00051 graph = SetupGraph(ctrl, *nvtxs, *ncon, xadj, adjncy, vwgt, vsize, adjwgt);
00052
00053
00054 SetupKWayBalMultipliers(ctrl, graph);
00055
00056
00057 ctrl->CoarsenTo = gk_max((*nvtxs)/(20*gk_log2(*nparts)), 30*(*nparts));
00058 ctrl->nIparts = (ctrl->CoarsenTo == 30*(*nparts) ? 4 : 5);
00059
00060
00061 if (ctrl->contig && !IsConnected(graph, 0))
00062 gk_errexit(SIGERR, "METIS Error: A contiguous partition is requested for a non-contiguous input graph.\n");
00063
00064
00065 AllocateWorkSpace(ctrl, graph);
00066
00067
00068 IFSET(ctrl->dbglvl, METIS_DBG_TIME, InitTimers(ctrl));
00069 IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->TotalTmr));
00070
00071 *objval = MlevelKWayPartitioning(ctrl, graph, part);
00072
00073 IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->TotalTmr));
00074 IFSET(ctrl->dbglvl, METIS_DBG_TIME, PrintTimers(ctrl));
00075
00076
00077 FreeCtrl(&ctrl);
00078
00079 SIGTHROW:
00080
00081 if (renumber)
00082 Change2FNumbering(*nvtxs, xadj, adjncy, part);
00083
00084 gk_siguntrap();
00085 gk_malloc_cleanup(0);
00086
00087 return metis_rcode(sigrval);
00088 }
00089
00090
00091
00102
00103 idx_t MlevelKWayPartitioning(ctrl_t *ctrl, graph_t *graph, idx_t *part)
00104 {
00105 idx_t i, j, objval=0, curobj=0, bestobj=0;
00106 real_t curbal=0.0, bestbal=0.0;
00107 graph_t *cgraph;
00108 int status;
00109
00110
00111 for (i=0; i<ctrl->ncuts; i++) {
00112 cgraph = CoarsenGraph(ctrl, graph);
00113
00114 IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->InitPartTmr));
00115 AllocateKWayPartitionMemory(ctrl, cgraph);
00116
00117
00118 FreeWorkSpace(ctrl);
00119
00120
00121 InitKWayPartitioning(ctrl, cgraph);
00122
00123
00124 AllocateWorkSpace(ctrl, graph);
00125 AllocateRefinementWorkSpace(ctrl, 2*cgraph->nedges);
00126
00127 IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->InitPartTmr));
00128 IFSET(ctrl->dbglvl, METIS_DBG_IPART,
00129 printf("Initial %"PRIDX"-way partitioning cut: %"PRIDX"\n", ctrl->nparts, objval));
00130
00131 RefineKWay(ctrl, graph, cgraph);
00132
00133 switch (ctrl->objtype) {
00134 case METIS_OBJTYPE_CUT:
00135 curobj = graph->mincut;
00136 break;
00137
00138 case METIS_OBJTYPE_VOL:
00139 curobj = graph->minvol;
00140 break;
00141
00142 default:
00143 gk_errexit(SIGERR, "Unknown objtype: %d\n", ctrl->objtype);
00144 }
00145
00146 curbal = ComputeLoadImbalanceDiff(graph, ctrl->nparts, ctrl->pijbm, ctrl->ubfactors);
00147
00148 if (i == 0
00149 || (curbal <= 0.0005 && bestobj > curobj)
00150 || (bestbal > 0.0005 && curbal < bestbal)) {
00151 icopy(graph->nvtxs, graph->where, part);
00152 bestobj = curobj;
00153 bestbal = curbal;
00154 }
00155
00156 FreeRData(graph);
00157
00158 if (bestobj == 0)
00159 break;
00160 }
00161
00162 FreeGraph(&graph);
00163
00164 return bestobj;
00165 }
00166
00167
00168
00171
00172 void InitKWayPartitioning(ctrl_t *ctrl, graph_t *graph)
00173 {
00174 idx_t i, ntrials, options[METIS_NOPTIONS], curobj=0, bestobj=0;
00175 idx_t *bestwhere=NULL;
00176 real_t *ubvec=NULL;
00177 int status;
00178
00179 METIS_SetDefaultOptions(options);
00180 options[METIS_OPTION_NITER] = 10;
00181 options[METIS_OPTION_OBJTYPE] = METIS_OBJTYPE_CUT;
00182 options[METIS_OPTION_NO2HOP] = ctrl->no2hop;
00183
00184
00185 ubvec = rmalloc(graph->ncon, "InitKWayPartitioning: ubvec");
00186 for (i=0; i<graph->ncon; i++)
00187 ubvec[i] = (real_t)pow(ctrl->ubfactors[i], 1.0/log(ctrl->nparts));
00188
00189
00190 switch (ctrl->objtype) {
00191 case METIS_OBJTYPE_CUT:
00192 case METIS_OBJTYPE_VOL:
00193 options[METIS_OPTION_NCUTS] = ctrl->nIparts;
00194 status = METIS_PartGraphRecursive(&graph->nvtxs, &graph->ncon,
00195 graph->xadj, graph->adjncy, graph->vwgt, graph->vsize,
00196 graph->adjwgt, &ctrl->nparts, ctrl->tpwgts, ubvec,
00197 options, &curobj, graph->where);
00198
00199 if (status != METIS_OK)
00200 gk_errexit(SIGERR, "Failed during initial partitioning\n");
00201
00202 break;
00203
00204 #ifdef XXX
00205 case METIS_OBJTYPE_VOL:
00206 bestwhere = imalloc(graph->nvtxs, "InitKWayPartitioning: bestwhere");
00207 options[METIS_OPTION_NCUTS] = 2;
00208
00209 ntrials = (ctrl->nIparts+1)/2;
00210 for (i=0; i<ntrials; i++) {
00211 status = METIS_PartGraphRecursive(&graph->nvtxs, &graph->ncon,
00212 graph->xadj, graph->adjncy, graph->vwgt, graph->vsize,
00213 graph->adjwgt, &ctrl->nparts, ctrl->tpwgts, ubvec,
00214 options, &curobj, graph->where);
00215 if (status != METIS_OK)
00216 gk_errexit(SIGERR, "Failed during initial partitioning\n");
00217
00218 curobj = ComputeVolume(graph, graph->where);
00219
00220 if (i == 0 || bestobj > curobj) {
00221 bestobj = curobj;
00222 if (i < ntrials-1)
00223 icopy(graph->nvtxs, graph->where, bestwhere);
00224 }
00225
00226 if (bestobj == 0)
00227 break;
00228 }
00229 if (bestobj != curobj)
00230 icopy(graph->nvtxs, bestwhere, graph->where);
00231
00232 break;
00233 #endif
00234
00235 default:
00236 gk_errexit(SIGERR, "Unknown objtype: %d\n", ctrl->objtype);
00237 }
00238
00239 gk_free((void **)&ubvec, &bestwhere, LTERM);
00240
00241 }
00242
00243