Bug #1267: Integrate METIS graph partitioning library
[charm.git] / src / libs / ck-libs / metis / libmetis / options.c
blob3bc1ac93c042131028db0fd0e456c04a49f7915b
1 /**
2 \file
3 \brief This file contains various routines for dealing with options and ctrl_t.
5 \date Started 5/12/2011
6 \author George
7 \author Copyright 1997-2011, Regents of the University of Minnesota
8 \version\verbatim $Id: options.c 13901 2013-03-24 16:17:03Z karypis $ \endverbatim
9 */
11 #include "metislib.h"
14 /*************************************************************************/
15 /*! This function creates and sets the run parameters (ctrl_t) */
16 /*************************************************************************/
17 ctrl_t *SetupCtrl(moptype_et optype, idx_t *options, idx_t ncon, idx_t nparts,
18 real_t *tpwgts, real_t *ubvec)
20 idx_t i, j;
21 ctrl_t *ctrl;
23 ctrl = (ctrl_t *)gk_malloc(sizeof(ctrl_t), "SetupCtrl: ctrl");
25 memset((void *)ctrl, 0, sizeof(ctrl_t));
27 switch (optype) {
28 case METIS_OP_PMETIS:
29 ctrl->objtype = GETOPTION(options, METIS_OPTION_OBJTYPE, METIS_OBJTYPE_CUT);
30 ctrl->rtype = METIS_RTYPE_FM;
31 ctrl->ncuts = GETOPTION(options, METIS_OPTION_NCUTS, 1);
32 ctrl->niter = GETOPTION(options, METIS_OPTION_NITER, 10);
34 if (ncon == 1) {
35 ctrl->iptype = GETOPTION(options, METIS_OPTION_IPTYPE, METIS_IPTYPE_GROW);
36 ctrl->ufactor = GETOPTION(options, METIS_OPTION_UFACTOR, PMETIS_DEFAULT_UFACTOR);
37 ctrl->CoarsenTo = 20;
39 else {
40 ctrl->iptype = GETOPTION(options, METIS_OPTION_IPTYPE, METIS_IPTYPE_RANDOM);
41 ctrl->ufactor = GETOPTION(options, METIS_OPTION_UFACTOR, MCPMETIS_DEFAULT_UFACTOR);
42 ctrl->CoarsenTo = 100;
45 break;
48 case METIS_OP_KMETIS:
49 ctrl->objtype = GETOPTION(options, METIS_OPTION_OBJTYPE, METIS_OBJTYPE_CUT);
50 ctrl->iptype = METIS_IPTYPE_METISRB;
51 ctrl->rtype = METIS_RTYPE_GREEDY;
52 ctrl->ncuts = GETOPTION(options, METIS_OPTION_NCUTS, 1);
53 ctrl->niter = GETOPTION(options, METIS_OPTION_NITER, 10);
54 ctrl->ufactor = GETOPTION(options, METIS_OPTION_UFACTOR, KMETIS_DEFAULT_UFACTOR);
55 ctrl->minconn = GETOPTION(options, METIS_OPTION_MINCONN, 0);
56 ctrl->contig = GETOPTION(options, METIS_OPTION_CONTIG, 0);
57 break;
60 case METIS_OP_OMETIS:
61 ctrl->objtype = GETOPTION(options, METIS_OPTION_OBJTYPE, METIS_OBJTYPE_NODE);
62 ctrl->rtype = GETOPTION(options, METIS_OPTION_RTYPE, METIS_RTYPE_SEP1SIDED);
63 ctrl->iptype = GETOPTION(options, METIS_OPTION_IPTYPE, METIS_IPTYPE_EDGE);
64 ctrl->nseps = GETOPTION(options, METIS_OPTION_NSEPS, 1);
65 ctrl->niter = GETOPTION(options, METIS_OPTION_NITER, 10);
66 ctrl->ufactor = GETOPTION(options, METIS_OPTION_UFACTOR, OMETIS_DEFAULT_UFACTOR);
67 ctrl->compress = GETOPTION(options, METIS_OPTION_COMPRESS, 1);
68 ctrl->ccorder = GETOPTION(options, METIS_OPTION_CCORDER, 0);
69 ctrl->pfactor = 0.1*GETOPTION(options, METIS_OPTION_PFACTOR, 0);
71 ctrl->CoarsenTo = 100;
72 break;
74 default:
75 gk_errexit(SIGERR, "Unknown optype of %d\n", optype);
78 /* common options */
79 ctrl->ctype = GETOPTION(options, METIS_OPTION_CTYPE, METIS_CTYPE_SHEM);
80 ctrl->no2hop = GETOPTION(options, METIS_OPTION_NO2HOP, 0);
81 ctrl->seed = GETOPTION(options, METIS_OPTION_SEED, -1);
82 ctrl->dbglvl = GETOPTION(options, METIS_OPTION_DBGLVL, 0);
83 ctrl->numflag = GETOPTION(options, METIS_OPTION_NUMBERING, 0);
85 /* set non-option information */
86 ctrl->optype = optype;
87 ctrl->ncon = ncon;
88 ctrl->nparts = nparts;
89 ctrl->maxvwgt = ismalloc(ncon, 0, "SetupCtrl: maxvwgt");
91 /* setup the target partition weights */
92 if (ctrl->optype != METIS_OP_OMETIS) {
93 ctrl->tpwgts = rmalloc(nparts*ncon, "SetupCtrl: ctrl->tpwgts");
94 if (tpwgts) {
95 rcopy(nparts*ncon, tpwgts, ctrl->tpwgts);
97 else {
98 for (i=0; i<nparts; i++) {
99 for (j=0; j<ncon; j++)
100 ctrl->tpwgts[i*ncon+j] = 1.0/nparts;
104 else { /* METIS_OP_OMETIS */
105 /* this is required to allow the pijbm to be defined properly for
106 the edge-based refinement during initial partitioning */
107 ctrl->tpwgts = rsmalloc(2, .5, "SetupCtrl: ctrl->tpwgts");
111 /* setup the ubfactors */
112 ctrl->ubfactors = rsmalloc(ctrl->ncon, I2RUBFACTOR(ctrl->ufactor), "SetupCtrl: ubfactors");
113 if (ubvec)
114 rcopy(ctrl->ncon, ubvec, ctrl->ubfactors);
115 for (i=0; i<ctrl->ncon; i++)
116 ctrl->ubfactors[i] += 0.0000499;
118 /* Allocate memory for balance multipliers.
119 Note that for PMETIS/OMETIS routines the memory allocated is more
120 than required as balance multipliers for 2 parts is sufficient. */
121 ctrl->pijbm = rmalloc(nparts*ncon, "SetupCtrl: ctrl->pijbm");
123 InitRandom(ctrl->seed);
125 IFSET(ctrl->dbglvl, METIS_DBG_INFO, PrintCtrl(ctrl));
127 if (!CheckParams(ctrl)) {
128 FreeCtrl(&ctrl);
129 return NULL;
131 else {
132 return ctrl;
137 /*************************************************************************/
138 /*! Computes the per-partition/constraint balance multipliers */
139 /*************************************************************************/
140 void SetupKWayBalMultipliers(ctrl_t *ctrl, graph_t *graph)
142 idx_t i, j;
144 for (i=0; i<ctrl->nparts; i++) {
145 for (j=0; j<graph->ncon; j++)
146 ctrl->pijbm[i*graph->ncon+j] = graph->invtvwgt[j]/ctrl->tpwgts[i*graph->ncon+j];
151 /*************************************************************************/
152 /*! Computes the per-partition/constraint balance multipliers */
153 /*************************************************************************/
154 void Setup2WayBalMultipliers(ctrl_t *ctrl, graph_t *graph, real_t *tpwgts)
156 idx_t i, j;
158 for (i=0; i<2; i++) {
159 for (j=0; j<graph->ncon; j++)
160 ctrl->pijbm[i*graph->ncon+j] = graph->invtvwgt[j]/tpwgts[i*graph->ncon+j];
165 /*************************************************************************/
166 /*! This function prints the various control fields */
167 /*************************************************************************/
168 void PrintCtrl(ctrl_t *ctrl)
170 idx_t i, j, modnum;
172 printf(" Runtime parameters:\n");
174 printf(" Objective type: ");
175 switch (ctrl->objtype) {
176 case METIS_OBJTYPE_CUT:
177 printf("METIS_OBJTYPE_CUT\n");
178 break;
179 case METIS_OBJTYPE_VOL:
180 printf("METIS_OBJTYPE_VOL\n");
181 break;
182 case METIS_OBJTYPE_NODE:
183 printf("METIS_OBJTYPE_NODE\n");
184 break;
185 default:
186 printf("Unknown!\n");
189 printf(" Coarsening type: ");
190 switch (ctrl->ctype) {
191 case METIS_CTYPE_RM:
192 printf("METIS_CTYPE_RM\n");
193 break;
194 case METIS_CTYPE_SHEM:
195 printf("METIS_CTYPE_SHEM\n");
196 break;
197 default:
198 printf("Unknown!\n");
201 printf(" Initial partitioning type: ");
202 switch (ctrl->iptype) {
203 case METIS_IPTYPE_GROW:
204 printf("METIS_IPTYPE_GROW\n");
205 break;
206 case METIS_IPTYPE_RANDOM:
207 printf("METIS_IPTYPE_RANDOM\n");
208 break;
209 case METIS_IPTYPE_EDGE:
210 printf("METIS_IPTYPE_EDGE\n");
211 break;
212 case METIS_IPTYPE_NODE:
213 printf("METIS_IPTYPE_NODE\n");
214 break;
215 case METIS_IPTYPE_METISRB:
216 printf("METIS_IPTYPE_METISRB\n");
217 break;
218 default:
219 printf("Unknown!\n");
222 printf(" Refinement type: ");
223 switch (ctrl->rtype) {
224 case METIS_RTYPE_FM:
225 printf("METIS_RTYPE_FM\n");
226 break;
227 case METIS_RTYPE_GREEDY:
228 printf("METIS_RTYPE_GREEDY\n");
229 break;
230 case METIS_RTYPE_SEP2SIDED:
231 printf("METIS_RTYPE_SEP2SIDED\n");
232 break;
233 case METIS_RTYPE_SEP1SIDED:
234 printf("METIS_RTYPE_SEP1SIDED\n");
235 break;
236 default:
237 printf("Unknown!\n");
240 printf(" Perform a 2-hop matching: %s\n", (ctrl->no2hop ? "Yes" : "No"));
242 printf(" Number of balancing constraints: %"PRIDX"\n", ctrl->ncon);
243 printf(" Number of refinement iterations: %"PRIDX"\n", ctrl->niter);
244 printf(" Random number seed: %"PRIDX"\n", ctrl->seed);
246 if (ctrl->optype == METIS_OP_OMETIS) {
247 printf(" Number of separators: %"PRIDX"\n", ctrl->nseps);
248 printf(" Compress graph prior to ordering: %s\n", (ctrl->compress ? "Yes" : "No"));
249 printf(" Detect & order connected components separately: %s\n", (ctrl->ccorder ? "Yes" : "No"));
250 printf(" Prunning factor for high degree vertices: %"PRREAL"\n", ctrl->pfactor);
252 else {
253 printf(" Number of partitions: %"PRIDX"\n", ctrl->nparts);
254 printf(" Number of cuts: %"PRIDX"\n", ctrl->ncuts);
255 printf(" User-supplied ufactor: %"PRIDX"\n", ctrl->ufactor);
257 if (ctrl->optype == METIS_OP_KMETIS) {
258 printf(" Minimize connectivity: %s\n", (ctrl->minconn ? "Yes" : "No"));
259 printf(" Create contigous partitions: %s\n", (ctrl->contig ? "Yes" : "No"));
262 modnum = (ctrl->ncon==1 ? 5 : (ctrl->ncon==2 ? 3 : (ctrl->ncon==3 ? 2 : 1)));
263 printf(" Target partition weights: ");
264 for (i=0; i<ctrl->nparts; i++) {
265 if (i%modnum == 0)
266 printf("\n ");
267 printf("%4"PRIDX"=[", i);
268 for (j=0; j<ctrl->ncon; j++)
269 printf("%s%.2e", (j==0 ? "" : " "), (double)ctrl->tpwgts[i*ctrl->ncon+j]);
270 printf("]");
272 printf("\n");
275 printf(" Allowed maximum load imbalance: ");
276 for (i=0; i<ctrl->ncon; i++)
277 printf("%.3"PRREAL" ", ctrl->ubfactors[i]);
278 printf("\n");
280 printf("\n");
284 /*************************************************************************/
285 /*! This function checks the validity of user-supplied parameters */
286 /*************************************************************************/
287 int CheckParams(ctrl_t *ctrl)
289 idx_t i, j;
290 real_t sum;
291 mdbglvl_et dbglvl=METIS_DBG_INFO;
293 switch (ctrl->optype) {
294 case METIS_OP_PMETIS:
295 if (ctrl->objtype != METIS_OBJTYPE_CUT) {
296 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect objective type.\n"));
297 return 0;
299 if (ctrl->ctype != METIS_CTYPE_RM && ctrl->ctype != METIS_CTYPE_SHEM) {
300 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect coarsening scheme.\n"));
301 return 0;
303 if (ctrl->iptype != METIS_IPTYPE_GROW && ctrl->iptype != METIS_IPTYPE_RANDOM) {
304 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect initial partitioning scheme.\n"));
305 return 0;
307 if (ctrl->rtype != METIS_RTYPE_FM) {
308 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect refinement scheme.\n"));
309 return 0;
311 if (ctrl->ncuts <= 0) {
312 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ncuts.\n"));
313 return 0;
315 if (ctrl->niter <= 0) {
316 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect niter.\n"));
317 return 0;
319 if (ctrl->ufactor <= 0) {
320 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ufactor.\n"));
321 return 0;
323 if (ctrl->numflag != 0 && ctrl->numflag != 1) {
324 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect numflag.\n"));
325 return 0;
327 if (ctrl->nparts <= 0) {
328 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect nparts.\n"));
329 return 0;
331 if (ctrl->ncon <= 0) {
332 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ncon.\n"));
333 return 0;
336 for (i=0; i<ctrl->ncon; i++) {
337 sum = rsum(ctrl->nparts, ctrl->tpwgts+i, ctrl->ncon);
338 if (sum < 0.99 || sum > 1.01) {
339 IFSET(dbglvl, METIS_DBG_INFO,
340 printf("Input Error: Incorrect sum of %"PRREAL" for tpwgts for constraint %"PRIDX".\n", sum, i));
341 return 0;
344 for (i=0; i<ctrl->ncon; i++) {
345 for (j=0; j<ctrl->nparts; j++) {
346 if (ctrl->tpwgts[j*ctrl->ncon+i] <= 0.0) {
347 IFSET(dbglvl, METIS_DBG_INFO,
348 printf("Input Error: Incorrect tpwgts for partition %"PRIDX" and constraint %"PRIDX".\n", j, i));
349 return 0;
354 for (i=0; i<ctrl->ncon; i++) {
355 if (ctrl->ubfactors[i] <= 1.0) {
356 IFSET(dbglvl, METIS_DBG_INFO,
357 printf("Input Error: Incorrect ubfactor for constraint %"PRIDX".\n", i));
358 return 0;
362 break;
364 case METIS_OP_KMETIS:
365 if (ctrl->objtype != METIS_OBJTYPE_CUT && ctrl->objtype != METIS_OBJTYPE_VOL) {
366 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect objective type.\n"));
367 return 0;
369 if (ctrl->ctype != METIS_CTYPE_RM && ctrl->ctype != METIS_CTYPE_SHEM) {
370 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect coarsening scheme.\n"));
371 return 0;
373 if (ctrl->iptype != METIS_IPTYPE_METISRB) {
374 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect initial partitioning scheme.\n"));
375 return 0;
377 if (ctrl->rtype != METIS_RTYPE_GREEDY) {
378 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect refinement scheme.\n"));
379 return 0;
381 if (ctrl->ncuts <= 0) {
382 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ncuts.\n"));
383 return 0;
385 if (ctrl->niter <= 0) {
386 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect niter.\n"));
387 return 0;
389 if (ctrl->ufactor <= 0) {
390 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ufactor.\n"));
391 return 0;
393 if (ctrl->numflag != 0 && ctrl->numflag != 1) {
394 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect numflag.\n"));
395 return 0;
397 if (ctrl->nparts <= 0) {
398 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect nparts.\n"));
399 return 0;
401 if (ctrl->ncon <= 0) {
402 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ncon.\n"));
403 return 0;
405 if (ctrl->contig != 0 && ctrl->contig != 1) {
406 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect contig.\n"));
407 return 0;
409 if (ctrl->minconn != 0 && ctrl->minconn != 1) {
410 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect minconn.\n"));
411 return 0;
414 for (i=0; i<ctrl->ncon; i++) {
415 sum = rsum(ctrl->nparts, ctrl->tpwgts+i, ctrl->ncon);
416 if (sum < 0.99 || sum > 1.01) {
417 IFSET(dbglvl, METIS_DBG_INFO,
418 printf("Input Error: Incorrect sum of %"PRREAL" for tpwgts for constraint %"PRIDX".\n", sum, i));
419 return 0;
422 for (i=0; i<ctrl->ncon; i++) {
423 for (j=0; j<ctrl->nparts; j++) {
424 if (ctrl->tpwgts[j*ctrl->ncon+i] <= 0.0) {
425 IFSET(dbglvl, METIS_DBG_INFO,
426 printf("Input Error: Incorrect tpwgts for partition %"PRIDX" and constraint %"PRIDX".\n", j, i));
427 return 0;
432 for (i=0; i<ctrl->ncon; i++) {
433 if (ctrl->ubfactors[i] <= 1.0) {
434 IFSET(dbglvl, METIS_DBG_INFO,
435 printf("Input Error: Incorrect ubfactor for constraint %"PRIDX".\n", i));
436 return 0;
440 break;
444 case METIS_OP_OMETIS:
445 if (ctrl->objtype != METIS_OBJTYPE_NODE) {
446 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect objective type.\n"));
447 return 0;
449 if (ctrl->ctype != METIS_CTYPE_RM && ctrl->ctype != METIS_CTYPE_SHEM) {
450 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect coarsening scheme.\n"));
451 return 0;
453 if (ctrl->iptype != METIS_IPTYPE_EDGE && ctrl->iptype != METIS_IPTYPE_NODE) {
454 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect initial partitioning scheme.\n"));
455 return 0;
457 if (ctrl->rtype != METIS_RTYPE_SEP1SIDED && ctrl->rtype != METIS_RTYPE_SEP2SIDED) {
458 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect refinement scheme.\n"));
459 return 0;
461 if (ctrl->nseps <= 0) {
462 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect nseps.\n"));
463 return 0;
465 if (ctrl->niter <= 0) {
466 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect niter.\n"));
467 return 0;
469 if (ctrl->ufactor <= 0) {
470 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ufactor.\n"));
471 return 0;
473 if (ctrl->numflag != 0 && ctrl->numflag != 1) {
474 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect numflag.\n"));
475 return 0;
477 if (ctrl->nparts != 3) {
478 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect nparts.\n"));
479 return 0;
481 if (ctrl->ncon != 1) {
482 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ncon.\n"));
483 return 0;
485 if (ctrl->compress != 0 && ctrl->compress != 1) {
486 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect compress.\n"));
487 return 0;
489 if (ctrl->ccorder != 0 && ctrl->ccorder != 1) {
490 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ccorder.\n"));
491 return 0;
493 if (ctrl->pfactor < 0.0 ) {
494 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect pfactor.\n"));
495 return 0;
498 for (i=0; i<ctrl->ncon; i++) {
499 if (ctrl->ubfactors[i] <= 1.0) {
500 IFSET(dbglvl, METIS_DBG_INFO,
501 printf("Input Error: Incorrect ubfactor for constraint %"PRIDX".\n", i));
502 return 0;
506 break;
508 default:
509 IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect optype\n"));
510 return 0;
513 return 1;
517 /*************************************************************************/
518 /*! This function frees the memory associated with a ctrl_t */
519 /*************************************************************************/
520 void FreeCtrl(ctrl_t **r_ctrl)
522 ctrl_t *ctrl = *r_ctrl;
524 FreeWorkSpace(ctrl);
526 gk_free((void **)&ctrl->tpwgts, &ctrl->pijbm,
527 &ctrl->ubfactors, &ctrl->maxvwgt, &ctrl, LTERM);
529 *r_ctrl = NULL;