chiark / gitweb /
introduce progress_eol and make stderr line buffered
[matchsticks-search.git] / main.c
diff --git a/main.c b/main.c
index 3a7984dc62a636d1e7183bbbbeb9c5565ebdc7ce..a81687172b545275b1c5b10d1c27c8c14bc78873 100644 (file)
--- a/main.c
+++ b/main.c
@@ -27,6 +27,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
+#include <unistd.h>
 #include <stdbool.h>
 #include <inttypes.h>
 
@@ -88,6 +89,13 @@ static AdjWord *best_adjmatrix;
 
 static unsigned printcounter;
 
+static int ncpus = 1;
+
+static void progress_eol(void) {
+  fprintf(stderr,"        \r");
+  fflush(stderr);
+}
+
 static AdjWord *xalloc_adjmatrix(void) {
   return xmalloc(sizeof(*adjmatrix)*n);
 }
@@ -96,6 +104,7 @@ static void prep(void) {
   adjall = ~((~(AdjWord)0) << m);
   adjmatrix = xalloc_adjmatrix();
   glp_term_out(GLP_OFF);
+  setlinebuf(stderr);
 }
 
 static AdjWord one_adj_bit(int bitnum) {
@@ -109,35 +118,19 @@ static int count_set_adj_bits(AdjWord w) {
   return total;
 }
 
-static void optimise(int doprint) {
-  /* Consider the best answer (if any) for a given adjacency matrix */
-  glp_prob *prob = 0;
-  int i, j, totalfrags;
+#define PRINTF(...) if (!doprint) ; else fprintf(stderr, __VA_ARGS__)
 
-  /*
-   * Up to a certain point, optimise() can be restarted.  We use this
-   * to go back and print the debugging output if it turns out that we
-   * have an interesting case.  The HAVE_PRINTED macro does this: its
-   * semantics are to go back in time and make sure that we have
-   * printed the description of the search case.
-   */
-#define HAVE_PRINTED ({                                                \
-      if (!doprint) { doprint = 1; goto retry_with_print; }    \
-    })
- retry_with_print:
-  if (prob) {
-    glp_delete_prob(prob);
-    prob = 0;
-  }
+static int totalfrags;
 
-#define PRINTF if (!doprint) ; else printf /* bodgy */
+static bool preconsider_ok(int nwords, bool doprint) {
+  int i;
 
   PRINTF("%2d ", maxhamweight);
 
   bool had_max = 0;
-  for (i=0, totalfrags=0; i<n; i++) {
+  for (i=0, totalfrags=0; i<nwords; i++) {
     int frags = count_set_adj_bits(adjmatrix[i]);
-    had_max += (frags == maxhamweight);
+    had_max += (frags >= maxhamweight);
     totalfrags += frags;
     PRINTF("%"PRADJ" ", adjmatrix[i]);
     double maxminsize = (double)m / frags;
@@ -154,6 +147,36 @@ static void optimise(int doprint) {
     PRINTF(" nomaxham");
     goto out;
   }
+  return 1;
+
+ out:
+  return 0;
+}
+
+static void optimise(bool doprint) {
+  /* Consider the best answer (if any) for a given adjacency matrix */
+  glp_prob *prob = 0;
+  int i, j;
+
+  /*
+   * Up to a certain point, optimise() can be restarted.  We use this
+   * to go back and print the debugging output if it turns out that we
+   * have an interesting case.  The HAVE_PRINTED macro does this: its
+   * semantics are to go back in time and make sure that we have
+   * printed the description of the search case.
+   */
+#define HAVE_PRINTED ({                                                \
+      if (!doprint) { doprint = 1; goto retry_with_print; }    \
+    })
+ retry_with_print:
+  if (prob) {
+    glp_delete_prob(prob);
+    prob = 0;
+  }
+
+  bool ok = preconsider_ok(n, doprint);
+  if (!ok)
+    goto out;
 
   /*
    * We formulate our problem as an LP problem as follows.
@@ -308,14 +331,14 @@ static void optimise(int doprint) {
   best_adjmatrix = xalloc_adjmatrix();
   memcpy(best_adjmatrix, adjmatrix, sizeof(*adjmatrix)*n);
 
-  printf(" BEST        \n");
+  PRINTF(" BEST        \n");
   return;
 
   }
  out:
   if (prob)
     glp_delete_prob(prob);
-  if (doprint) { printf("        \r"); fflush(stdout); }
+  if (doprint) progress_eol();
 }
 
 static void iterate_recurse(int i, AdjWord min) {
@@ -329,6 +352,8 @@ static void iterate_recurse(int i, AdjWord min) {
        adjmatrix[i]++) {
     if (count_set_adj_bits(adjmatrix[i]) > maxhamweight)
       goto again;
+    if (i == 0 && (adjmatrix[i] & (1+adjmatrix[i])))
+      goto again;
 
     iterate_recurse(i+1, adjmatrix[i]);
 
@@ -348,13 +373,8 @@ static void iterate(void) {
   }
 }
 
-int main(int argc, char **argv) {
-  assert(argc==3);
-  n = atoi(argv[1]);
-  m = atoi(argv[2]);
-  prep();
-  iterate();
-  printf("\n");
+static void report(void) {
+  fprintf(stderr, "\n");
   if (best_prob) {
     double min = glp_get_obj_val(best_prob);
     double a[n][m];
@@ -381,5 +401,25 @@ int main(int argc, char **argv) {
     }
   }
   if (ferror(stdout) || fclose(stdout)) { perror("stdout"); exit(-1); }
+}
+int main(int argc, char **argv) {
+  int opt;
+  while ((opt = getopt(argc,argv,"j:")) >= 0) {
+    switch (opt) {
+    case 'j': ncpus = atoi(optarg); break;
+    case '+': assert(!"bad option");
+    default: abort();
+    }
+  }
+  argc -= optind-1;
+  argv += optind-1;
+  assert(argc==3);
+  n = atoi(argv[1]);
+  m = atoi(argv[2]);
+
+  prep();
+  iterate();
+  report();
   return 0;
 }