pmetis.c
Go to the documentation of this file.
1 
13 #include "metislib.h"
14 
15 
16 /*************************************************************************/
90 /*************************************************************************/
95 {
96  int sigrval=0, renumber=0;
97  graph_t *graph;
98  ctrl_t *ctrl;
99 
100  /* set up malloc cleaning code and signal catchers */
101  if (!gk_malloc_init())
102  return METIS_ERROR_MEMORY;
103 
104  gk_sigtrap();
105 
106  if ((sigrval = gk_sigcatch()) != 0)
107  goto SIGTHROW;
108 
109 
110  /* set up the run parameters */
111  ctrl = SetupCtrl(METIS_OP_PMETIS, options, *ncon, *nparts, tpwgts, ubvec);
112  if (!ctrl) {
113  gk_siguntrap();
114  return METIS_ERROR_INPUT;
115  }
116 
117  /* if required, change the numbering to 0 */
118  if (ctrl->numflag == 1) {
119  Change2CNumbering(*nvtxs, xadj, adjncy);
120  renumber = 1;
121  }
122 
123  /* set up the graph */
124  graph = SetupGraph(ctrl, *nvtxs, *ncon, xadj, adjncy, vwgt, vsize, adjwgt);
125 
126  /* allocate workspace memory */
127  AllocateWorkSpace(ctrl, graph);
128 
129  /* start the partitioning */
130  IFSET(ctrl->dbglvl, METIS_DBG_TIME, InitTimers(ctrl));
132 
133  *objval = MlevelRecursiveBisection(ctrl, graph, *nparts, part, ctrl->tpwgts, 0);
134 
136  IFSET(ctrl->dbglvl, METIS_DBG_TIME, PrintTimers(ctrl));
137 
138  /* clean up */
139  FreeCtrl(&ctrl);
140 
141 SIGTHROW:
142  /* if required, change the numbering back to 1 */
143  if (renumber)
144  Change2FNumbering(*nvtxs, xadj, adjncy, part);
145 
146  gk_siguntrap();
148 
149  return metis_rcode(sigrval);
150 }
151 
152 
153 /*************************************************************************/
156 /*************************************************************************/
158  idx_t *part, real_t *tpwgts, idx_t fpart)
159 {
160  idx_t i, j, nvtxs, ncon, objval;
161  idx_t *label, *where;
162  graph_t *lgraph, *rgraph;
163  real_t wsum, *tpwgts2;
164 
165  if ((nvtxs = graph->nvtxs) == 0) {
166  printf("\t***Cannot bisect a graph with 0 vertices!\n"
167  "\t***You are trying to partition a graph into too many parts!\n");
168  return 0;
169  }
170 
171  ncon = graph->ncon;
172 
173  /* determine the weights of the two partitions as a function of the weight of the
174  target partition weights */
175  WCOREPUSH;
176  tpwgts2 = rwspacemalloc(ctrl, 2*ncon);
177  for (i=0; i<ncon; i++) {
178  tpwgts2[i] = rsum((nparts>>1), tpwgts+i, ncon);
179  tpwgts2[ncon+i] = 1.0 - tpwgts2[i];
180  }
181 
182  /* perform the bisection */
183  objval = MultilevelBisect(ctrl, graph, tpwgts2);
184 
185  WCOREPOP;
186 
187  label = graph->label;
188  where = graph->where;
189  for (i=0; i<nvtxs; i++)
190  part[label[i]] = where[i] + fpart;
191 
192  if (nparts > 2)
193  SplitGraphPart(ctrl, graph, &lgraph, &rgraph);
194 
195  /* Free the memory of the top level graph */
196  FreeGraph(&graph);
197 
198  /* Scale the fractions in the tpwgts according to the true weight */
199  for (i=0; i<ncon; i++) {
200  wsum = rsum((nparts>>1), tpwgts+i, ncon);
201  rscale((nparts>>1), 1.0/wsum, tpwgts+i, ncon);
202  rscale(nparts-(nparts>>1), 1.0/(1.0-wsum), tpwgts+(nparts>>1)*ncon+i, ncon);
203  }
204 
205  /* Do the recursive call */
206  if (nparts > 3) {
207  objval += MlevelRecursiveBisection(ctrl, lgraph, (nparts>>1), part,
208  tpwgts, fpart);
209  objval += MlevelRecursiveBisection(ctrl, rgraph, nparts-(nparts>>1), part,
210  tpwgts+(nparts>>1)*ncon, fpart+(nparts>>1));
211  }
212  else if (nparts == 3) {
213  FreeGraph(&lgraph);
214  objval += MlevelRecursiveBisection(ctrl, rgraph, nparts-(nparts>>1), part,
215  tpwgts+(nparts>>1)*ncon, fpart+(nparts>>1));
216  }
217 
218 
219  return objval;
220 }
221 
222 
223 /*************************************************************************/
225 /*************************************************************************/
227 {
228  idx_t i, niparts, bestobj=0, curobj=0, *bestwhere=NULL;
229  graph_t *cgraph;
230  real_t bestbal=0.0, curbal=0.0;
231 
232  Setup2WayBalMultipliers(ctrl, graph, tpwgts);
233 
234  WCOREPUSH;
235 
236  if (ctrl->ncuts > 1)
237  bestwhere = iwspacemalloc(ctrl, graph->nvtxs);
238 
239  for (i=0; i<ctrl->ncuts; i++) {
240  cgraph = CoarsenGraph(ctrl, graph);
241 
242  niparts = (cgraph->nvtxs <= ctrl->CoarsenTo ? SMALLNIPARTS : LARGENIPARTS);
243  Init2WayPartition(ctrl, cgraph, tpwgts, niparts);
244 
245  Refine2Way(ctrl, graph, cgraph, tpwgts);
246 
247  curobj = graph->mincut;
248  curbal = ComputeLoadImbalanceDiff(graph, 2, ctrl->pijbm, ctrl->ubfactors);
249 
250  if (i == 0
251  || (curbal <= 0.0005 && bestobj > curobj)
252  || (bestbal > 0.0005 && curbal < bestbal)) {
253  bestobj = curobj;
254  bestbal = curbal;
255  if (i < ctrl->ncuts-1)
256  icopy(graph->nvtxs, graph->where, bestwhere);
257  }
258 
259  if (bestobj == 0){
260  break;
261  }
262 
263  if (i < ctrl->ncuts-1)
264  FreeRData(graph);
265  }
266 
267  if (bestobj != curobj) {
268  icopy(graph->nvtxs, bestwhere, graph->where);
269  Compute2WayPartitionParams(ctrl, graph);
270  }
271 
272  WCOREPOP;
273  return bestobj;
274 }
275 
276 
277 /*************************************************************************/
279 /*************************************************************************/
280 void SplitGraphPart(ctrl_t *ctrl, graph_t *graph, graph_t **r_lgraph,
281  graph_t **r_rgraph)
282 {
283  idx_t i, j, k, l, istart, iend, mypart, nvtxs, ncon, snvtxs[2], snedges[2];
284  idx_t *xadj, *vwgt, *adjncy, *adjwgt, *label, *where, *bndptr;
285  idx_t *sxadj[2], *svwgt[2], *sadjncy[2], *sadjwgt[2], *slabel[2];
286  idx_t *rename;
287  idx_t *auxadjncy, *auxadjwgt;
288  graph_t *lgraph, *rgraph;
289 
290  WCOREPUSH;
291 
293 
294  nvtxs = graph->nvtxs;
295  ncon = graph->ncon;
296  xadj = graph->xadj;
297  vwgt = graph->vwgt;
298  adjncy = graph->adjncy;
299  adjwgt = graph->adjwgt;
300  label = graph->label;
301  where = graph->where;
302  bndptr = graph->bndptr;
303 
304  ASSERT(bndptr != NULL);
305 
306  rename = iwspacemalloc(ctrl, nvtxs);
307 
308  snvtxs[0] = snvtxs[1] = snedges[0] = snedges[1] = 0;
309  for (i=0; i<nvtxs; i++) {
310  k = where[i];
311  rename[i] = snvtxs[k]++;
312  snedges[k] += xadj[i+1]-xadj[i];
313  }
314 
315  lgraph = SetupSplitGraph(graph, snvtxs[0], snedges[0]);
316  sxadj[0] = lgraph->xadj;
317  svwgt[0] = lgraph->vwgt;
318  sadjncy[0] = lgraph->adjncy;
319  sadjwgt[0] = lgraph->adjwgt;
320  slabel[0] = lgraph->label;
321 
322  rgraph = SetupSplitGraph(graph, snvtxs[1], snedges[1]);
323  sxadj[1] = rgraph->xadj;
324  svwgt[1] = rgraph->vwgt;
325  sadjncy[1] = rgraph->adjncy;
326  sadjwgt[1] = rgraph->adjwgt;
327  slabel[1] = rgraph->label;
328 
329  snvtxs[0] = snvtxs[1] = snedges[0] = snedges[1] = 0;
330  sxadj[0][0] = sxadj[1][0] = 0;
331  for (i=0; i<nvtxs; i++) {
332  mypart = where[i];
333 
334  istart = xadj[i];
335  iend = xadj[i+1];
336  if (bndptr[i] == -1) { /* This is an interior vertex */
337  auxadjncy = sadjncy[mypart] + snedges[mypart] - istart;
338  auxadjwgt = sadjwgt[mypart] + snedges[mypart] - istart;
339  for(j=istart; j<iend; j++) {
340  auxadjncy[j] = adjncy[j];
341  auxadjwgt[j] = adjwgt[j];
342  }
343  snedges[mypart] += iend-istart;
344  }
345  else {
346  auxadjncy = sadjncy[mypart];
347  auxadjwgt = sadjwgt[mypart];
348  l = snedges[mypart];
349  for (j=istart; j<iend; j++) {
350  k = adjncy[j];
351  if (where[k] == mypart) {
352  auxadjncy[l] = k;
353  auxadjwgt[l++] = adjwgt[j];
354  }
355  }
356  snedges[mypart] = l;
357  }
358 
359  /* copy vertex weights */
360  for (k=0; k<ncon; k++)
361  svwgt[mypart][snvtxs[mypart]*ncon+k] = vwgt[i*ncon+k];
362 
363  slabel[mypart][snvtxs[mypart]] = label[i];
364  sxadj[mypart][++snvtxs[mypart]] = snedges[mypart];
365  }
366 
367  for (mypart=0; mypart<2; mypart++) {
368  iend = sxadj[mypart][snvtxs[mypart]];
369  auxadjncy = sadjncy[mypart];
370  for (i=0; i<iend; i++)
371  auxadjncy[i] = rename[auxadjncy[i]];
372  }
373 
374  lgraph->nedges = snedges[0];
375  rgraph->nedges = snedges[1];
376 
377  SetupGraph_tvwgt(lgraph);
378  SetupGraph_tvwgt(rgraph);
379 
381 
382  *r_lgraph = lgraph;
383  *r_rgraph = rgraph;
384 
385  WCOREPOP;
386 }
387 
idx_t idx_t idx_t idx_t * vwgt
int gk_siguntrap()
Definition: error.c:116
#define SetupSplitGraph
Definition: rename.h:94
#define SMALLNIPARTS
Definition: libmetis/defs.h:46
double TotalTmr
real_t * tpwgts
#define iwspacemalloc
Definition: rename.h:256
idx_t idx_t idx_t idx_t idx_t idx_t idx_t real_t real_t idx_t idx_t idx_t * part
#define gk_startcputimer(tmr)
Definition: gk_macros.h:33
#define SetupGraph
Definition: rename.h:90
#define ComputeLoadImbalanceDiff
Definition: rename.h:144
idx_t * xadj
#define gk_stopcputimer(tmr)
Definition: gk_macros.h:34
idx_t * adjwgt
#define FreeGraph
Definition: rename.h:98
#define metis_rcode
Definition: rename.h:247
idx_t * bndptr
idx_t idx_t * xadj
#define rwspacemalloc
Definition: rename.h:257
idx_t * where
double SplitTmr
idx_t idx_t idx_t idx_t idx_t idx_t idx_t * nparts
#define WCOREPUSH
idx_t nvtxs
#define Compute2WayPartitionParams
Definition: rename.h:214
mdbglvl_et dbglvl
idx_t ncuts
#define CoarsenGraph
Definition: rename.h:35
NonlinearFactorGraph graph
idx_t MlevelRecursiveBisection(ctrl_t *ctrl, graph_t *graph, idx_t nparts, idx_t *part, real_t *tpwgts, idx_t fpart)
Definition: pmetis.c:157
idx_t idx_t idx_t idx_t idx_t * vsize
#define Refine2Way
Definition: rename.h:212
idx_t nedges
#define ASSERT(expression)
Definition: ccolamd.c:872
#define rscale
Definition: gklib_rename.h:112
#define AllocateWorkSpace
Definition: rename.h:250
static const Line3 l(Rot3(), 1, 1)
#define rsum
Definition: gklib_rename.h:117
idx_t idx_t idx_t idx_t idx_t idx_t real_t idx_t idx_t * objval
idx_t MultilevelBisect(ctrl_t *ctrl, graph_t *graph, real_t *tpwgts)
Definition: pmetis.c:226
int32_t idx_t
#define InitTimers
Definition: rename.h:238
#define Change2CNumbering
Definition: rename.h:81
void SplitGraphPart(ctrl_t *ctrl, graph_t *graph, graph_t **r_lgraph, graph_t **r_rgraph)
Definition: pmetis.c:280
real_t * pijbm
idx_t ncon
idx_t idx_t idx_t idx_t idx_t idx_t idx_t real_t real_t * ubvec
void gk_malloc_cleanup(int showstats)
Definition: memory.c:118
float real_t
idx_t * ncon
#define NULL
Definition: ccolamd.c:609
idx_t idx_t idx_t idx_t idx_t idx_t idx_t real_t * tpwgts
#define SetupCtrl
Definition: rename.h:194
idx_t mincut
idx_t idx_t idx_t idx_t idx_t idx_t * adjwgt
#define FreeCtrl
Definition: rename.h:198
real_t * ubfactors
#define icopy
Definition: gklib_rename.h:28
idx_t idx_t idx_t idx_t * where
idx_t * adjncy
#define gk_sigcatch()
Definition: gk_macros.h:52
#define Setup2WayBalMultipliers
Definition: rename.h:196
idx_t idx_t idx_t * adjncy
#define PrintTimers
Definition: rename.h:239
#define FreeRData
Definition: rename.h:97
int METIS_PartGraphRecursive(idx_t *nvtxs, idx_t *ncon, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t *vsize, idx_t *adjwgt, idx_t *nparts, real_t *tpwgts, real_t *ubvec, idx_t *options, idx_t *objval, idx_t *part)
Recursive partitioning routine.
Definition: pmetis.c:91
idx_t CoarsenTo
#define SetupGraph_tvwgt
Definition: rename.h:92
#define WCOREPOP
#define LARGENIPARTS
Definition: libmetis/defs.h:45
#define IFSET(a, flag, cmd)
Definition: gk_macros.h:45
int gk_malloc_init()
Definition: memory.c:99
std::ptrdiff_t j
int gk_sigtrap()
Definition: error.c:98
#define Change2FNumbering
Definition: rename.h:82
idx_t numflag
idx_t * label
#define Init2WayPartition
Definition: rename.h:101
idx_t * vwgt


gtsam
Author(s):
autogenerated on Tue Jul 4 2023 02:35:14