3 \brief This file contains various routines for dealing with options and ctrl_t.
5 \date Started 5/12/2011
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
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
)
23 ctrl
= (ctrl_t
*)gk_malloc(sizeof(ctrl_t
), "SetupCtrl: ctrl");
25 memset((void *)ctrl
, 0, sizeof(ctrl_t
));
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);
35 ctrl
->iptype
= GETOPTION(options
, METIS_OPTION_IPTYPE
, METIS_IPTYPE_GROW
);
36 ctrl
->ufactor
= GETOPTION(options
, METIS_OPTION_UFACTOR
, PMETIS_DEFAULT_UFACTOR
);
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;
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);
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;
75 gk_errexit(SIGERR
, "Unknown optype of %d\n", optype
);
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
;
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");
95 rcopy(nparts
*ncon
, tpwgts
, ctrl
->tpwgts
);
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");
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
)) {
137 /*************************************************************************/
138 /*! Computes the per-partition/constraint balance multipliers */
139 /*************************************************************************/
140 void SetupKWayBalMultipliers(ctrl_t
*ctrl
, graph_t
*graph
)
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
)
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
)
172 printf(" Runtime parameters:\n");
174 printf(" Objective type: ");
175 switch (ctrl
->objtype
) {
176 case METIS_OBJTYPE_CUT
:
177 printf("METIS_OBJTYPE_CUT\n");
179 case METIS_OBJTYPE_VOL
:
180 printf("METIS_OBJTYPE_VOL\n");
182 case METIS_OBJTYPE_NODE
:
183 printf("METIS_OBJTYPE_NODE\n");
186 printf("Unknown!\n");
189 printf(" Coarsening type: ");
190 switch (ctrl
->ctype
) {
192 printf("METIS_CTYPE_RM\n");
194 case METIS_CTYPE_SHEM
:
195 printf("METIS_CTYPE_SHEM\n");
198 printf("Unknown!\n");
201 printf(" Initial partitioning type: ");
202 switch (ctrl
->iptype
) {
203 case METIS_IPTYPE_GROW
:
204 printf("METIS_IPTYPE_GROW\n");
206 case METIS_IPTYPE_RANDOM
:
207 printf("METIS_IPTYPE_RANDOM\n");
209 case METIS_IPTYPE_EDGE
:
210 printf("METIS_IPTYPE_EDGE\n");
212 case METIS_IPTYPE_NODE
:
213 printf("METIS_IPTYPE_NODE\n");
215 case METIS_IPTYPE_METISRB
:
216 printf("METIS_IPTYPE_METISRB\n");
219 printf("Unknown!\n");
222 printf(" Refinement type: ");
223 switch (ctrl
->rtype
) {
225 printf("METIS_RTYPE_FM\n");
227 case METIS_RTYPE_GREEDY
:
228 printf("METIS_RTYPE_GREEDY\n");
230 case METIS_RTYPE_SEP2SIDED
:
231 printf("METIS_RTYPE_SEP2SIDED\n");
233 case METIS_RTYPE_SEP1SIDED
:
234 printf("METIS_RTYPE_SEP1SIDED\n");
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
);
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
++) {
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
]);
275 printf(" Allowed maximum load imbalance: ");
276 for (i
=0; i
<ctrl
->ncon
; i
++)
277 printf("%.3"PRREAL
" ", ctrl
->ubfactors
[i
]);
284 /*************************************************************************/
285 /*! This function checks the validity of user-supplied parameters */
286 /*************************************************************************/
287 int CheckParams(ctrl_t
*ctrl
)
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"));
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"));
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"));
307 if (ctrl
->rtype
!= METIS_RTYPE_FM
) {
308 IFSET(dbglvl
, METIS_DBG_INFO
, printf("Input Error: Incorrect refinement scheme.\n"));
311 if (ctrl
->ncuts
<= 0) {
312 IFSET(dbglvl
, METIS_DBG_INFO
, printf("Input Error: Incorrect ncuts.\n"));
315 if (ctrl
->niter
<= 0) {
316 IFSET(dbglvl
, METIS_DBG_INFO
, printf("Input Error: Incorrect niter.\n"));
319 if (ctrl
->ufactor
<= 0) {
320 IFSET(dbglvl
, METIS_DBG_INFO
, printf("Input Error: Incorrect ufactor.\n"));
323 if (ctrl
->numflag
!= 0 && ctrl
->numflag
!= 1) {
324 IFSET(dbglvl
, METIS_DBG_INFO
, printf("Input Error: Incorrect numflag.\n"));
327 if (ctrl
->nparts
<= 0) {
328 IFSET(dbglvl
, METIS_DBG_INFO
, printf("Input Error: Incorrect nparts.\n"));
331 if (ctrl
->ncon
<= 0) {
332 IFSET(dbglvl
, METIS_DBG_INFO
, printf("Input Error: Incorrect ncon.\n"));
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
));
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
));
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
));
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"));
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"));
373 if (ctrl
->iptype
!= METIS_IPTYPE_METISRB
) {
374 IFSET(dbglvl
, METIS_DBG_INFO
, printf("Input Error: Incorrect initial partitioning scheme.\n"));
377 if (ctrl
->rtype
!= METIS_RTYPE_GREEDY
) {
378 IFSET(dbglvl
, METIS_DBG_INFO
, printf("Input Error: Incorrect refinement scheme.\n"));
381 if (ctrl
->ncuts
<= 0) {
382 IFSET(dbglvl
, METIS_DBG_INFO
, printf("Input Error: Incorrect ncuts.\n"));
385 if (ctrl
->niter
<= 0) {
386 IFSET(dbglvl
, METIS_DBG_INFO
, printf("Input Error: Incorrect niter.\n"));
389 if (ctrl
->ufactor
<= 0) {
390 IFSET(dbglvl
, METIS_DBG_INFO
, printf("Input Error: Incorrect ufactor.\n"));
393 if (ctrl
->numflag
!= 0 && ctrl
->numflag
!= 1) {
394 IFSET(dbglvl
, METIS_DBG_INFO
, printf("Input Error: Incorrect numflag.\n"));
397 if (ctrl
->nparts
<= 0) {
398 IFSET(dbglvl
, METIS_DBG_INFO
, printf("Input Error: Incorrect nparts.\n"));
401 if (ctrl
->ncon
<= 0) {
402 IFSET(dbglvl
, METIS_DBG_INFO
, printf("Input Error: Incorrect ncon.\n"));
405 if (ctrl
->contig
!= 0 && ctrl
->contig
!= 1) {
406 IFSET(dbglvl
, METIS_DBG_INFO
, printf("Input Error: Incorrect contig.\n"));
409 if (ctrl
->minconn
!= 0 && ctrl
->minconn
!= 1) {
410 IFSET(dbglvl
, METIS_DBG_INFO
, printf("Input Error: Incorrect minconn.\n"));
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
));
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
));
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
));
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"));
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"));
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"));
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"));
461 if (ctrl
->nseps
<= 0) {
462 IFSET(dbglvl
, METIS_DBG_INFO
, printf("Input Error: Incorrect nseps.\n"));
465 if (ctrl
->niter
<= 0) {
466 IFSET(dbglvl
, METIS_DBG_INFO
, printf("Input Error: Incorrect niter.\n"));
469 if (ctrl
->ufactor
<= 0) {
470 IFSET(dbglvl
, METIS_DBG_INFO
, printf("Input Error: Incorrect ufactor.\n"));
473 if (ctrl
->numflag
!= 0 && ctrl
->numflag
!= 1) {
474 IFSET(dbglvl
, METIS_DBG_INFO
, printf("Input Error: Incorrect numflag.\n"));
477 if (ctrl
->nparts
!= 3) {
478 IFSET(dbglvl
, METIS_DBG_INFO
, printf("Input Error: Incorrect nparts.\n"));
481 if (ctrl
->ncon
!= 1) {
482 IFSET(dbglvl
, METIS_DBG_INFO
, printf("Input Error: Incorrect ncon.\n"));
485 if (ctrl
->compress
!= 0 && ctrl
->compress
!= 1) {
486 IFSET(dbglvl
, METIS_DBG_INFO
, printf("Input Error: Incorrect compress.\n"));
489 if (ctrl
->ccorder
!= 0 && ctrl
->ccorder
!= 1) {
490 IFSET(dbglvl
, METIS_DBG_INFO
, printf("Input Error: Incorrect ccorder.\n"));
493 if (ctrl
->pfactor
< 0.0 ) {
494 IFSET(dbglvl
, METIS_DBG_INFO
, printf("Input Error: Incorrect pfactor.\n"));
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
));
509 IFSET(dbglvl
, METIS_DBG_INFO
, printf("Input Error: Incorrect optype\n"));
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
;
526 gk_free((void **)&ctrl
->tpwgts
, &ctrl
->pijbm
,
527 &ctrl
->ubfactors
, &ctrl
->maxvwgt
, &ctrl
, LTERM
);