From 2e094554784cd53632805a6e833fd2e31357c955 Mon Sep 17 00:00:00 2001
From: Marco van Oort <marcovoort@gmail.com>
Date: Thu, 27 Oct 2016 15:06:14 +0200
Subject: [PATCH] Modify interface of the MondriaanOpt command to be more in
 line with the other Mondriaan* commands

---
 docs/USERS_GUIDE.html           | 10 ++--
 docs/USERS_GUIDE_OPT.html       | 94 ++++++++++++++++++++++++---------
 src/MondriaanOpt/MondriaanOpt.c | 11 ++--
 src/MondriaanOpt/errors.c       | 39 ++++++++++----
 src/MondriaanOpt/options.c      | 34 ++++++++----
 src/MondriaanOpt/options.h      |  2 +-
 src/MondriaanOpt/solution.c     |  6 ++-
 tools/MatlabMondriaanOpt.c      |  2 +-
 tools/mondriaanOpt.m            |  4 ++
 9 files changed, 146 insertions(+), 56 deletions(-)

diff --git a/docs/USERS_GUIDE.html b/docs/USERS_GUIDE.html
index 5d95360..8b57322 100644
--- a/docs/USERS_GUIDE.html
+++ b/docs/USERS_GUIDE.html
@@ -22,6 +22,7 @@
 <div><a href="#libr">Library use</a></div>
 <div><a href="MATLAB.html">MATLAB</a></div>
 <div><a href="HYPERGRAPH.html">Hypergraphs</a></div>
+<div><a href="USERS_GUIDE_OPT.html">MondriaanOpt</a></div>
 <div><a href="#prof">Profiling</a></div>
 <div><a href="#dev">Developers</a></div>
 <div><a href="#moar">More...</a></div>
@@ -70,9 +71,8 @@ Go inside the directory <tt>Mondriaan4</tt> and type
 <li><tt>% make</tt></li>
 </ul>
 <p>
-This will compile the Mondriaan library, tools included with
-the Mondriaan library, and all 102 unit tests of the library
-with the default options as given in <tt>mondriaan.mk</tt>.
+This will compile the Mondriaan library, the <a href="USERS_GUIDE_OPT.html">MondriaanOpt</a> library and
+tools included with the Mondriaan library.
 
 After compilation the include files are located in <tt>Mondriaan4/src/include</tt>,
 the compiled library in <tt>Mondriaan4/src/lib</tt>,
@@ -790,14 +790,14 @@ Chapter 12 of Combinatorial Scientific Computing, Chapman and Hall/CRC, pp. 321-
 
 <hr>
 <p>
-Last updated: September 27, 2016.<br><br>
+Last updated: October 27, 2016.<br><br>
 June 9, 2009 by Rob Bisseling,<br>
 December 2, 2010 by Bas Fagginger Auer,<br>
 December 10, 2010 by A. N. Yzelman,<br>
 March 27, 2012 by Bas Fagginger Auer,<br>
 April 18, 2013 by Dani&euml;l M. Pelt,<br>
 August 29, 2013 by Rob Bisseling and Bas Fagginger Auer,<br>
-September 27, 2016 by Marco van Oort.<br><br>
+October 27, 2016 by Marco van Oort.<br><br>
 To <a href="http://www.staff.science.uu.nl/~bisse101/Mondriaan">
 the Mondriaan package home page</a>.</p>
 
diff --git a/docs/USERS_GUIDE_OPT.html b/docs/USERS_GUIDE_OPT.html
index 10243d5..e6a6705 100644
--- a/docs/USERS_GUIDE_OPT.html
+++ b/docs/USERS_GUIDE_OPT.html
@@ -14,6 +14,7 @@
 <h2>User's guide MondriaanOpt</h2>
 
 <div id="top">
+<div><a href="USERS_GUIDE.html">&laquo; Mondriaan</a></div>
 <div><a href="#inst">Installing</a></div>
 <div><a href="#outp">Output</a></div>
 <div><a href="#opts">Options</a></div>
@@ -30,30 +31,44 @@ This offline version is bundled with the software for your convenience.
 </p>
 <hr>
 
+<p>
+Whereas Mondriaan uses heuristics to obtain good partitionings for sparse matrix-vector multiplication for any number of processors,
+MondriaanOpt will calculate an actual optimal solution for this partitioning problem with 2 processors. More precisely, it will
+calculate a partitioning with minimum volume among all solutions that obey the imbalance constraint.
+</p>
+
+<p>
+A database with already solved problems with use of MondriaanOpt can be found <a href="http://www.staff.science.uu.nl/~bisse101/Mondriaan/Opt/">online</a>.
+</p>
+
 <h3><a name="inst">How to install MondriaanOpt</a></h3>
 <p>
 MondriaanOpt comes packaged with the Mondriaan software. Refer to <a href="./USERS_GUIDE.html">this page</a> for
 instructions on using Mondriaan. MondriaanOpt is automatically compiled when you compile Mondriaan. The executable
 is then available at <tt>tools/MondriaanOpt</tt>.
 </p>
+
+<h3><a name="run">How to run MondriaanOpt</a></h3>
 <p>
-Whereas Mondriaan uses heuristics to obtain good partitionings for sparse matrix-vector multiplication for any number of processors,
-MondriaanOpt will calculate an actual optimal solution for this partitioning problem with 2 processors. More precisely, it will
-calculate a partitioning with minimum volume among all solutions that obey the imbalance constraint.
+The MondriaanOpt program has the following interface:
+<ul><li><tt>% ./tools/MondriaanOpt matrix [P [eps]] [options]</tt></li></ul>
+One, two or three parameters may be passed, after which further options may be given.
+Either [eps], -e or -k must be passed, and it is advised to pass -v (see <a href="#opts">options</a>).
 </p>
 
-<h3><a name="run">How to run MondriaanOpt</a></h3>
 <p>
-Go inside the directory <tt>Mondriaan4</tt> and type
+Some equivalent examples are:
 </p>
 <ul>
-<li><tt>% cd tools</tt></li>
-<li><tt>% ./MondriaanOpt -m ../tests/arc130.mtx -e 0.03 -v 20</tt></li>
+	<li><tt>% ./tools/MondriaanOpt tests/arc130.mtx 2 0.03 -v 17</tt></li>
+	<li><tt>% ./tools/MondriaanOpt tests/arc130.mtx -e 0.03 -v 17</tt></li>
+	<li><tt>% ./tools/MondriaanOpt tests/arc130.mtx -k 660 -v 17</tt></li>
 </ul>
+
 <p>
-if you want to partition the <tt>arc130.mtx</tt> matrix (Matrix Market file format)
+The above examples partition the <tt>arc130.mtx</tt> matrix (Matrix Market file format)
 for 2 processors with at most 3% load imbalance, knowing that solutions must exist with
-volume at most 20. The matrix should be the full relative path; <em>in the above example 
+volume at most 17. The matrix should be the full relative path; <em>in the above example 
 output is saved in the Mondriaan tests folder</em> (<tt>../tests/</tt>).
 </p>
 
@@ -89,6 +104,7 @@ containing a visualisation of the partitioning.
 <p><i>
 Here, the free nonzeros of a partitioning are distributed among the two processors in
 such a way that load imbalance is kept at a minimum.
+Note that whenever we write <tt>P</tt> for the number of processors below, it implicitly equals 2.
 </i></p>
 <h4>Distributed matrix (<tt>-P2</tt>)</h4>
 <p> The <tt>MondriaanOpt</tt> program
@@ -134,51 +150,81 @@ and you may not need it.
 containing a visualisation of the partitioning.
 </p>
 
+<h4><u>Output to <tt>stdout</tt>/<tt>stderr</tt></u></h4>
+<p>
+In a succesful run, at the end of execution general statistics are written to <tt>stdout</tt>.
+Also, during such a run, every <tt>2^23 = 8388608</tt> iterations the current depth in the tree is written to <tt>stderr</tt>, in the format <tt>`current depth`/`maximum depth`</tt>.
+Last but not least, every time a new solution is found which improves on the previous solution regarding total volume, a message is written to <tt>stderr</tt> reporting the newly found volume and load distribution in the format <tt>`load P0`, `load P1`, `load Free`</tt>.
+</p>
 
 <h3><a name="opts">Program options</a></h3>
 <p>
-The MondriaanOpt options can be passed in the command line.
-An overview of the options is given below.
+The MondriaanOpt program has the following interface:
+<ul><li><tt>% ./tools/MondriaanOpt matrix [P [eps]] [options]</tt></li></ul>
+One, two or three parameters may be passed, after which further options may be given.
+An overview of the available parameters and options is given below.
 </p>
+<h4>Parameters</h4>
 <table>
 	<thead>
 		<tr>
-			<th>Option</th>
-			<th>Value</th>
+			<th>Parameter</th>
 			<th>Description</th>
 		</tr>
 	</thead>
 	<tbody>
 		<tr>
-			<td>-m</td>
 			<td>Matrix file</td>
 			<td><i>Required.</i> The input matrix file in Matrix Market (.mtx) format</td>
 		</tr>
+		<tr>
+			<td>Number of processors</td>
+			<td>Present for consistency with other Mondriaan* commands. This parameter, if given, must be equal to 2.</td>
+		</tr>
+		<tr>
+			<td>Load imbalance</td>
+			<td>The maximum allowed load imbalance</td>
+		</tr>
+	</tbody>
+</table>
+
+<h4>Options</h4>
+<p>
+Apart from the matrix, at least one of [eps], -e or -k must be given, defining the maximum allowed load imbalance.
+</p>
+<table>
+	<thead>
+		<tr>
+			<th>Option</th>
+			<th>Value</th>
+			<th>Description</th>
+		</tr>
+	</thead>
+	<tbody>
 		<tr>
 			<td>-v</td>
 			<td>Volume</td>
-			<td><i>Required.</i> The starting upper bound volume</td>
+			<td>
+				<i>Recommended.</i> The starting upper bound volume.
+				This defaults to <tt>m+n</tt>, with <tt>m</tt> and <tt>n</tt> denoting the dimensions of the matrix to be partitioned.
+				While this is a valid upper bound, you may wish to pass a tighter upper bound to reduce computing time.
+			</td>
 		</tr>
 		<tr>
 			<td>-e</td>
 			<td>Load imbalance</td>
-			<td><i>Required if -k is not passed.</i> The allowed load imbalance</td>
+			<td>The maximum allowed load imbalance</td>
 		</tr>
 		<tr>
 			<td>-k</td>
 			<td>Number of nonzeros</td>
-			<td><i>Required if -e is not passed.</i> The maximum allowed number of nonzeros per part</td>
+			<td>The maximum allowed number of nonzeros per part</td>
 		</tr>
 		<tr>
 			<td>-t</td>
 			<td>Seconds</td>
 			<td>Max running time in seconds</td>
 		</tr>
-		<tr>
-			<td>-r</td>
-			<td>Dumpfile</td>
-			<td>Resume with given dumpfile</td>
-		</tr>
 		<tr>
 			<td>-h</td>
 			<td><i>None</i></td>
@@ -211,8 +257,8 @@ Daniel M. Pelt and Rob H. Bisseling, <i>Journal of Parallel and Distributed Comp
 
 <hr>
 <p>
-Last updated: October 3, 2016.<br><br>
-October 3, 2016 by Marco van Oort.<br><br>
+Last updated: October 27, 2016.<br><br>
+October 27, 2016 by Marco van Oort.<br><br>
 To <a href="http://www.staff.science.uu.nl/~bisse101/Mondriaan">
 the Mondriaan package home page</a>.</p>
 
diff --git a/src/MondriaanOpt/MondriaanOpt.c b/src/MondriaanOpt/MondriaanOpt.c
index a3fde9e..a86fb5e 100644
--- a/src/MondriaanOpt/MondriaanOpt.c
+++ b/src/MondriaanOpt/MondriaanOpt.c
@@ -39,16 +39,19 @@ int main(int argc,char **argv){
 
     /* Output time used */
     printf("Time taken: %lf s\n",opt.time);
-
-    /* Output final volume upper bound to stdout */
-    printf("%d\n",sol.maxvol);
     
     if(sol.maxvol < opt.maxvol) {
+        /* A solution has been found */
+        /* Output final volume upper bound to stdout */
+        printf("Final volume: %d\n",sol.maxvol);
+        
         /* Convert to other file formats */
         printConverted(&opt);
     }
     else {
-        printf("No solution with a volume lower than %d exists!\n", opt.maxvol);
+        /* No solution found. */
+        /* Subtract 1 from maxvol, as maxvol contains 'the volume we want to improve', while we want to print 'the upper bound'. */
+        printf("No solution with a volume at most %d exists!\n", opt.maxvol-1);
     }
     
     exit (EXIT_SUCCESS);
diff --git a/src/MondriaanOpt/errors.c b/src/MondriaanOpt/errors.c
index 93d2ff4..a6f9575 100644
--- a/src/MondriaanOpt/errors.c
+++ b/src/MondriaanOpt/errors.c
@@ -7,28 +7,45 @@ void exitwitherror(unsigned int err){
     if(err==0){
         /* Options error, output program usage */
         fprintf(stderr,"MondriaanOpt - written by Daan Pelt and Rob Bisseling (2015)\n");
-        fprintf(stderr,"\nInvalid options are given...\nUsage:\n\n");
-        fprintf(stderr,"  ./program -m \"matrix file\" -e \"load imbalance\" -v \"volume\"\n");
-        fprintf(stderr," or \n");
-        fprintf(stderr,"  ./program -m \"matrix file\" -k \"number of nonzeros\" -v \"volume\"\n\n");
+        fprintf(stderr,"\nInvalid options are given...\nUsage:\n");
+        fprintf(stderr,"  ./tools/MondriaanOpt matrix [P [eps]] [options]\n\n");
+        
+        fprintf(stderr,"Either [eps], -e or -k must be passed, and it is advised to pass -v.\n");
         fprintf(stderr,"Use -h option for more help\n");
         fprintf(stderr,"\n");
         exit(EXIT_SUCCESS);
     }else if(err==1){
         /* Help asked */
         fprintf(stderr,"MondriaanOpt - written by Daan Pelt and Rob Bisseling (2015)\n");
-        printf("\nProgram to find optimal matrix bipartitioning.\n\nRequired options:\n");
-        printf("  -m \"matrix file\"        : the input matrix file in Matrix Market (.mtx) format\n");
+        printf("\nProgram to find optimal matrix bipartitioning.\n\nUsage:\n");
+        printf("  ./tools/MondriaanOpt matrix [P [eps]] [options]\n\n");
+        
+        printf("One, two or three parameters may be passed, after which further options may be given.\n");
+        printf("Either [eps], -e or -k must be passed, and it is advised to pass -v (see below).\n\n");
+        
+        printf("Parameters:\n");
+        printf("  matrix                  : the input matrix file in Matrix Market (.mtx) format (may not start with a dash (-))\n");
+        printf("  P                       : the number of processors. This must equal 2; this option is present for consistency with the other Mondriaan* commands\n");
+        printf("  eps                     : the maximum allowed load imbalance\n\n");
+        
+        printf("Further options:\n");
         printf("  -v \"volume\"             : the starting upper bound volume\n");
-        printf("\nAlso, it is required to pass either of the following:\n");
-        printf("  -e \"load imbalance\"     : the allowed load imbalance\n");
+        printf("  -e \"load imbalance\"     : the maximum allowed load imbalance\n");
         printf("  -k \"number of nonzeros\" : the maximum allowed number of nonzeros per part\n");
-        printf("\nFurther options:\n");
         printf("  -t \"seconds\"            : max running time in seconds\n");
-        printf("  -r \"dumpfile\"           : resume with given dumpfile\n");
         printf("  -h                      : show this help\n");
-        printf("  -svg                    : Write visualisations of the partitioning to .svg files\n");
+        printf("  -svg                    : Write visualisations of the partitioning to .svg files\n\n");
+        
+        printf("Apart from the matrix, at least one of [eps], -e or -k must be given, defining the maximum allowed load imbalance.\n");
+        printf("The default value for the initial upper bound on the communication volume is m+n (m and n being the dimensions of the matrix),\n");
+        printf("but it is strongly recommended to pass a better upper bound (-v) if available, to reduce computing time.\n\n");
+        
+        printf("Equivalent examples:\n");
+        printf("  ./tools/MondriaanOpt tests/arc130.mtx 2 0.03 -v 17\n");
+        printf("  ./tools/MondriaanOpt tests/arc130.mtx -e 0.03 -v 17\n");
+        printf("  ./tools/MondriaanOpt tests/arc130.mtx -k 660 -v 17\n");
         printf("\n");
+        
         exit(EXIT_SUCCESS);
     }else if(err==2){
         /* Not enough memory */
diff --git a/src/MondriaanOpt/options.c b/src/MondriaanOpt/options.c
index 8962eb2..960f3ed 100644
--- a/src/MondriaanOpt/options.c
+++ b/src/MondriaanOpt/options.c
@@ -28,16 +28,32 @@ char readoptions(struct options *o, int c, char **v){
     o->maxruntime=0.;
     o->nbranches=0; /* number of branches traversed */
     o->SVG=SVGNo;
+    o->maxvol = -1;
+    
+    while(i<c && v[i][0] != '-') {
+        if(i == 1) {
+            /* Read matrix filename */
+            sprintf(o->fn,"%s",v[i]);
+            req[0]=TRUE;
+        }
+        if(i == 2) {
+            if(strcmp(v[i], "2") != 0) {
+                exitwitherror(0);
+            }
+        }
+        if(i == 3) {
+            o->eps = atof(v[i]);
+            o->epsset = TRUE;
+            req[1]=TRUE;
+        }
+        
+        i++;
+    }
+    
 
     /* Read while there are options left */
     while(i<c){
-        if(strcmp(v[i],"-m")==0){
-            /* Matrix file */
-            if(i==c-1) exitwitherror(0);
-            sprintf(o->fn,"%s",v[i+1]);
-            req[0]=TRUE;
-            i++;
-        }else if(strcmp(v[i],"-t")==0){
+        if(strcmp(v[i],"-t")==0){
             /* Max running time in seconds */
             if(i==c-1) exitwitherror(0);
             o->maxruntime = atof(v[i+1]);
@@ -59,8 +75,8 @@ char readoptions(struct options *o, int c, char **v){
         }else if(strcmp(v[i],"-v")==0){
             /* Starting upper bound on volume, e.g. MIN(m,n)+1 for an m by n matrix  */
             if(i==c-1) exitwitherror(0);
-            o->maxvol = atoi(v[i+1]);
-            req[2]=TRUE;
+            /* We add +1, to change from 'upper bound' to 'the value we want to improve upon' */
+            o->maxvol = atoi(v[i+1])+1;
             i++;
         }else if(strcmp(v[i],"-h")==0){
             /* Get help */
diff --git a/src/MondriaanOpt/options.h b/src/MondriaanOpt/options.h
index df5b473..b310874 100644
--- a/src/MondriaanOpt/options.h
+++ b/src/MondriaanOpt/options.h
@@ -5,7 +5,7 @@
 #include <sys/time.h>
 
 #define MAXFNSIZE 64
-#define CUR_REQ_OPTIONS 3
+#define CUR_REQ_OPTIONS 2
 #define TRUE 1
 #define FALSE 0
 
diff --git a/src/MondriaanOpt/solution.c b/src/MondriaanOpt/solution.c
index a41a85d..664750b 100644
--- a/src/MondriaanOpt/solution.c
+++ b/src/MondriaanOpt/solution.c
@@ -65,10 +65,14 @@ void initsolution(const struct mat *a, struct solution *s, struct options *o){
     s->max1 = o->k;
 
     /* Set volume upper bound */
+    if(o->maxvol == -1) {
+        o->maxvol = a->m + a->n;
+        fprintf(stderr, "Warning: With the default upper bound on the communication volume, m+n, the program may take long to complete. Consider passing a better upper bound with the -v option.\n");
+    }
     s->maxvol = o->maxvol;
 
     /* Set matrix name */
-    s->matname = basename(o->fn);
+    s->matname = o->fn; /* basename(o->fn) */
 
     /* Set start time of solution process */
     time(&(s->starttime));
diff --git a/tools/MatlabMondriaanOpt.c b/tools/MatlabMondriaanOpt.c
index 7a5ba6b..4e572f7 100644
--- a/tools/MatlabMondriaanOpt.c
+++ b/tools/MatlabMondriaanOpt.c
@@ -89,7 +89,7 @@ int DoMondriaanOpt(struct sparsematrix *A, struct solution *sol, struct mat *a,
 	sprintf(Options.fn, "MatlabMex.mtx");
 	Options.eps = Imbalance;
 	Options.epsset = TRUE;
-	Options.maxvol = Volume;
+	Options.maxvol = Volume+1; /* We add +1, to change from 'upper bound' to 'the volume we want to improve upon' */
 	
 	/* Initialise solution */
 	initsolution(a,sol,&Options);
diff --git a/tools/mondriaanOpt.m b/tools/mondriaanOpt.m
index c29b738..2a6160e 100644
--- a/tools/mondriaanOpt.m
+++ b/tools/mondriaanOpt.m
@@ -43,6 +43,10 @@ function [I, s] = mondriaanOpt(A, Imbalance, Volume)
     comVol = MatlabMondriaanOpt(A, Imbalance, Volume);
     elapsedTime = toc;
     
+    if(comVol > Volume)
+        throw(MException('mondriaanOpt:NoSol', ['No solution with a volume at most ' num2str(Volume) ' exists!']));
+    end
+    
     % Read computed partitioning from disk
     I = mmread('MatlabMex.mtx-I2f');
     
-- 
GitLab