h48

A prototype for an optimal Rubik's cube solver, work in progress.
git clone https://git.tronto.net/h48
Download | Log | Files | Refs | README | LICENSE

commit 41be2d294e5b6f55d485d635065096f274bc89c1
parent 15fe089b3e625cb6d3a19dee661f4fc9c6224699
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Fri, 27 Sep 2024 16:37:55 +0200

Made table derivation tool more flexible

So apparently my RAM is broken. That took me a while to figure out.
While I get a replacement, I have to restrict myself to a weaker
test for the intermediate tables: instead of deriving them from
the huge table and checking that they are the same, I have to derive
a small h0k2 table from the intermediate ones and check that it is
correct. This is not a 100% proof of correctness, but it is good
enough (and much faster).

Diffstat:
Msrc/solvers/h48/gendata_h48.h | 19+++++++++++--------
Atools/001_derive_h48/derive_h48.c | 33+++++++++++++++++++++++++++++++++
Dtools/001_derive_h48h0k2/derive_h48h0k2.c | 21---------------------
Mtools/expected_distributions.h | 8++++++++
Mtools/tool.h | 33+++++++++++++++++++++------------
5 files changed, 73 insertions(+), 41 deletions(-)

diff --git a/src/solvers/h48/gendata_h48.h b/src/solvers/h48/gendata_h48.h @@ -389,7 +389,7 @@ gendata_h48k2(gendata_h48_arg_t *arg) [8] = 10, [9] = 10, [10] = 10, - [11] = 10 + [11] = 8 }; uint8_t t, *table; @@ -609,14 +609,17 @@ STATIC_INLINE bool gendata_h48k2_dfs_stop(cube_t cube, int8_t depth, h48k2_dfs_arg_t *arg) { uint64_t val; - int64_t coord; + int64_t coord, mutex; int8_t oldval; if (arg->h == 0 || arg->h == 11) { /* We are in the "real coordinate" case, we can stop if this coordinate has already been visited */ coord = coord_h48(cube, arg->cocsepdata, arg->h); + mutex = H48_INDEX(coord, arg->k) % CHUNKS; + pthread_mutex_lock(arg->table_mutex[mutex]); oldval = get_h48_pval(arg->table, coord, arg->k); + pthread_mutex_unlock(arg->table_mutex[mutex]); return oldval <= depth; } else { /* With 0 < k < 11 we do not have a "real coordinate". @@ -747,7 +750,7 @@ gendata_h48_derive(uint8_t h, const void *fulltable, void *buf) /* Technically this step is redundant, except that we need selfsim and crep */ cocsepsize = gendata_cocsep(buf, arg.selfsim, arg.crep); - arg.h48buf = (char *)buf + cocsepsize; + arg.h48buf = (uint8_t *)buf + cocsepsize; h48size = H48_TABLESIZE(h, arg.k) + INFOSIZE; if (buf == NULL) @@ -765,17 +768,17 @@ gendata_h48_derive(uint8_t h, const void *fulltable, void *buf) goto gendata_h48_derive_error; } - h48full = (uint8_t *)fulltable + INFOSIZE; + h48full = (uint8_t *)fulltable + cocsepsize + INFOSIZE; h48derive = (uint8_t *)arg.h48buf + INFOSIZE; memset(h48derive, 0xFF, H48_TABLESIZE(h, arg.k)); memset(arg.info.distribution, 0, INFO_DISTRIBUTION_LEN * sizeof(uint64_t)); - h48max = H48_COORDMAX(11); + h48max = H48_COORDMAX(fulltableinfo.h48h); for (i = 0; i < h48max; i++) { - if (i % INT64_C(1000000000) == 0) + if (i % INT64_C(1000000000) == 0 && i > 0) LOG("Processing %" PRId64 "th coordinate\n", i); - j = i >> (int64_t)(11-h); + j = i >> (int64_t)(fulltableinfo.h48h - h); val_full = get_h48_pval(h48full, i, arg.k); val_derive = get_h48_pval(h48derive, j, arg.k); set_h48_pval(h48derive, j, arg.k, MIN(val_full, val_derive)); @@ -783,7 +786,7 @@ gendata_h48_derive(uint8_t h, const void *fulltable, void *buf) getdistribution_h48(h48derive, arg.info.distribution, h, arg.k); - if (!writetableinfo(&arg.info, buf)) { + if (!writetableinfo(&arg.info, arg.h48buf)) { LOG("gendata_h48_derive: could not write info for table\n"); goto gendata_h48_derive_error; } diff --git a/tools/001_derive_h48/derive_h48.c b/tools/001_derive_h48/derive_h48.c @@ -0,0 +1,33 @@ +#include "../tool.h" + +char *opts_large, *opts_small, *filename_large, *filename_small; + +void run(void) { + derivedata_run(opts_large, opts_small, filename_large, filename_small); +} + +int main(int argc, char **argv) { + char description[256]; + + if (argc < 5) { + fprintf(stderr, + "Error: not enough arguments. Required:\n" + "1. Options for large table\n" + "2. Options for derived table\n" + "3. Filename containing large table\n" + "4. Filename for saving derived table\n"); + return 1; + } + + opts_large = argv[1]; + opts_small = argv[2]; + filename_large = argv[3]; + filename_small = argv[4]; + sprintf(description, "deriving %s from %s\n", opts_small, opts_large); + + nissy_setlogger(log_stderr); + + timerun(run, description); + + return 0; +} diff --git a/tools/001_derive_h48h0k2/derive_h48h0k2.c b/tools/001_derive_h48h0k2/derive_h48h0k2.c @@ -1,21 +0,0 @@ -#include "../tool.h" - -uint64_t expected[21] = { - /* Base value is 8 */ - [0] = 5473562, - [1] = 34776317, - [2] = 68566704, - [3] = 8750867, -}; - -void run(void) { - derivedata_run(0, "tables/h48h0k2_derived", expected); -} - -int main(void) { - nissy_setlogger(log_stderr); - - timerun(run, "benchmark derivedata_h48 h = 0, k = 2"); - - return 0; -} diff --git a/tools/expected_distributions.h b/tools/expected_distributions.h @@ -22,4 +22,12 @@ uint64_t expected_h48[12][9][21] = { [12] = 1673, }, }, + [1] = { + [2] = { + [0] = 6012079, + [1] = 45822302, + [2] = 142018732, + [3] = 41281787, + }, + }, }; diff --git a/tools/tool.h b/tools/tool.h @@ -14,10 +14,11 @@ static double timerun(void (*)(void), const char *); static void getfilename(const char *, const char *, char *); static void writetable(const char *, int64_t, const char *); static int64_t generatetable(const char *, const char *, char **); -static int64_t derivetable(uint8_t, char **); +static int64_t derivetable(const char *, const char *, const char *, char **); static int getdata(const char *, const char *, char **, const char *); static void gendata_run(const char *, const char *, uint64_t[static 21]); -static void derivedata_run(uint8_t, const char *, uint64_t[static 21]); +static void derivedata_run( + const char *, const char *, const char *, const char *); static void log_stderr(const char *str, ...) @@ -125,27 +126,30 @@ generatetable(const char *solver, const char *options, char **buf) } static int64_t -derivetable(uint8_t h, char **buf) +derivetable( + const char *opts_large, + const char *opts_small, + const char *filename_large, + char **buf +) { + uint8_t h; int64_t size, gensize; char *fulltable; - char options[20] = " ;2;20"; /* Only for k = 2 for now */ - options[0] = (char)(h + '0'); /* h = 10 not supported for now */ - - /* Support only b8 for now */ - if (getdata("h48", "11;2;20", &fulltable, "tables/h48h11k2_b8") != 0) { + if (getdata("h48", opts_large, &fulltable, filename_large) != 0) { printf("Error reading full table.\n"); return -1; } - size = nissy_datasize("h48", options); + size = nissy_datasize("h48", opts_small); if (size == -1) { printf("Error getting table size.\n"); free(fulltable); return -1; } + h = atoi(opts_small); /* TODO: use option parser */ *buf = malloc(size); gensize = gendata_h48_derive(h, fulltable, *buf); @@ -233,12 +237,17 @@ gendata_run_finish: } static void -derivedata_run(uint8_t h, const char *filename, uint64_t expected[static 21]) +derivedata_run( + const char *opts_large, + const char *opts_small, + const char *filename_large, + const char *filename_small +) { int64_t size; char *buf; - size = derivetable(h, &buf); + size = derivetable(opts_large, opts_small, filename_large, &buf); switch (size) { case -1: return; @@ -250,7 +259,7 @@ derivedata_run(uint8_t h, const char *filename, uint64_t expected[static 21]) printf("Succesfully generated %" PRId64 " bytes. " "See above for details on the tables.\n", size); - writetable(buf, size, filename); + writetable(buf, size, filename_small); break; }