Browse Source

Add: Application to write Sn and Cn as well as application to search for groups of a given order

Sebastian Kreisel 1 year ago
parent
commit
203d284b43

+ 1 - 0
TODO.txt

@@ -3,6 +3,7 @@
 * gen: Think about truly binom-incremental genSet functions, i.e. that only
        progress one binom shift at a time no matter if we find a genSet or not
 * gen: Make sure that all functions work with a genSet that is 0xffff-terminated
+* gen: Think about automatically truncing the genSet, esp. in alloc version
 * all: Make independent of neutral == 0 (elementOrder, ...)
 
 

+ 108 - 0
src/application/group_library.c

@@ -1,6 +1,10 @@
 #include "group_library.h"
 
 #include "../group/group_io.h"
+#include "../group/group_gen.h"
+#include "../group/group_common.h"
+
+#include <elfc_random.h>
 
 #include <string.h>
 #include <stdio.h>
@@ -8,6 +12,54 @@
 #include <dirent.h>
 
 
+// ---------------------------------------------------------------------------
+// Writing constructable groups
+// ---------------------------------------------------------------------------
+
+//TODO: Maybe get an indexed copy before making expensive calculations
+bool app_writeGroup(char *path, Group *group, char *name)
+{
+  GroupMetaInfo meta;
+  memset(meta.name, '\0', GROUP_META_NAME_LEN); // avoid garbage in meta.name
+  memset(meta.minGenSet, 0xffff, GROUP_META_MINGENSET_LEN * sizeof(u16));
+  strcpy(meta.name, name);
+  meta.order = group_order(group);
+  meta.isCommutative = group_isCommutative(group);
+  Vecu16 *minGenSet = group_minGeneratingSet_alloc(group);
+  group_truncGeneratedSet(minGenSet, 1);
+  meta.minGenSetSize = minGenSet->size;
+  vecu16_copyIntoArray(meta.minGenSet, minGenSet, minGenSet->size);
+  vecu16_free(minGenSet);
+  return group_writeToFile(group, meta, path);
+}
+
+bool app_writeGroupSn(char *path, u32 n)
+{
+  char name[16];
+  memset(name, 0, 16);
+  sprintf(name, "S%u", n);
+  Group *group = group_createSn_alloc(n);
+  bool ok = app_writeGroup(path, group, name);
+  group_free(group);
+  return ok;
+}
+
+bool app_writeGroupCn(char *path, u32 n)
+{
+  char name[16];
+  memset(name, 0, 16);
+  sprintf(name, "C%u", n);
+  Group *group = group_createCn_alloc(n);
+  bool ok = app_writeGroup(path, group, name);
+  group_free(group);
+  return ok;
+}
+
+
+// ---------------------------------------------------------------------------
+// Read group files
+// ---------------------------------------------------------------------------
+
 Vecptr *app_listGroupFiles_alloc(char *path, u16 order, i32 isCommutative)
 {
   DIR *dir = opendir(path);
@@ -53,3 +105,59 @@ Vecptr *app_listGroupFiles_alloc(char *path, u16 order, i32 isCommutative)
   closedir(dir);
   return fileNames;
 }
+
+
+// --------------------------------------------------------------------------
+// Search for groups
+// --------------------------------------------------------------------------
+
+Group *app_searchForGroup_alloc(Group *parent,
+                                u16 order, i32 isCommutative,
+                                u32 genSizeLower, u32 genSizeUpper,
+                                u32 iter)
+{
+  u16 n = group_order(parent);
+  Vecu16 *set = vecu16_alloc(genSizeUpper);
+  Vecu16 *res = vecu16_alloc(n);
+  Vecu16 *util = vecu16_alloc(n);
+  Vecu16 *orderVec = group_getOrderVector_alloc(parent);
+  rand_setSeed(41);
+  for(i32 i = 0; i < iter; i++) {
+    u32 numGen = rand_getU32InRange(genSizeLower, genSizeUpper);
+    vecu16_fill(set, 0xffff);
+    for(i32 j = 0; j < numGen; j++) {
+      u16 randEle = 0xffff;
+      bool validEle = 0;
+      while(!validEle) {
+        randEle = rand_getU32InRange(1, n - 1);
+        validEle = !vecu16_contains(set, randEle, 0);
+        if(!validEle) {
+          continue;
+        }
+        // Check prime factor condition
+        u16 l = group_elementOrder(parent, randEle);
+        validEle = order % l == 0;
+      }
+      *vecu16_at(set, j) = randEle;
+    }
+    //printf("Generating with set ...\n");
+    //vecu16_print(set);
+    bool ok = group_generateFromConstr_noalloc(parent, set, res, util,
+                                               orderVec, order);
+    if(ok) {
+      group_truncGeneratedSet(res, 0);
+      u32 m = 0;
+      vecu16_indexOf(res, 0xffff, &m, 0);
+      if(m == order) {
+        printf("%05u :: %u :: Found subgrp of order %u.\n", i + 1, numGen, m);
+      }
+    } else {
+
+    }
+  }
+  vecu16_free(orderVec);
+  vecu16_free(util);
+  vecu16_free(res);
+  vecu16_free(set);
+  return 0;
+}

+ 26 - 0
src/application/group_library.h

@@ -1,10 +1,26 @@
 #ifndef GROUP_LIBRARY
 #define GROUP_LIBRARY
 
+#include "../group/group.h"
+
 #include <elfc_common.h>
 #include <elfc_vecptr.h>
 
 
+// --------------------------------------------------------------------------
+// Writing constructable groups
+// --------------------------------------------------------------------------
+
+bool app_writeGroup(char *path, Group *group, char *name);
+
+bool app_writeGroupSn(char *path, u32 n);
+bool app_writeGroupCn(char *path, u32 n);
+
+
+// --------------------------------------------------------------------------
+// Read group files
+// --------------------------------------------------------------------------
+
 /*
  * Get a list of all group file names in directory path. Allocates vecptr and
  * the contained strings
@@ -15,4 +31,14 @@
 Vecptr *app_listGroupFiles_alloc(char *path, u16 order, i32 isCommutative);
 
 
+// --------------------------------------------------------------------------
+// Search for groups
+// --------------------------------------------------------------------------
+
+Group *app_searchForGroup_alloc(Group *parent,
+                                u16 order, i32 isCommutative,
+                                u32 genSizeLower, u32 genSizeUpper,
+                                u32 iter);
+
+
 #endif

+ 10 - 0
src/group/group.c

@@ -109,6 +109,16 @@ u16 group_elementOrderi(Group *group, u16 ind)
   return ord;
 }
 
+Vecu16 *group_getOrderVector_alloc(Group *group)
+{
+  u16 n = group_order(group);
+  Vecu16 *orderVec = vecu16_alloc(n);
+  for(i32 i = 0; i < n; i++) {
+    *vecu16_at(orderVec, i) = group_elementOrderi(group, i);
+  }
+  return orderVec;
+}
+
 Mapu16 *group_orderDist_alloc(Group *group)
 {
   u32 n = group_order(group);

+ 1 - 0
src/group/group.h

@@ -39,6 +39,7 @@ bool group_isCyclic(Group *group);
 
 u16 group_elementOrder(Group *group, u16 ele);
 u16 group_elementOrderi(Group *group, u16 ind);
+Vecu16 *group_getOrderVector_alloc(Group *group);
 
 Mapu16 *group_orderDist_alloc(Group *group);
 

+ 52 - 0
src/group/group_gen.c

@@ -65,6 +65,58 @@ void group_generateFrom_noalloc(Group *group,
   }
 }
 
+bool group_generateFromConstr_noalloc(Group *group,
+                                      Vecu16 *set,
+                                      Vecu16 *res,
+                                      Vecu16 *util,
+                                      Vecu16 *orderVec,
+                                      u32 subgroupOrder)
+{
+  bool isCommu = group_isCommutative(group);
+  vecu16_fill(res, 0xffff);
+  // fill util with the inds of elements in set, copy elements from set to res
+  u16 ele;
+  u32 ind = -1;
+  i32 num = 0;
+  for(i32 i = 0; i < set->size; i++) {
+    ele = *vecu16_at(set, i);
+    if(ele == 0xffff) {
+      break;
+    }
+    num++;
+    vecu16_indexOf(group->set, ele, &ind, 0);
+    *vecu16_at(res, ind) = ele;
+    *vecu16_at(util, i) = ind;
+  }
+  i32 prevNum = 0;
+  u16 a, b, c;
+  // Calculate the product of all elements in util with each other and check
+  // if we got any new. If yes, repeat, if not we are done
+  while(prevNum != num) {
+    prevNum = num;
+    for(i32 i = 0; i < num; i++) {
+      a = *vecu16_at(util, i);
+      i32 startJ = isCommu ? i : 0;
+      for(i32 j = startJ; j < num; j++) {
+        b = *vecu16_at(util, j);
+        c = group_opi(group, a, b);
+        if(*vecu16_at(res, c) == 0xffff) { // is this prod new in res?
+          if(num >= subgroupOrder ||
+             subgroupOrder % *vecu16_at(orderVec, c) != 0) {
+            vecu16_fill(res, 0xffff);
+            return 0;
+          }
+          ele = *vecu16_at(group->set, c);
+          *vecu16_at(res, c) = ele;
+          *vecu16_at(util, num) = c;
+          num++;
+        }
+      }
+    }
+  }
+  return 1;
+}
+
 Vecu16 *group_generateFrom_alloc(Group *group, Vecu16 *set) {
   u16 n = group_order(group);
   Vecu16* res = vecu16_alloc(n);

+ 16 - 0
src/group/group_gen.h

@@ -22,6 +22,22 @@ void group_generateFrom_noalloc(Group *group,
                                 Vecu16 *res,   // result
                                 Vecu16 *util); // fills up, unordered
 
+/*
+ * Slightly modified version to abort early if a generated (sub)group of
+ * subgroupOrder is impossible to reach based on the amount of resulting
+ * elements or elementOrder which does not divide subgroupOrder. To this end
+ * a vector containing precomputed element orders must be supplied to save
+ * expensive and redundant computation. Same indexing as group->set.
+ *
+ * Returns 0 if subgroupOrder could not be attained and fills res with 0xffff
+ * Returns 1 otherwise with similar res as above
+ */
+bool group_generateFromConstr_noalloc(Group *group,
+                                      Vecu16 *set,
+                                      Vecu16 *res,
+                                      Vecu16 *util,
+                                      Vecu16 *orderVec, // precomputed ele ords
+                                      u32 subgroupOrder);
 
 /*
  * Returns a newly allocated array containing the result of generating from set

+ 2 - 2
src/group/group_io.c

@@ -118,8 +118,8 @@ i32 group_sprintFileMeta(char *buf)
   struct tm tm = *localtime(&t);
   i32 offs = 0;
   offs += sprintf(buf + offs, "# Version: %s\n", VERSION);
-  offs += sprintf(buf + offs, "# File Created: %d-%d-%d", tm.tm_year + 1900,
-                  tm.tm_mon + 1, tm.tm_mday);
+  offs += sprintf(buf + offs, "# File Created: %d-%02d-%02d",
+                  tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
   return offs;
 }
 

+ 15 - 1
src/main.c

@@ -16,6 +16,7 @@
 
 #include "application/group_library.h"
 
+i32 main_10();
 i32 main_9();
 i32 main_8();
 i32 main_7();
@@ -28,7 +29,20 @@ i32 main_1();
 
 i32 main()
 {
-  return main_9();
+  return main_10();
+}
+
+i32 main_10()
+{
+  Group *group =
+    group_readGroupFromFile_alloc("./grplib/05040n_ec6eb6f39e278625.txt");
+  if(group == 0) {
+    return 0;
+  }
+  // 7! = 2 * 2 * 2 * 2 * 3 * 3 * 5 * 7
+  app_searchForGroup_alloc(group, 2 * 2 * 2 * 2, 0, 2, 3, 90000);
+  group_free(group);
+  return 0;
 }
 
 i32 main_9()