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 5727f06c5694a4831881322876e3ba4d8ce3b743
parent e20e4f550ae373414d9bc106b1615a5c5896c9c4
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Sat, 20 Jul 2024 10:05:51 +0200

Finally fixed selfsim logic

Diffstat:
MTODO.txt | 9+++++----
Msrc/solve_h48.h | 117++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Dtest/111_gendata_h48_h0/00_h_0.in | 0
Dtest/111_gendata_h48_h0/gendata_h48_tests.c | 33---------------------------------
Rtest/112_h48map/00_small.in -> test/111_h48map/00_small.in | 0
Rtest/112_h48map/00_small.out -> test/111_h48map/00_small.out | 0
Rtest/112_h48map/01_large.in -> test/111_h48map/01_large.in | 0
Rtest/112_h48map/01_large.out -> test/111_h48map/01_large.out | 0
Rtest/112_h48map/h48map_tests.c -> test/111_h48map/h48map_tests.c | 0
Atest/112_gendata_h48/00_h_0.in | 2++
Rtest/111_gendata_h48_h0/00_h_0.out -> test/112_gendata_h48/00_h_0.out | 0
Atest/112_gendata_h48/gendata_h48_tests.c | 43+++++++++++++++++++++++++++++++++++++++++++
Rtools/benchmark_gendata_h48/benchmark_gendata_h48.c -> tools/01_gendata_h48/benchmark_gendata_h48.c | 0
Rtools/stats_tables_h48/stats_tables_h48.c -> tools/02_stats_tables_h48/stats_tables_h48.c | 0
14 files changed, 112 insertions(+), 92 deletions(-)

diff --git a/TODO.txt b/TODO.txt @@ -1,4 +1,7 @@ -Bug in esep table generation +H48 table generation + - fix gendata tool + - use to test generation of full h0k4 table + - remove ifdef and old code - compute all tables for h<11 x compute visited up to a fixed depth 8 - compute additional step (if needed) to fill <=base @@ -10,9 +13,7 @@ Bug in esep table generation - Add long-running test for h0k4 (maybe as a tool?) - tests for other sizes? - optimize - - use cached values for invcoord_esep? check if it is faster - - Unify and improve performance of finding nasty sim - (right now we don't even use selfsim) + - use only transform_edges (need compose trans) - parallelize with pthread (OLD: diff --git a/src/solve_h48.h b/src/solve_h48.h @@ -27,6 +27,24 @@ #define MAX_SOLUTION_LENGTH 20 +/* +TODO: This loop other similar h48 coordinates can be improved by only +transforming edges, but we need to compose transformations (i.e. conjugate +_t by _ttrep). +*/ +#define _foreach_h48sim(_cube, _cocsepdata, _selfsim, _h, _action) \ + int64_t _cocsep = coord_cocsep(_cube); \ + uint8_t _ttrep = TTREP(_cocsepdata[_cocsep]); \ + int64_t _coclass = COCLASS(_cocsepdata[_cocsep]); \ + cube_t _rep = transform(_cube, _ttrep); \ + uint64_t _sim = _selfsim[_coclass]; \ + for (uint8_t _t = 0; _t < 48 && _sim; _t++, _sim >>= 1) { \ + if (!(_sim & 1)) continue; \ + _cube = transform(_rep, _t); \ + _cube = transform(_cube, inverse_trans(_ttrep)); \ + _action \ + } + typedef struct { uint64_t n; uint64_t capacity; @@ -229,12 +247,12 @@ coord_h48(cube_t c, const uint32_t *cocsepdata, uint8_t h) } _static_inline int64_t -coord_h48_edges(cube_t c, int64_t coclass, uint8_t t, uint8_t h) +coord_h48_edges(cube_t c, int64_t coclass, uint8_t ttrep, uint8_t h) { cube_t d; int64_t esep, eo, edges; - d = transform_edges(c, t); + d = transform_edges(c, ttrep); esep = coord_esep(d); eo = coord_eo(d); edges = (esep << 11) + eo; @@ -394,11 +412,11 @@ gen_h48short( const uint64_t *selfsim, h48map_t *map ) { - uint8_t i, m, t; - int64_t coord, cc; - uint64_t j, oldn, sim; + uint8_t i, m; + int64_t coord; + uint64_t j, oldn; kvpair_t kv; - cube_t cube, d, e; + cube_t cube, d; cube = solvedcube(); coord = coord_h48(cube, cocsepdata, 11); @@ -418,17 +436,10 @@ gen_h48short( cube = invcoord_h48(kv.key, crep, 11); for (m = 0; m < 18; m++) { d = move(cube, m); - coord = coord_h48(d, cocsepdata, 11); - h48map_insertmin(map, coord, i+1); - cc = coord / H48_ESIZE(11); - sim = selfsim[cc] >> UINT64_C(1); - for (t = 1; t < 48 && sim; t++) { - /* TODO: optimize by using transform_edges, - corner coordinate is kept */ - e = transform(d, t); - coord = coord_h48(e, cocsepdata, 11); + _foreach_h48sim(d, cocsepdata, selfsim, 11, + coord = coord_h48(d, cocsepdata, 11); h48map_insertmin(map, coord, i+1); - } + ) } } LOG("found %" PRIu8 "\n", map->n-oldn); @@ -512,9 +523,8 @@ gendata_h48h0k4_bfs_fromdone(bfsarg_esep_t *arg) { uint8_t c, m, x; uint32_t cc; - int64_t i, j, k, t, cocsep_coord; - uint64_t sim; - cube_t cube, moved, transd; + int64_t i, j, k; + cube_t cube, moved; for (i = 0, cc = 0; i < (int64_t)ESEP_MAX(0); i++) { c = get_esep_pval(arg->buf32, i); @@ -522,30 +532,16 @@ gendata_h48h0k4_bfs_fromdone(bfsarg_esep_t *arg) continue; cube = invcoord_h48(i, arg->crep, 0); for (m = 0; m < 18; m++) { - /* - * TODO: here we can optimize by computing at first - * only the corner part of the coordinate, and then - * the edge parts for each transformation. - */ moved = move(cube, m); j = coord_h48(moved, arg->cocsepdata, 0); - x = get_esep_pval(arg->buf32, j); - if (x <= arg->depth) + if (get_esep_pval(arg->buf32, j) <= arg->depth) continue; - set_esep_pval(arg->buf32, j, arg->depth); - cc += x != arg->depth; - cocsep_coord = j / H48_ESIZE(0); - sim = arg->selfsim[cocsep_coord] >> UINT64_C(1); - for (t = 1; t < 48 && sim; t++) { - /* TODO: use only selfsim */ - transd = transform(moved, t); - k = coord_h48(transd, arg->cocsepdata, 0); + _foreach_h48sim(moved, arg->cocsepdata, arg->selfsim, 0, + k = coord_h48(moved, arg->cocsepdata, 0); x = get_esep_pval(arg->buf32, k); - if (x <= arg->depth) - continue; set_esep_pval(arg->buf32, k, arg->depth); cc += x != arg->depth; - } + ) } } @@ -557,8 +553,8 @@ gendata_h48h0k4_bfs_fromnew(bfsarg_esep_t *arg) { uint8_t c, m, x; uint32_t cc; - int64_t i, j, t, cocsep_coord, sim; - cube_t cube, moved, transd; + int64_t i, j; + cube_t cube, moved; for (i = 0, cc = 0; i < (int64_t)ESEP_MAX(0); i++) { c = get_esep_pval(arg->buf32, i); @@ -569,22 +565,33 @@ gendata_h48h0k4_bfs_fromnew(bfsarg_esep_t *arg) moved = move(cube, m); j = coord_h48(moved, arg->cocsepdata, 0); x = get_esep_pval(arg->buf32, j); - if (x < arg->depth) - goto neighbor_found; - } - continue; -neighbor_found: - set_esep_pval(arg->buf32, i, arg->depth); - cc++; - cocsep_coord = i / H48_ESIZE(0); - sim = arg->selfsim[cocsep_coord] >> 1; - for (t = 1; t < 48 && sim; t++) { - /* TODO: use only selfsim */ - transd = transform(cube, t); - j = coord_h48(transd, arg->cocsepdata, 0); - x = get_esep_pval(arg->buf32, j); - set_esep_pval(arg->buf32, j, arg->depth); - cc += x == 0xF; + if (x >= arg->depth) + continue; +#if 0 + cube_t transd; + int64_t t, cocsep_coord, sim; + + set_esep_pval(arg->buf32, i, arg->depth); + cc++; + cocsep_coord = i / H48_ESIZE(0); + sim = arg->selfsim[cocsep_coord] >> 1; + for (t = 1; t < 48 && sim; t++) { + transd = transform(cube, t); + j = coord_h48(transd, arg->cocsepdata, 0); + x = get_esep_pval(arg->buf32, j); + set_esep_pval(arg->buf32, j, arg->depth); + cc += x == 0xF; + } +#else + _foreach_h48sim(cube, arg->cocsepdata, arg->selfsim, 0, + j = coord_h48(cube, arg->cocsepdata, 0); + x = get_esep_pval(arg->buf32, j); + set_esep_pval(arg->buf32, j, arg->depth); + cc += x == 0xF; + ) +#endif + + break; } } diff --git a/test/111_gendata_h48_h0/00_h_0.in b/test/111_gendata_h48_h0/00_h_0.in diff --git a/test/111_gendata_h48_h0/gendata_h48_tests.c b/test/111_gendata_h48_h0/gendata_h48_tests.c @@ -1,33 +0,0 @@ -#include "../test.h" - -#define MAXDEPTH 5 -#define COCSEPSIZE 1119792 -#define ETABLESIZE ((3393 * 495 * 70) >> 1) - -int64_t gendata_h48h0k4(void *, uint8_t); - -void run(void) { - char str[STRLENMAX]; - uint8_t i; - uint32_t *buf, *h48info; - size_t result; - - fgets(str, STRLENMAX, stdin); - buf = (uint32_t *)malloc(sizeof(uint32_t) * 60000000); - result = gendata_h48h0k4(buf, MAXDEPTH); - h48info = buf + (ETABLESIZE + COCSEPSIZE) / 4; - - printf("%zu\n\n", result); - - printf("cocsepdata:\n"); - printf("Classes: %" PRIu32 "\n", buf[COCSEPSIZE/4-12]); - printf("Max value: %" PRIu32 "\n", buf[COCSEPSIZE/4-11]); - for (i = 0; i < 10; i++) - printf("%" PRIu32 ": %" PRIu32 "\n", i, buf[COCSEPSIZE/4-10+i]); - - printf("\nh48:\n"); - for (i = 0; i < MAXDEPTH+1; i++) - printf("%" PRIu32 ": %" PRIu32 "\n", i, h48info[i+1]); - - free(buf); -} diff --git a/test/112_h48map/00_small.in b/test/111_h48map/00_small.in diff --git a/test/112_h48map/00_small.out b/test/111_h48map/00_small.out diff --git a/test/112_h48map/01_large.in b/test/111_h48map/01_large.in diff --git a/test/112_h48map/01_large.out b/test/111_h48map/01_large.out diff --git a/test/112_h48map/h48map_tests.c b/test/111_h48map/h48map_tests.c diff --git a/test/112_gendata_h48/00_h_0.in b/test/112_gendata_h48/00_h_0.in @@ -0,0 +1,2 @@ +5 +0 diff --git a/test/111_gendata_h48_h0/00_h_0.out b/test/112_gendata_h48/00_h_0.out diff --git a/test/112_gendata_h48/gendata_h48_tests.c b/test/112_gendata_h48/gendata_h48_tests.c @@ -0,0 +1,43 @@ +#include "../test.h" + +#define COCSEPSIZE 1119792 +#define ETABLESIZE ((3393 * 495 * 70) >> 1) + +int64_t gendata_h48h0k4(void *, uint8_t); + +int64_t gendata_h48_fixture(void *buf, uint8_t maxdepth, uint8_t h) { + if (h == 0) + return gendata_h48h0k4(buf, maxdepth); + fprintf(stderr, "Error: gendata h48 for h>0 not implemented yet\n"); + exit(1); +} + +void run(void) { + char str[STRLENMAX]; + uint8_t i, maxdepth, h; + uint32_t *buf, *h48info; + size_t result; + + fgets(str, STRLENMAX, stdin); + maxdepth = atoi(str); + fgets(str, STRLENMAX, stdin); + h = atoi(str); + + buf = (uint32_t *)malloc(sizeof(uint32_t) * 60000000); + result = gendata_h48_fixture(buf, maxdepth, h); + h48info = buf + (ETABLESIZE + COCSEPSIZE) / 4; + + printf("%zu\n\n", result); + + printf("cocsepdata:\n"); + printf("Classes: %" PRIu32 "\n", buf[COCSEPSIZE/4-12]); + printf("Max value: %" PRIu32 "\n", buf[COCSEPSIZE/4-11]); + for (i = 0; i < 10; i++) + printf("%" PRIu32 ": %" PRIu32 "\n", i, buf[COCSEPSIZE/4-10+i]); + + printf("\nh48:\n"); + for (i = 0; i < maxdepth+1; i++) + printf("%" PRIu32 ": %" PRIu32 "\n", i, h48info[i+1]); + + free(buf); +} diff --git a/tools/benchmark_gendata_h48/benchmark_gendata_h48.c b/tools/01_gendata_h48/benchmark_gendata_h48.c diff --git a/tools/stats_tables_h48/stats_tables_h48.c b/tools/02_stats_tables_h48/stats_tables_h48.c