Permalink
Browse files

Updated for a better interface to version 5

  • Loading branch information...
1 parent bf10fb1 commit abf009ee72b5cd5ca703dbb3d795e96d763286cc @dgleich committed May 22, 2012
Showing with 187 additions and 84 deletions.
  1. +21 −0 make.m
  2. +161 −84 metismex.c
  3. +5 −0 test_main.m
View
21 make.m
@@ -0,0 +1,21 @@
+function make
+c = computer;
+switch c
+ case 'MACI64'
+ mex -O -largeArrayDims -I../include -I../libmetis ...
+ -I../GKlib -L../build/Darwin-x86_64/libmetis ...
+ -lmetis metismex.c -D__thread= -DLINUX
+ case 'GLNX64'
+ mex -O -largeArrayDims -I../include -I../libmetis ...
+ -I../GKlib -L../build/Linux-x86_64/libmetis ...
+ -lmetis metismex.c -DLINUX
+ case 'MACI64'
+ mex -O -largeArrayDims -I../include -I../libmetis ...
+ -I../GKlib -L../build/Darwin-x86/libmetis ...
+ -lmetis metismex.c -D__thread= -DLINUX
+ case 'GLNX64'
+ mex -O -largeArrayDims -I../include -I../libmetis ...
+ -I../GKlib -L../build/Linux-x86/libmetis ...
+ -lmetis metismex.c -DLINUX
+end
+test_main
View
245 metismex.c
@@ -45,70 +45,6 @@ typedef int mwSize;
#include <metislib.h>
-/*************************************************************************
-* Given a graph, find a node separator bisecting it (roughly). The number
-* of bisector nodes is returned in *nbnd, and the nodes themselves in the
-* array bnds, which should already be allocated to have enough room.
-**************************************************************************/
-#if 0
-void METIS_NodeBisect(idx_t nvtxs, idx_t *xadj, idx_t *adjncy,
- idx_t *vwgt, idx_t *adjwgt, idx_t wgtflag,
- idx_t *options, idx_t *nbnd, idx_t *bnds, double unbalance)
-{
- idx_t i, j, tvwgt, tpwgts2[2];
- GraphType graph;
- CtrlType ctrl;
- idx_t *label, *bndind;
-
- if (options[0] == 0) { /* Use the default parameters */
- ctrl.CType = ONMETIS_CTYPE;
- ctrl.IType = ONMETIS_ITYPE;
- ctrl.RType = ONMETIS_RTYPE;
- ctrl.dbglvl = ONMETIS_DBGLVL;
- }
- else {
- ctrl.CType = options[OPTION_CTYPE];
- ctrl.IType = options[OPTION_ITYPE];
- ctrl.RType = options[OPTION_RTYPE];
- ctrl.dbglvl = options[OPTION_DBGLVL];
- }
- ctrl.nseps = 5; /* Take the best of 5 separators */
- ctrl.optype = OP_ONMETIS;
- ctrl.CoarsenTo = 50;
-
- IFSET(ctrl.dbglvl, DBG_TIME, InitTimers(&ctrl));
- IFSET(ctrl.dbglvl, DBG_TIME, starttimer(ctrl.TotalTmr));
-
- SetUpGraph(&graph, OP_ONMETIS, nvtxs, 1, xadj,adjncy,vwgt,adjwgt,wgtflag);
-
- /* Determine the weights of the partitions */
- tvwgt = idxsum(nvtxs, graph.vwgt);
- tpwgts2[0] = tvwgt/2;
- tpwgts2[1] = tvwgt-tpwgts2[0];
-
- ctrl.maxvwgt = (1.5*tvwgt)/ctrl.CoarsenTo;
-
- InitRandom(-1);
-
- AllocateWorkSpace(&ctrl, &graph, 2);
-
- MlevelNodeBisectionMultiple (&ctrl, &graph, tpwgts2, unbalance);
-
- IFSET(ctrl.dbglvl, DBG_SEPINFO, printf("Nvtxs: %6d, [%6d %6d %6d]\n", graph.nvtxs, graph.pwgts[0], graph.pwgts[1], graph.pwgts[2]));
-
- /* Now indicate the vertex separator */
- *nbnd = graph.nbnd;
- bndind = graph.bndind;
- label = graph.label;
- for (i = 0; i < *nbnd; ++i)
- bnds[i] = label[bndind[i]];
-
- IFSET(ctrl.dbglvl, DBG_TIME, stoptimer(ctrl.TotalTmr));
- IFSET(ctrl.dbglvl, DBG_TIME, PrintTimers(&ctrl));
-
- FreeWorkSpace(&ctrl, &graph);
-}
-#endif
void convertMatrix (const mxArray *A, idx_t **xadj, idx_t **adjncy,
idx_t **vwgt, idx_t **adjwgt)
@@ -152,14 +88,17 @@ struct string_map_data {
int val;
};
static struct string_map_data ctypeMap[] = {
- {"rb", METIS_PTYPE_RB},
- {"kway", METIS_PTYPE_KWAY},
- {NULL, 0}
+ {"rm", METIS_CTYPE_RM},
+ {"shem", METIS_CTYPE_SHEM},
+ {NULL, 0}
};
static struct string_map_data iptypeMap[] = {
- {"rm", METIS_CTYPE_RM},
- {"shem", METIS_CTYPE_SHEM},
+ {"grow", METIS_IPTYPE_GROW},
+ {"random", METIS_IPTYPE_RANDOM},
+ /* these are set via a function call EdgeND vs. NodeND */
+ /* {"node", METIS_IPTYPE_NODE}, */
+ /* {"edge", METIS_IPTYPE_EDGE}, */
{NULL, 0}
};
@@ -169,6 +108,12 @@ static struct string_map_data objtypeMap[] = {
{NULL, 0}
};
+static struct string_map_data rtypeMap[] = {
+ {"2sided", METIS_RTYPE_SEP2SIDED},
+ {"1sided", METIS_RTYPE_SEP1SIDED},
+ {NULL, 0}
+};
+
int parseString(mxArray* arg, struct string_map_data* map, char *argname) {
char argval[25];
if (!mxIsChar(arg)) {
@@ -195,25 +140,39 @@ struct option {
int val;
};
+struct parameter_data {
+#define METISMEX_OPTION_WGTFLAG -1
+ int wgtflag;
+#define METISMEX_OPTION_ADJWGT -2
+ int adjwgt;
+#define METISMEX_OPTION_VSIZE -3
+ idx_t *vsize;
+};
+
static struct option option_names[] = {
{"seed", 1, METIS_OPTION_SEED},
{"ctype", -1, METIS_OPTION_CTYPE},
{"iptype", -1, METIS_OPTION_IPTYPE},
{"objtype", -1, METIS_OPTION_OBJTYPE},
+ {"rtype", -1, METIS_OPTION_RTYPE},
{"minconn", 0, METIS_OPTION_MINCONN},
{"contig", 0, METIS_OPTION_CONTIG},
{"ufactor", 1, METIS_OPTION_UFACTOR},
{"niter", 1, METIS_OPTION_NITER},
{"ncuts", 1, METIS_OPTION_NCUTS},
+ {"nseps", 1, METIS_OPTION_NSEPS},
+ {"ccorder", 0, METIS_OPTION_CCORDER},
+ {"nocompress", -1, METIS_OPTION_COMPRESS},
+ {"pfactor", 1, METIS_OPTION_PFACTOR},
+ {"dbglvl", 1, METIS_OPTION_DBGLVL},
{"tpwgts", -1, METIS_OPTION_TPWGTS},
{"ubvec", -1, METIS_OPTION_UBVEC},
+ {"wgtflag", -1, METISMEX_OPTION_WGTFLAG},
+ {"adjwgt", -1, METISMEX_OPTION_ADJWGT},
+ {"vsize",-1, METISMEX_OPTION_VSIZE},
{NULL, 0, 0},
};
-struct parameter_data {
- int wgtflag;
-};
-
void parseOptions(const mxArray *optarg, idx_t *options, struct parameter_data* params)
{
struct option* opt = option_names;
@@ -236,12 +195,24 @@ void parseOptions(const mxArray *optarg, idx_t *options, struct parameter_data*
case METIS_OPTION_OBJTYPE:
options[opt->val] = parseString(mopt, objtypeMap, opt->name);
break;
+ case METIS_OPTION_RTYPE:
+ options[opt->val] = parseString(mopt, rtypeMap, opt->name);
+ break;
case METIS_OPTION_TPWGTS:
mxAssert(0, "tpwgts not handled");
break;
case METIS_OPTION_UBVEC:
mxAssert(0, "ubvec not handled");
break;
+ case METIS_OPTION_COMPRESS: // this is the nocompress option
+ options[opt->val] = 0;
+ break;
+ case METISMEX_OPTION_WGTFLAG:
+ params->wgtflag = 1;
+ break;
+ case METISMEX_OPTION_ADJWGT:
+ params->adjwgt = 1;
+ break;
default:
mxAssert(0, "unhandled option");
}
@@ -267,17 +238,39 @@ void parseOptions(const mxArray *optarg, idx_t *options, struct parameter_data*
#define FUNCNAMELEN 25
+void checkCall(int rval) {
+ switch (rval) {
+ case METIS_OK:
+ return;
+ case METIS_ERROR_INPUT:
+ mexErrMsgIdAndTxt("metismex:metisError", "metis input error");
+ break;
+ case METIS_ERROR_MEMORY:
+ mexErrMsgIdAndTxt("metismex:metisError", "metis memory error");
+ break;
+ default:
+ mexErrMsgIdAndTxt("metismex:metisError", "unknown metis error");
+ break;
+ }
+}
+
+
/****************************************************************************
* mexFunction: gateway routine for MATLAB interface.
*****************************************************************************/
void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
- idx_t i, n, nparts, wgtflag=0, options[METIS_NOPTIONS] = {0}, edgecut, sepsize;
+ idx_t i, n, nparts, options[METIS_NOPTIONS] = {0}, edgecut, sepsize;
idx_t *xadj, *adjncy, *vwgt, *adjwgt, *part, *perm, *iperm, *sep;
char funcname[FUNCNAMELEN];
double *optarray, *partpr, *permpr, *ipermpr, *seppr;
- struct parameter_data params;
+
+ struct parameter_data params = {
+ 0, // wgtflag = 0
+ 0, // adjwgt = 0
+ NULL, // vsize = NULL
+ };
/* First do some general argument checking */
if (nrhs < 2 || nrhs > 4 || nlhs > 2) {
@@ -296,6 +289,9 @@ void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
/* Copy the matrix over, getting rid of diagonal, and converting to
* integer weights */
convertMatrix (A_IN, &xadj, &adjncy, &vwgt, &adjwgt);
+
+ /* Allocate vsize */
+ params.vsize = (idx_t*)mxMalloc(sizeof(idx_t)*n);
/* Now figure out which function we have to do */
mxGetString (FUNC_IN, funcname, FUNCNAMELEN);
@@ -312,11 +308,17 @@ void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
parseOptions(prhs[3], options, &params);
}
- if (wgtflag == 0) {
+ if (params.wgtflag == 0) {
for (i=0; i<n; ++i) {
vwgt[i] = 1;
}
- }
+ }
+
+ if (params.adjwgt == 0) {
+ for (i=0; i<xadj[n]; ++i) {
+ adjwgt[i] = 1;
+ }
+ }
if (nparts < 2) {
mexErrMsgTxt("nparts must be at least 2");
@@ -326,18 +328,19 @@ void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
part = (idx_t*) mxCalloc (n, sizeof(idx_t));
idx_t ncon = 1;
- idx_t* vsize = (idx_t*)mxMalloc(sizeof(idx_t)*n);
for (i=0; i<n; ++i) {
- vsize[i] = 1;
+ params.vsize[i] = 1;
}
/* Do the call */
if (strcasecmp(funcname,"PartGraphRecursive") == 0) {
- METIS_PartGraphRecursive (&n, &ncon, xadj, adjncy, vwgt, vsize, adjwgt,
- &nparts, NULL, NULL, options, &edgecut, part);
+ checkCall(METIS_PartGraphRecursive (&n, &ncon, xadj, adjncy,
+ vwgt, params.vsize, adjwgt,
+ &nparts, NULL, NULL, options, &edgecut, part));
} else if (strcasecmp(funcname, "PartGraphKway") == 0) {
- METIS_PartGraphKway (&n, &ncon, xadj, adjncy, vwgt, vsize, adjwgt,
- &nparts, NULL, NULL, options, &edgecut, part);
+ checkCall(METIS_PartGraphKway (&n, &ncon, xadj, adjncy,
+ vwgt, params.vsize, adjwgt,
+ &nparts, NULL, NULL, options, &edgecut, part));
} else {
mxAssert(0,"unhandled case");
}
@@ -358,6 +361,8 @@ void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
} else if (strcasecmp(funcname,"EdgeND")==0 ||
strcasecmp(funcname,"NodeND")==0) {
+
+ mexWarnMsgTxt("untested code");
/* Figure out values for options */
if (nrhs >= 3) {
@@ -369,7 +374,13 @@ void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
iperm = (idx_t*) mxCalloc (n, sizeof(idx_t));
/* Do the call */
- METIS_NodeND (&n, xadj, adjncy, NULL, options, perm, iperm);
+ if (strcasecmp(funcname,"EdgeND")==0) {
+ options[METIS_OPTION_IPTYPE] = METIS_IPTYPE_EDGE;
+ METIS_NodeND (&n, xadj, adjncy, NULL, options, perm, iperm);
+ } else {
+ options[METIS_OPTION_IPTYPE] = METIS_IPTYPE_NODE;
+ METIS_NodeND (&n, xadj, adjncy, NULL, options, perm, iperm);
+ }
/* Figure out output values */
if (nlhs >= 1) {
@@ -424,3 +435,69 @@ void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
}
}
+
+
+/*************************************************************************
+* Given a graph, find a node separator bisecting it (roughly). The number
+* of bisector nodes is returned in *nbnd, and the nodes themselves in the
+* array bnds, which should already be allocated to have enough room.
+**************************************************************************/
+#if 0
+void METIS_NodeBisect(idx_t nvtxs, idx_t *xadj, idx_t *adjncy,
+ idx_t *vwgt, idx_t *adjwgt, idx_t wgtflag,
+ idx_t *options, idx_t *nbnd, idx_t *bnds, double unbalance)
+{
+ idx_t i, j, tvwgt, tpwgts2[2];
+ GraphType graph;
+ CtrlType ctrl;
+ idx_t *label, *bndind;
+
+ if (options[0] == 0) { /* Use the default parameters */
+ ctrl.CType = ONMETIS_CTYPE;
+ ctrl.IType = ONMETIS_ITYPE;
+ ctrl.RType = ONMETIS_RTYPE;
+ ctrl.dbglvl = ONMETIS_DBGLVL;
+ }
+ else {
+ ctrl.CType = options[OPTION_CTYPE];
+ ctrl.IType = options[OPTION_ITYPE];
+ ctrl.RType = options[OPTION_RTYPE];
+ ctrl.dbglvl = options[OPTION_DBGLVL];
+ }
+ ctrl.nseps = 5; /* Take the best of 5 separators */
+ ctrl.optype = OP_ONMETIS;
+ ctrl.CoarsenTo = 50;
+
+ IFSET(ctrl.dbglvl, DBG_TIME, InitTimers(&ctrl));
+ IFSET(ctrl.dbglvl, DBG_TIME, starttimer(ctrl.TotalTmr));
+
+ SetUpGraph(&graph, OP_ONMETIS, nvtxs, 1, xadj,adjncy,vwgt,adjwgt,wgtflag);
+
+ /* Determine the weights of the partitions */
+ tvwgt = idxsum(nvtxs, graph.vwgt);
+ tpwgts2[0] = tvwgt/2;
+ tpwgts2[1] = tvwgt-tpwgts2[0];
+
+ ctrl.maxvwgt = (1.5*tvwgt)/ctrl.CoarsenTo;
+
+ InitRandom(-1);
+
+ AllocateWorkSpace(&ctrl, &graph, 2);
+
+ MlevelNodeBisectionMultiple (&ctrl, &graph, tpwgts2, unbalance);
+
+ IFSET(ctrl.dbglvl, DBG_SEPINFO, printf("Nvtxs: %6d, [%6d %6d %6d]\n", graph.nvtxs, graph.pwgts[0], graph.pwgts[1], graph.pwgts[2]));
+
+ /* Now indicate the vertex separator */
+ *nbnd = graph.nbnd;
+ bndind = graph.bndind;
+ label = graph.label;
+ for (i = 0; i < *nbnd; ++i)
+ bnds[i] = label[bndind[i]];
+
+ IFSET(ctrl.dbglvl, DBG_TIME, stoptimer(ctrl.TotalTmr));
+ IFSET(ctrl.dbglvl, DBG_TIME, PrintTimers(&ctrl));
+
+ FreeWorkSpace(&ctrl, &graph);
+}
+#endif
View
5 test_main.m
@@ -0,0 +1,5 @@
+function test_main
+A = spaugment(ones(5)); A(1,10) = 1; A(10,1) = 1; A(5,6) = 1; A(6,5) = 1;
+map = metismex('PartGraphRecursive',sparse(A),2);
+map2 = metismex('PartGraphRecursive',sparse(A),2,struct('seed',2));
+assert(any(map ~= map2));

0 comments on commit abf009e

Please sign in to comment.