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 c548499e68e473452592c9b0bf860f76bd8b94b8
parent 7e6c14a2f6e9e9cbac3431f3085c42bbe474d13d
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Fri, 30 Aug 2024 07:52:53 +0200

Added tool for checking new tables (and they are wrong)

Diffstat:
Msrc/solvers/h48/gendata_h48.h | 21+++++++++++++++------
Msrc/solvers/h48/map.h | 5+++--
Msrc/utils/math.h | 1+
Mtools/001_gendata_h48h0k4/gendata_h48h0k4.c | 4++--
Atools/002_gendata_h48h0k2/gendata_h48h0k2.c | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rtools/002_stats_tables_h48/stats_tables_h48.c -> tools/010_stats_tables_h48/stats_tables_h48.c | 0
Rtools/003_solve_small/solve_small.c -> tools/020_solve_small/solve_small.c | 0
7 files changed, 83 insertions(+), 10 deletions(-)

diff --git a/src/solvers/h48/gendata_h48.h b/src/solvers/h48/gendata_h48.h @@ -1,6 +1,7 @@ #define H48_COORDMAX_NOEO ((int64_t)(COCSEP_CLASSES * _12c4 * _8c4)) #define H48_COORDMAX(h) ((int64_t)(H48_COORDMAX_NOEO << (int64_t)(h))) -#define H48_TABLESIZE(h, k) ((size_t)H48_COORDMAX((h)) / ((size_t)8 / (size_t)(k))) +#define H48_DIV(k) ((size_t)8 / (size_t)(k)) +#define H48_TABLESIZE(h, k) _div_round_up((size_t)H48_COORDMAX((h)), H48_DIV(k)) #define H48_COEFF(k) (UINT32_C(32) / (uint32_t)(k)) #define H48_INDEX(i, k) ((uint32_t)(i) / H48_COEFF(k)) @@ -140,7 +141,7 @@ gendata_h48(gendata_h48_arg_t *arg) cocsepsize = gendata_cocsep( (void *)arg->cocsepdata, arg->selfsim, arg->crep); arg->h48data = arg->cocsepdata + (cocsepsize / sizeof(uint32_t)); - arg->info = arg->h48data + + arg->info = arg->h48data + 1 + (H48_TABLESIZE(arg->h, arg->k) / sizeof(uint32_t)); if (arg->buf != NULL) @@ -341,18 +342,27 @@ gendata_h48k2(gendata_h48_arg_t *arg) }; i = 0; +int jj = 0; for (kv = h48map_nextkvpair(&shortcubes, &i); i != shortcubes.capacity; kv = h48map_nextkvpair(&shortcubes, &i) ) { - /* TODO maybe over all sim? */ dfsarg.cube = invcoord_h48(kv.key, arg->crep, 11); + +#if 1 gendata_h48k2_dfs(&dfsarg); +#else + /* It looks like this is not necessary, we get the same result */ + _foreach_h48sim( + dfsarg.cube, arg->cocsepdata, arg->selfsim, arg->h, + gendata_h48k2_dfs(&dfsarg); + ) +#endif +if ((++jj) % 1000 == 0) LOG("Done %d distance 8 cubes\n", jj); } h48map_destroy(&shortcubes); - /* TODO: move info update to dfs? */ memset(arg->info, 0, 5 * sizeof(arg->info[0])); arg->info[0] = base[arg->k]; for (j = 0; j < H48_COORDMAX(arg->h); j++) { @@ -384,8 +394,7 @@ gendata_h48k2_dfs(h48k2_dfs_arg_t *arg) set_esep_pval(arg->h48data, coord, arg->k, newval); } - if ((val < arg->shortdepth) || - (arg->depth > arg->shortdepth && val != MAP_UNSET) || + if ((arg->depth > arg->shortdepth && val != MAP_UNSET_VAL) || (arg->depth >= arg->maxdepth || arg->depth >= arg->base + 2)) return; diff --git a/src/solvers/h48/map.h b/src/solvers/h48/map.h @@ -1,6 +1,7 @@ #define MAP_UNSET UINT64_C(0xFFFFFFFFFFFFFFFF) #define MAP_KEYMASK UINT64_C(0xFFFFFFFFFF) #define MAP_KEYSHIFT UINT64_C(40) +#define MAP_UNSET_VAL (MAP_UNSET >> MAP_KEYSHIFT) typedef struct { uint64_t n; @@ -84,8 +85,8 @@ h48map_nextkvpair(h48map_t *map, uint64_t *p) kvpair_t kv; uint64_t pair; - kv.key = MAP_UNSET; - kv.val = MAP_UNSET; + kv.key = MAP_KEYMASK; + kv.val = MAP_UNSET_VAL; DBG_ASSERT(*p < map->capacity, kv, "Error looping over map: given index %" PRIu64 " is out of " diff --git a/src/utils/math.h b/src/utils/math.h @@ -1,6 +1,7 @@ #define _swap(x, y) do { x ^= y; y ^= x; x ^= y; } while (0) #define _min(x, y) ((x) < (y) ? (x) : (y)) #define _max(x, y) ((x) > (y) ? (x) : (y)) +#define _div_round_up(n, d) (((n) + (d) - 1) / (d)) _static int64_t factorial(int64_t); _static bool isperm(uint8_t *, int64_t); diff --git a/tools/001_gendata_h48h0k4/gendata_h48h0k4.c b/tools/001_gendata_h48h0k4/gendata_h48h0k4.c @@ -37,12 +37,12 @@ void run(void) { printf("Error generating table\n"); } else { printf("Succesfully generated %" PRId64 " bytes. Table:\n", s); - h48info = (uint32_t *)buf + (ETABLESIZE(HVALUE) + COCSEPSIZE) / 4; + h48info = (uint32_t *)buf + 1 + (ETABLESIZE(HVALUE) + COCSEPSIZE) / 4; for (i = 0; i < MAXDEPTH+1 && h48info[i+1]; i++) { x = h48info[i+1]; printf("%d:\t%" PRIu32, i, x); if (x != expected[i]) - printf(" <--- Error! Expected: %" PRIu32 "\n", + printf(" <--- Error! Expected: %" PRIu32, expected[i]); printf("\n"); } diff --git a/tools/002_gendata_h48h0k2/gendata_h48h0k2.c b/tools/002_gendata_h48h0k2/gendata_h48h0k2.c @@ -0,0 +1,62 @@ +#include "../tool.h" + +#define MAXDEPTH 20 +#define HVALUE 0 +#define OPTIONS "0;2;20" +#define LONGOPTIONS "h = 0, k = 2, max depth = 20" + +#define COCSEPSIZE 1119792 +#define ETABLESIZE(h) (((3393 * 495 * 70) >> 2) << (size_t)(h)) + +uint32_t expected[21] = { + /* Base value is 8 */ + [0] = 5473562, + [1] = 34776317, + [2] = 68566704, + [3] = 8750867, +}; + +char *buf; + +void run(void) { + uint32_t *h48info, x; + int i; + int64_t s; + + s = nissy_gendata("h48", OPTIONS, buf); + + if (s == -1) { + printf("Error generating table\n"); + } else { + printf("Succesfully generated %" PRId64 " bytes. Table:\n", s); + h48info = (uint32_t *)buf + 1 + (ETABLESIZE(HVALUE) + COCSEPSIZE) / 4; + for (i = 0; i < 4; i++) { + x = h48info[i+1]; + printf("%d:\t%" PRIu32, i, x); + if (x != expected[i]) + printf(" <--- Error! Expected: %" PRIu32, + expected[i]); + printf("\n"); + } + } +} + +int main(void) { + int64_t size; + + nissy_setlogger(log_stderr); + + size = nissy_datasize("h48", OPTIONS); + if (size == -1) { + printf("gendata_h48 benchmark: error in datasize\n"); + return 1; + } + + buf = malloc(size); + + timerun(run, "benchmark gendata_h48 " LONGOPTIONS); + + free(buf); + + return 0; +} diff --git a/tools/002_stats_tables_h48/stats_tables_h48.c b/tools/010_stats_tables_h48/stats_tables_h48.c diff --git a/tools/003_solve_small/solve_small.c b/tools/020_solve_small/solve_small.c