Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Updated for a better interface to version 5

  • Loading branch information...
commit abf009ee72b5cd5ca703dbb3d795e96d763286cc 1 parent bf10fb1
David Gleich authored May 22, 2012
21  make.m
... ...
@@ -0,0 +1,21 @@
  1
+function make
  2
+c = computer;
  3
+switch c
  4
+    case 'MACI64'
  5
+        mex -O -largeArrayDims -I../include -I../libmetis ...
  6
+                -I../GKlib -L../build/Darwin-x86_64/libmetis ...
  7
+                -lmetis metismex.c -D__thread= -DLINUX
  8
+    case 'GLNX64'
  9
+        mex -O -largeArrayDims -I../include -I../libmetis ...
  10
+                -I../GKlib -L../build/Linux-x86_64/libmetis ...
  11
+                -lmetis metismex.c -DLINUX
  12
+    case 'MACI64'
  13
+        mex -O -largeArrayDims -I../include -I../libmetis ...
  14
+                -I../GKlib -L../build/Darwin-x86/libmetis ...
  15
+                -lmetis metismex.c -D__thread= -DLINUX
  16
+    case 'GLNX64'
  17
+        mex -O -largeArrayDims -I../include -I../libmetis ...
  18
+                -I../GKlib -L../build/Linux-x86/libmetis ...
  19
+                -lmetis metismex.c -DLINUX
  20
+end
  21
+test_main
245  metismex.c
@@ -45,70 +45,6 @@ typedef int mwSize;
45 45
 
46 46
 #include <metislib.h>
47 47
 
48  
-/*************************************************************************
49  
-* Given a graph, find a node separator bisecting it (roughly). The number
50  
-* of bisector nodes is returned in *nbnd, and the nodes themselves in the
51  
-* array bnds, which should already be allocated to have enough room.
52  
-**************************************************************************/
53  
-#if 0
54  
-void METIS_NodeBisect(idx_t nvtxs, idx_t *xadj, idx_t *adjncy,
55  
-                      idx_t *vwgt, idx_t *adjwgt, idx_t wgtflag,
56  
-                      idx_t *options, idx_t *nbnd, idx_t *bnds, double unbalance)
57  
-{
58  
-  idx_t i, j, tvwgt, tpwgts2[2];
59  
-  GraphType graph;
60  
-  CtrlType ctrl;
61  
-  idx_t *label, *bndind;
62  
-
63  
-  if (options[0] == 0) {  /* Use the default parameters */
64  
-    ctrl.CType   = ONMETIS_CTYPE;
65  
-    ctrl.IType   = ONMETIS_ITYPE;
66  
-    ctrl.RType   = ONMETIS_RTYPE;
67  
-    ctrl.dbglvl  = ONMETIS_DBGLVL;
68  
-  }
69  
-  else {
70  
-    ctrl.CType   = options[OPTION_CTYPE];
71  
-    ctrl.IType   = options[OPTION_ITYPE];
72  
-    ctrl.RType   = options[OPTION_RTYPE];
73  
-    ctrl.dbglvl  = options[OPTION_DBGLVL];
74  
-  }
75  
-  ctrl.nseps = 5;    /* Take the best of 5 separators */
76  
-  ctrl.optype = OP_ONMETIS;
77  
-  ctrl.CoarsenTo = 50;
78  
-
79  
-  IFSET(ctrl.dbglvl, DBG_TIME, InitTimers(&ctrl));
80  
-  IFSET(ctrl.dbglvl, DBG_TIME, starttimer(ctrl.TotalTmr));
81  
-
82  
-  SetUpGraph(&graph, OP_ONMETIS, nvtxs, 1, xadj,adjncy,vwgt,adjwgt,wgtflag);
83  
-
84  
-  /* Determine the weights of the partitions */
85  
-  tvwgt = idxsum(nvtxs, graph.vwgt);
86  
-  tpwgts2[0] = tvwgt/2;
87  
-  tpwgts2[1] = tvwgt-tpwgts2[0];
88  
-
89  
-  ctrl.maxvwgt = (1.5*tvwgt)/ctrl.CoarsenTo;
90  
-
91  
-  InitRandom(-1);
92  
-
93  
-  AllocateWorkSpace(&ctrl, &graph, 2);
94  
-
95  
-  MlevelNodeBisectionMultiple (&ctrl, &graph, tpwgts2, unbalance);
96  
-
97  
-  IFSET(ctrl.dbglvl, DBG_SEPINFO, printf("Nvtxs: %6d, [%6d %6d %6d]\n", graph.nvtxs, graph.pwgts[0], graph.pwgts[1], graph.pwgts[2]));
98  
-
99  
-  /* Now indicate the vertex separator */
100  
-  *nbnd = graph.nbnd;
101  
-  bndind = graph.bndind;
102  
-  label = graph.label;
103  
-  for (i = 0; i < *nbnd; ++i) 
104  
-    bnds[i] = label[bndind[i]];
105  
-
106  
-  IFSET(ctrl.dbglvl, DBG_TIME, stoptimer(ctrl.TotalTmr));
107  
-  IFSET(ctrl.dbglvl, DBG_TIME, PrintTimers(&ctrl));
108  
-
109  
-  FreeWorkSpace(&ctrl, &graph);
110  
-}
111  
-#endif
112 48
 
113 49
 void convertMatrix (const mxArray *A, idx_t **xadj, idx_t **adjncy,
114 50
                     idx_t **vwgt, idx_t **adjwgt)
@@ -152,14 +88,17 @@ struct string_map_data {
152 88
     int val;
153 89
 };
154 90
 static struct string_map_data ctypeMap[] = {
155  
-  {"rb",                 METIS_PTYPE_RB},
156  
-  {"kway",               METIS_PTYPE_KWAY},
157  
-  {NULL,                 0}
  91
+ {"rm",                 METIS_CTYPE_RM},
  92
+ {"shem",               METIS_CTYPE_SHEM},
  93
+ {NULL,                 0}
158 94
 };
159 95
 
160 96
 static struct string_map_data iptypeMap[] = {
161  
-  {"rm",                 METIS_CTYPE_RM},
162  
-  {"shem",               METIS_CTYPE_SHEM},
  97
+  {"grow",               METIS_IPTYPE_GROW},
  98
+  {"random",             METIS_IPTYPE_RANDOM},
  99
+  /* these are set via a function call EdgeND vs. NodeND */
  100
+  /* {"node",               METIS_IPTYPE_NODE}, */ 
  101
+  /* {"edge",               METIS_IPTYPE_EDGE}, */
163 102
   {NULL,                 0}
164 103
 };
165 104
 
@@ -169,6 +108,12 @@ static struct string_map_data objtypeMap[] = {
169 108
   {NULL,                 0}
170 109
 };
171 110
 
  111
+static struct string_map_data rtypeMap[] = {
  112
+  {"2sided",             METIS_RTYPE_SEP2SIDED},
  113
+  {"1sided",             METIS_RTYPE_SEP1SIDED},
  114
+  {NULL,                 0}
  115
+};
  116
+
172 117
 int parseString(mxArray* arg, struct string_map_data* map, char *argname) {
173 118
     char argval[25];
174 119
     if (!mxIsChar(arg)) {
@@ -195,25 +140,39 @@ struct option {
195 140
     int val;
196 141
 };
197 142
 
  143
+struct parameter_data  {
  144
+#define METISMEX_OPTION_WGTFLAG -1
  145
+    int wgtflag;
  146
+#define METISMEX_OPTION_ADJWGT -2
  147
+    int adjwgt;
  148
+#define METISMEX_OPTION_VSIZE -3
  149
+    idx_t *vsize;
  150
+};
  151
+
198 152
 static struct option option_names[] = {
199 153
  {"seed", 1, METIS_OPTION_SEED},
200 154
  {"ctype", -1, METIS_OPTION_CTYPE},
201 155
  {"iptype", -1, METIS_OPTION_IPTYPE},
202 156
  {"objtype", -1, METIS_OPTION_OBJTYPE},
  157
+ {"rtype", -1, METIS_OPTION_RTYPE},
203 158
  {"minconn", 0, METIS_OPTION_MINCONN},
204 159
  {"contig", 0, METIS_OPTION_CONTIG},
205 160
  {"ufactor", 1, METIS_OPTION_UFACTOR},
206 161
  {"niter", 1, METIS_OPTION_NITER},
207 162
  {"ncuts",  1, METIS_OPTION_NCUTS},
  163
+ {"nseps",  1, METIS_OPTION_NSEPS},
  164
+ {"ccorder",  0, METIS_OPTION_CCORDER},
  165
+ {"nocompress", -1, METIS_OPTION_COMPRESS},
  166
+ {"pfactor", 1, METIS_OPTION_PFACTOR},
  167
+ {"dbglvl", 1, METIS_OPTION_DBGLVL},
208 168
  {"tpwgts", -1, METIS_OPTION_TPWGTS},
209 169
  {"ubvec", -1, METIS_OPTION_UBVEC},
  170
+ {"wgtflag", -1, METISMEX_OPTION_WGTFLAG},
  171
+ {"adjwgt", -1, METISMEX_OPTION_ADJWGT},
  172
+ {"vsize",-1, METISMEX_OPTION_VSIZE},
210 173
  {NULL, 0, 0},
211 174
 }; 
212 175
 
213  
-struct parameter_data  {
214  
-  int wgtflag;
215  
-};
216  
-
217 176
 void parseOptions(const mxArray *optarg, idx_t *options, struct parameter_data* params)
218 177
 {
219 178
     struct option* opt = option_names;
@@ -236,12 +195,24 @@ void parseOptions(const mxArray *optarg, idx_t *options, struct parameter_data*
236 195
                 case METIS_OPTION_OBJTYPE:
237 196
                 options[opt->val] = parseString(mopt, objtypeMap, opt->name);
238 197
                 break;
  198
+                case METIS_OPTION_RTYPE:
  199
+                options[opt->val] = parseString(mopt, rtypeMap, opt->name);
  200
+                break;
239 201
                 case METIS_OPTION_TPWGTS:
240 202
                 mxAssert(0, "tpwgts not handled");
241 203
                 break;
242 204
                 case METIS_OPTION_UBVEC:
243 205
                 mxAssert(0, "ubvec not handled");
244 206
                 break;
  207
+                case METIS_OPTION_COMPRESS: // this is the nocompress option
  208
+                options[opt->val] = 0;
  209
+                break;
  210
+                case METISMEX_OPTION_WGTFLAG:
  211
+                params->wgtflag = 1;
  212
+                break;
  213
+                case METISMEX_OPTION_ADJWGT:
  214
+                params->adjwgt = 1;
  215
+                break;
245 216
                 default:
246 217
                     mxAssert(0, "unhandled option");
247 218
                 }
@@ -267,17 +238,39 @@ void parseOptions(const mxArray *optarg, idx_t *options, struct parameter_data*
267 238
 
268 239
 #define FUNCNAMELEN 25
269 240
 
  241
+void checkCall(int rval) {
  242
+    switch (rval) {
  243
+        case METIS_OK:
  244
+            return;
  245
+        case METIS_ERROR_INPUT:
  246
+            mexErrMsgIdAndTxt("metismex:metisError", "metis input error");
  247
+            break;
  248
+        case METIS_ERROR_MEMORY:
  249
+            mexErrMsgIdAndTxt("metismex:metisError", "metis memory error");
  250
+            break;
  251
+        default:
  252
+            mexErrMsgIdAndTxt("metismex:metisError", "unknown metis error");
  253
+            break;
  254
+    }
  255
+}
  256
+         
  257
+
270 258
 /****************************************************************************
271 259
 * mexFunction: gateway routine for MATLAB interface.
272 260
 *****************************************************************************/
273 261
 void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
274 262
 {
275  
-    idx_t i, n, nparts, wgtflag=0, options[METIS_NOPTIONS] = {0}, edgecut, sepsize;
  263
+    idx_t i, n, nparts, options[METIS_NOPTIONS] = {0}, edgecut, sepsize;
276 264
     idx_t *xadj, *adjncy, *vwgt, *adjwgt, *part, *perm, *iperm, *sep;
277 265
     
278 266
     char funcname[FUNCNAMELEN];
279 267
     double *optarray, *partpr, *permpr, *ipermpr, *seppr;
280  
-    struct parameter_data params;
  268
+    
  269
+    struct parameter_data params = {
  270
+            0, // wgtflag = 0
  271
+            0, // adjwgt = 0
  272
+            NULL, // vsize = NULL
  273
+            }; 
281 274
 
282 275
     /* First do some general argument checking */
283 276
     if (nrhs < 2 || nrhs > 4 || nlhs > 2) {
@@ -296,6 +289,9 @@ void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
296 289
     /* Copy the matrix over, getting rid of diagonal, and converting to
297 290
      * integer weights */
298 291
     convertMatrix (A_IN, &xadj, &adjncy, &vwgt, &adjwgt);
  292
+    
  293
+    /* Allocate vsize */
  294
+    params.vsize = (idx_t*)mxMalloc(sizeof(idx_t)*n);
299 295
 
300 296
     /* Now figure out which function we have to do */
301 297
     mxGetString (FUNC_IN, funcname, FUNCNAMELEN);
@@ -312,11 +308,17 @@ void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
312 308
             parseOptions(prhs[3], options, &params); 
313 309
         }
314 310
         
315  
-        if (wgtflag == 0) {
  311
+        if (params.wgtflag == 0) {
316 312
             for (i=0; i<n; ++i) {
317 313
                 vwgt[i] = 1;
318 314
             }
319  
-        }        
  315
+        }
  316
+        
  317
+        if (params.adjwgt == 0) {
  318
+            for (i=0; i<xadj[n]; ++i) {
  319
+                adjwgt[i] = 1;
  320
+            }
  321
+        }
320 322
 
321 323
         if (nparts < 2) { 
322 324
             mexErrMsgTxt("nparts must be at least 2");
@@ -326,18 +328,19 @@ void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
326 328
         part = (idx_t*) mxCalloc (n, sizeof(idx_t));
327 329
         
328 330
         idx_t ncon = 1;
329  
-        idx_t* vsize = (idx_t*)mxMalloc(sizeof(idx_t)*n);
330 331
         for (i=0; i<n; ++i) { 
331  
-            vsize[i] = 1;
  332
+            params.vsize[i] = 1;
332 333
         }
333 334
 
334 335
         /* Do the call */
335 336
         if (strcasecmp(funcname,"PartGraphRecursive") == 0) {
336  
-            METIS_PartGraphRecursive (&n, &ncon, xadj, adjncy, vwgt, vsize, adjwgt, 
337  
-                &nparts, NULL, NULL, options, &edgecut, part);
  337
+            checkCall(METIS_PartGraphRecursive (&n, &ncon, xadj, adjncy,
  338
+                 vwgt, params.vsize, adjwgt, 
  339
+                 &nparts, NULL, NULL, options, &edgecut, part));
338 340
         } else if (strcasecmp(funcname, "PartGraphKway") == 0) {
339  
-            METIS_PartGraphKway (&n, &ncon, xadj, adjncy, vwgt, vsize, adjwgt, 
340  
-                &nparts, NULL, NULL, options, &edgecut, part);
  341
+            checkCall(METIS_PartGraphKway (&n, &ncon, xadj, adjncy, 
  342
+                        vwgt, params.vsize, adjwgt, 
  343
+                        &nparts, NULL, NULL, options, &edgecut, part));
341 344
         } else {
342 345
             mxAssert(0,"unhandled case");
343 346
         }
@@ -358,6 +361,8 @@ void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
358 361
 
359 362
     } else if (strcasecmp(funcname,"EdgeND")==0 || 
360 363
                strcasecmp(funcname,"NodeND")==0) {
  364
+        
  365
+        mexWarnMsgTxt("untested code");
361 366
 
362 367
         /* Figure out values for options */
363 368
         if (nrhs >= 3) {
@@ -369,7 +374,13 @@ void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
369 374
         iperm = (idx_t*) mxCalloc (n, sizeof(idx_t));
370 375
 
371 376
         /* Do the call */
372  
-        METIS_NodeND (&n, xadj, adjncy, NULL, options, perm, iperm);
  377
+        if (strcasecmp(funcname,"EdgeND")==0) {
  378
+            options[METIS_OPTION_IPTYPE] = METIS_IPTYPE_EDGE;
  379
+            METIS_NodeND (&n, xadj, adjncy, NULL, options, perm, iperm);
  380
+        } else {
  381
+            options[METIS_OPTION_IPTYPE] = METIS_IPTYPE_NODE;
  382
+            METIS_NodeND (&n, xadj, adjncy, NULL, options, perm, iperm);
  383
+        }
373 384
 
374 385
         /* Figure out output values */
375 386
         if (nlhs >= 1) {
@@ -424,3 +435,69 @@ void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
424 435
     }
425 436
 }
426 437
 
  438
+
  439
+
  440
+/*************************************************************************
  441
+* Given a graph, find a node separator bisecting it (roughly). The number
  442
+* of bisector nodes is returned in *nbnd, and the nodes themselves in the
  443
+* array bnds, which should already be allocated to have enough room.
  444
+**************************************************************************/
  445
+#if 0
  446
+void METIS_NodeBisect(idx_t nvtxs, idx_t *xadj, idx_t *adjncy,
  447
+                      idx_t *vwgt, idx_t *adjwgt, idx_t wgtflag,
  448
+                      idx_t *options, idx_t *nbnd, idx_t *bnds, double unbalance)
  449
+{
  450
+  idx_t i, j, tvwgt, tpwgts2[2];
  451
+  GraphType graph;
  452
+  CtrlType ctrl;
  453
+  idx_t *label, *bndind;
  454
+
  455
+  if (options[0] == 0) {  /* Use the default parameters */
  456
+    ctrl.CType   = ONMETIS_CTYPE;
  457
+    ctrl.IType   = ONMETIS_ITYPE;
  458
+    ctrl.RType   = ONMETIS_RTYPE;
  459
+    ctrl.dbglvl  = ONMETIS_DBGLVL;
  460
+  }
  461
+  else {
  462
+    ctrl.CType   = options[OPTION_CTYPE];
  463
+    ctrl.IType   = options[OPTION_ITYPE];
  464
+    ctrl.RType   = options[OPTION_RTYPE];
  465
+    ctrl.dbglvl  = options[OPTION_DBGLVL];
  466
+  }
  467
+  ctrl.nseps = 5;    /* Take the best of 5 separators */
  468
+  ctrl.optype = OP_ONMETIS;
  469
+  ctrl.CoarsenTo = 50;
  470
+
  471
+  IFSET(ctrl.dbglvl, DBG_TIME, InitTimers(&ctrl));
  472
+  IFSET(ctrl.dbglvl, DBG_TIME, starttimer(ctrl.TotalTmr));
  473
+
  474
+  SetUpGraph(&graph, OP_ONMETIS, nvtxs, 1, xadj,adjncy,vwgt,adjwgt,wgtflag);
  475
+
  476
+  /* Determine the weights of the partitions */
  477
+  tvwgt = idxsum(nvtxs, graph.vwgt);
  478
+  tpwgts2[0] = tvwgt/2;
  479
+  tpwgts2[1] = tvwgt-tpwgts2[0];
  480
+
  481
+  ctrl.maxvwgt = (1.5*tvwgt)/ctrl.CoarsenTo;
  482
+
  483
+  InitRandom(-1);
  484
+
  485
+  AllocateWorkSpace(&ctrl, &graph, 2);
  486
+
  487
+  MlevelNodeBisectionMultiple (&ctrl, &graph, tpwgts2, unbalance);
  488
+
  489
+  IFSET(ctrl.dbglvl, DBG_SEPINFO, printf("Nvtxs: %6d, [%6d %6d %6d]\n", graph.nvtxs, graph.pwgts[0], graph.pwgts[1], graph.pwgts[2]));
  490
+
  491
+  /* Now indicate the vertex separator */
  492
+  *nbnd = graph.nbnd;
  493
+  bndind = graph.bndind;
  494
+  label = graph.label;
  495
+  for (i = 0; i < *nbnd; ++i) 
  496
+    bnds[i] = label[bndind[i]];
  497
+
  498
+  IFSET(ctrl.dbglvl, DBG_TIME, stoptimer(ctrl.TotalTmr));
  499
+  IFSET(ctrl.dbglvl, DBG_TIME, PrintTimers(&ctrl));
  500
+
  501
+  FreeWorkSpace(&ctrl, &graph);
  502
+}
  503
+#endif
5  test_main.m
... ...
@@ -0,0 +1,5 @@
  1
+function test_main
  2
+A = spaugment(ones(5)); A(1,10) = 1; A(10,1) = 1; A(5,6) = 1; A(6,5) = 1;
  3
+map = metismex('PartGraphRecursive',sparse(A),2);
  4
+map2 = metismex('PartGraphRecursive',sparse(A),2,struct('seed',2));
  5
+assert(any(map ~= map2));

0 notes on commit abf009e

Please sign in to comment.
Something went wrong with that request. Please try again.