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 4dde2625a1bcb5381b50b22e7212070266cd224f
parent 7b1836b35e4e4e275c093f1a120db8006108b90d
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Mon, 20 May 2024 12:52:57 +0200

Changed gendata h48 to bfs

Diffstat:
MTODO.txt | 30++++++------------------------
Msrc/solve_h48.h | 180++++++++++++++++++++++++++++++++++++++-----------------------------------------
Dtest/102_gendata_esep/gendata_esep_tests.c | 22----------------------
Rtest/102_gendata_esep/00_all.in -> test/102_gendata_h48/00_all.in | 0
Rtest/102_gendata_esep/00_all.out -> test/102_gendata_h48/00_all.out | 0
Atest/102_gendata_h48/gendata_h48_tests.c | 18++++++++++++++++++
6 files changed, 111 insertions(+), 139 deletions(-)

diff --git a/TODO.txt b/TODO.txt @@ -1,27 +1,9 @@ -In progress: go back to nissy-style BFS for eosep data computation - - (done) compute selfsim and cocsep representatives - - (done) implement set_eo_fast for invcoord_h48 - - (done) for invcoord_h48 remove erep, implement inverse esep coord - - (done) add unit tests for invcoord_h48 (compute tables, if needed) - - change to BFS - -TODO pruning tables: - - four different ruotines for k=4,2,1 for eoesep - - try: do not compute CO, but use its binary representation - (x8 memory for cocsep) - (isn't this already done?) - - numbers so far (eoesep h=0, k=0): - 0 1 - 1 1 - 2 4 - 3 34 - 4 331 - 5 3612 - 6 41605 - 7 474128 - 8 4953846 - 9 34776317 +TODO + - test h48 table by adding a parameter to stop computation at certain depth + - add back benchmark, test performance of table computation + - table generation is still slow, how to improve? profile! + selfsim could be a list of cubes (representatives) + - add h48 table for different values of k TODO checkdata (available from cube.h) and hash check for cocsep TODO benchmarks for solve and table generation diff --git a/src/solve_h48.h b/src/solve_h48.h @@ -1,20 +1,20 @@ -#define COCSEP_CLASSES 3393U -#define COCSEP_TABLESIZE (_3p7 << 7U) -#define COCSEP_VISITEDSIZE ((COCSEP_TABLESIZE + 7U) / 8U) -#define COCSEP_INFOSIZE 12U -#define COCSEP_FULLSIZE (4 * (COCSEP_TABLESIZE + COCSEP_INFOSIZE)) +#define COCSEP_CLASSES 3393U +#define COCSEP_TABLESIZE (_3p7 << 7U) +#define COCSEP_VISITEDSIZE ((COCSEP_TABLESIZE + 7U) / 8U) +#define COCSEP_INFOSIZE 12U +#define COCSEP_FULLSIZE (4 * (COCSEP_TABLESIZE + COCSEP_INFOSIZE)) -#define ESEP_TABLESIZE ((COCSEP_CLASSES * _12c4 * _8c4) / 2U) -#define ESEP_VISITEDSIZE ((ESEP_TABLESIZE * 2U + 7U) / 8U) -#define ESEP_INFOSIZE 25 /* TODO unknown yet */ +#define ESEP_MAX(h) ((COCSEP_CLASSES * _12c4 * _8c4) << (h)) +#define ESEP_TABLESIZE(h, k) (ESEP_MAX((h)) >> (k)) +#define ESEP_INFOSIZE 25 /* TODO unknown yet */ -#define H48_ESIZE(h) ((_12c4 * _8c4) << (h)) +#define H48_ESIZE(h) ((_12c4 * _8c4) << (h)) -#define _esep_ind(i) (i / 8U) -#define _esep_shift(i) (4U * (i % 8U)) -#define _esep_mask(i) (((1U << 4U) - 1U) << _esep_shift(i)) -#define _visited_ind(i) (i / 8U) -#define _visited_mask(i) (1U << (i % 8U)) +#define _esep_ind(i) (i / 8U) +#define _esep_shift(i) (4U * (i % 8U)) +#define _esep_mask(i) (((1U << 4U) - 1U) << _esep_shift(i)) +#define _visited_ind(i) (i / 8U) +#define _visited_mask(i) (1U << (i % 8U)) typedef struct { cube_fast_t cube; @@ -28,23 +28,21 @@ typedef struct { } dfsarg_cocsep_t; typedef struct { - cube_fast_t cube; - uint8_t *visited; - uint8_t *moves; - uint8_t nmoves; uint8_t depth; - uint16_t *nclasses; + uint8_t h; uint32_t *cocsepdata; uint32_t *buf32; -} dfsarg_esep_t; + uint64_t *selfsim; + cube_fast_t *crep; +} bfsarg_esep_t; _static_inline int64_t coord_h48(cube_fast_t, const uint32_t *, uint8_t); _static_inline cube_fast_t invcoord_h48(int64_t, const cube_fast_t *, uint8_t); _static size_t gendata_cocsep(void *, uint64_t *, cube_fast_t *); _static uint32_t gendata_cocsep_dfs(dfsarg_cocsep_t *); -_static size_t gendata_esep(void *); -_static uint32_t gendata_esep_dfs(dfsarg_esep_t *); +_static size_t gendata_h48(void *, uint8_t); +_static uint64_t gendata_esep_bfs(bfsarg_esep_t *); _static_inline bool get_visited(const uint8_t *, int64_t); _static_inline void set_visited(uint8_t *, int64_t); @@ -86,7 +84,7 @@ invcoord_h48(int64_t i, const cube_fast_t *crep, uint8_t h) { cube_fast_t ret; int64_t coclass, ee, esep, eo; DBG_ASSERT(h <= 11, cubetofast(zero), - "invcoord_h48: h must be between 0 and 11\n"); + "invcoord_h48: h must be between 0 and 11\n"); coclass = i / H48_ESIZE(h); ee = i % H48_ESIZE(h); @@ -164,7 +162,7 @@ gendata_cocsep_dfs(dfsarg_cocsep_t *arg) { uint8_t m, t, tinv, olddepth; uint32_t cc; - int64_t i; + int64_t i, ii; uint64_t sim; cube_fast_t d; dfsarg_cocsep_t nextarg; @@ -181,13 +179,12 @@ gendata_cocsep_dfs(dfsarg_cocsep_t *arg) for (t = 0, cc = 0; t < 48; t++) { d = transform(arg->cube, t); - sim = equal_fast(arg->cube, d); - arg->selfsim[*arg->n] |= sim << t; - i = coord_fast_cocsep(d); - set_visited(arg->visited, i); + ii = coord_fast_cocsep(d); + arg->selfsim[*arg->n] |= (i == ii) << t; + set_visited(arg->visited, ii); tinv = inverse_trans(t); - cc += (arg->buf32[i] & 0xFFU) == 0xFFU; - arg->buf32[i] = + cc += (arg->buf32[ii] & 0xFFU) == 0xFFU; + arg->buf32[ii] = (*arg->n << 16U) | (tinv << 8U) | arg->depth; } arg->rep[*arg->n] = arg->cube; @@ -211,84 +208,81 @@ TODO description generating fixed table with h=0, k=4 */ _static size_t -gendata_esep(void *buf) +gendata_h48(void *buf, uint8_t h) { - uint32_t *buf32, *info, *cocsepdata, cc; - uint8_t moves[20]; - dfsarg_esep_t arg; - - arg.visited = malloc(ESEP_TABLESIZE); + const int k = 1; /* TODO: other cases? */ + uint32_t *buf32, *info, *cocsepdata; + bfsarg_esep_t arg; + int64_t sc, cc, tot; + uint64_t selfsim[COCSEP_CLASSES]; + cube_fast_t crep[COCSEP_CLASSES]; + size_t cocsepsize; + + cocsepsize = gendata_cocsep(buf, selfsim, crep); + DBG_ASSERT(cocsepsize == COCSEP_FULLSIZE, 0, + "gendata_h48: error computing cocsep data\n"); cocsepdata = (uint32_t *)buf; - buf32 = cocsepdata + COCSEP_FULLSIZE; - info = buf32 + ESEP_TABLESIZE; - memset(buf32, 0xFFU, sizeof(uint32_t) * ESEP_TABLESIZE); + buf32 = cocsepdata + cocsepsize; + info = buf32 + ESEP_TABLESIZE(h, k); + memset(buf32, 0xFFU, sizeof(uint32_t) * ESEP_TABLESIZE(h, k)); memset(info, 0, sizeof(uint32_t) * ESEP_INFOSIZE); - arg.cube = cubetofast(solvedcube()); - arg.moves = moves; - arg.nmoves = 0; - arg.cocsepdata = cocsepdata; - arg.buf32 = buf32; - /* TODO loop until no more is done, not until 12! (or hardcode limits)*/ - /* TODO use bfs instead - how to work with different k? k=1 is the easiest */ - for (arg.depth = 0, cc = 0; arg.depth < 12; arg.depth++) { + sc = coord_h48(cubetofast(solved), cocsepdata, h); + set_esep_pval(buf32, sc, 0); + arg = (bfsarg_esep_t) { + .h = h, + .cocsepdata = cocsepdata, + .buf32 = buf32, + .crep = crep, + .selfsim = selfsim + }; + for (tot = 1, arg.depth = 1, cc = 0; tot < ESEP_MAX(h); arg.depth++) { DBG_LOG("esep: generating depth %" PRIu8 "\n", arg.depth); - memset(arg.visited, 0, ESEP_VISITEDSIZE); - cc = gendata_esep_dfs(&arg); + cc = gendata_esep_bfs(&arg); + tot += cc; info[arg.depth+1] = cc; - DBG_LOG("found %" PRIu32 "\n", cc); + DBG_LOG("found %" PRIu64 "\n", cc); } - free(arg.visited); return COCSEP_FULLSIZE + cc; } -_static uint32_t -gendata_esep_dfs(dfsarg_esep_t *arg) +_static uint64_t +gendata_esep_bfs(bfsarg_esep_t *arg) { - uint8_t m, t, olddepth; + uint8_t c, m, t, x; uint32_t cc; - uint64_t i; - cube_fast_t d; - dfsarg_esep_t nextarg; - - if (!allowednextmove(arg->moves, arg->nmoves)) - return 0; - - if (arg->nmoves > 0) - arg->cube = move(arg->cube, arg->moves[arg->nmoves-1]); - - i = coord_h48(arg->cube, arg->cocsepdata, 0U); - olddepth = get_esep_pval(arg->buf32, i); - - if (olddepth < arg->nmoves || get_visited(arg->visited, i)) - return 0; - set_visited(arg->visited, i); - - if (arg->nmoves == arg->depth) { - if (olddepth != 15U) - return 0; - - for (t = 0, cc = 0; t < 48; t++) { - d = transform(arg->cube, t); - i = coord_h48(d, arg->cocsepdata, 0U); - set_visited(arg->visited, i); - cc += get_esep_pval(arg->buf32, i) == 15U; - set_esep_pval(arg->buf32, i, arg->depth); + uint64_t i, j, k, cocsep_coord, sim; + cube_fast_t cube, moved, transd; + + for (i = 0, cc = 0; i < ESEP_MAX(arg->h); i++) { + c = get_esep_pval(arg->buf32, i); + if (c != arg->depth - 1) + continue; + cube = invcoord_h48(i, arg->crep, arg->h); + for (m = 0; m < 18; m++) { + moved = move(cube, m); + j = coord_h48(moved, arg->cocsepdata, arg->h); + x = get_esep_pval(arg->buf32, j); + if (x <= arg->depth) + continue; + set_esep_pval(arg->buf32, j, arg->depth); + cc += x != arg->depth; + cocsep_coord = j / H48_ESIZE(arg->h); + sim = arg->selfsim[cocsep_coord]; + for (t = 1; t < 48; t++) { /* Skip trivial trans */ + if (!(sim & (1 << t))) + continue; + transd = transform(moved, t); + k = coord_h48(transd, arg->cocsepdata, arg->h); + x = get_esep_pval(arg->buf32, k); + if (x <= arg->depth) + continue; + set_esep_pval(arg->buf32, k, arg->depth); + cc += x != arg->depth; + } } - - return cc; - } - - - nextarg = *arg; - nextarg.nmoves = arg->nmoves + 1; - for (m = 0, cc = 0; m < 18; m++) { - nextarg.cube = arg->cube; - nextarg.moves[arg->nmoves] = m; - cc += gendata_esep_dfs(&nextarg); } return cc; diff --git a/test/102_gendata_esep/gendata_esep_tests.c b/test/102_gendata_esep/gendata_esep_tests.c @@ -1,22 +0,0 @@ -#include "../test.h" - -#define CSIZE 1200000 -#define ESIZE 250000000 - -uint32_t buf_c[CSIZE/4]; -uint32_t buf_e[ESIZE/4]; - -size_t gendata_cocsep(void *); -size_t gendata_esep(const void *, void *); - -int main(void) { - uint32_t i; - size_t result; - - gendata_cocsep(buf_c); - result = gendata_esep(buf_c, buf_e); - - printf("nothing\n"); - - return 0; -} diff --git a/test/102_gendata_esep/00_all.in b/test/102_gendata_h48/00_all.in diff --git a/test/102_gendata_esep/00_all.out b/test/102_gendata_h48/00_all.out diff --git a/test/102_gendata_h48/gendata_h48_tests.c b/test/102_gendata_h48/gendata_h48_tests.c @@ -0,0 +1,18 @@ +#include "../test.h" + +#define H 0 +#define SIZE (120000000 << (H)) + +uint32_t buf[SIZE]; + +size_t gendata_h48(void *, uint8_t); + +int main(void) { + size_t result; + + result = gendata_h48(buf, H); + + printf("nothing\n"); + + return 0; +}