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 7defd8041e6050a9adf7927b43fd249d75d6389f
parent 038469b6f27106ab2002c7da11c6bca2a5fe30ee
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Tue,  4 Mar 2025 08:24:39 +0100

Begin work for coordinate solver

Diffstat:
ATODO_COORDINATES | 7+++++++
Asrc/solvers/coord/common.h | 20++++++++++++++++++++
Asrc/solvers/coord/coord_solve.h | 3+++
Asrc/solvers/coord/coord_types_macros.h | 13+++++++++++++
Asrc/solvers/coord/eo.h | 33+++++++++++++++++++++++++++++++++
Asrc/solvers/coord/gendata_coord.h | 134+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/solvers/solvers.h | 1+
Msrc/utils/constants.h | 2++
Atest/120_gendata_eo/00_all.in | 0
Atest/120_gendata_eo/00_all.out | 12++++++++++++
Atest/120_gendata_eo/gendata_eo_tests.c | 37+++++++++++++++++++++++++++++++++++++
Mtest/test.h | 1+
12 files changed, 263 insertions(+), 0 deletions(-)

diff --git a/TODO_COORDINATES b/TODO_COORDINATES @@ -0,0 +1,7 @@ +- solver + - include NISS +- test solver for EO +- make solve parallelized +- other coordinates + - gendata must handle symmetry +- make gendata parallelized diff --git a/src/solvers/coord/common.h b/src/solvers/coord/common.h @@ -0,0 +1,20 @@ +#include "eo.h" + +coord_t *all_coordinates[] = { + &coordinate_eo, + NULL +}; + +STATIC void append_coord_name(const coord_t *, char *); + +STATIC void +append_coord_name(const coord_t *coord, char *str) +{ + int i, j; + + i = 0; + j = strlen(str); + while (coord->name[i]) str[j++] = coord->name[i++]; + + str[j] = '\0'; +} diff --git a/src/solvers/coord/coord_solve.h b/src/solvers/coord/coord_solve.h @@ -0,0 +1,3 @@ +#include "coord_types_macros.h" +#include "common.h" +#include "gendata_coord.h" diff --git a/src/solvers/coord/coord_types_macros.h b/src/solvers/coord/coord_types_macros.h @@ -0,0 +1,13 @@ +#define COORD_INDEX(i) ((i)/2) +#define COORD_SHIFT(i) (UINT8_C(4) * (uint8_t)((i) % 2)) +#define COORD_MASK(i) (UINT8_C(0xF) << COORD_SHIFT(i)) + +typedef struct { + char name[255]; + uint64_t (*coord)(cube_t, const void *); + cube_t (*cube)(uint64_t, const void *); + size_t (*gendata)(void *); + uint64_t max; + uint32_t moves_mask; + uint64_t trans_mask; +} coord_t; diff --git a/src/solvers/coord/eo.h b/src/solvers/coord/eo.h @@ -0,0 +1,33 @@ +STATIC uint64_t coordinate_eo_coord(cube_t, const void *); +STATIC cube_t coordinate_eo_cube(uint64_t, const void *); +STATIC uint64_t coordinate_eo_gendata(void *); + +STATIC coord_t coordinate_eo = { + .name = "EO", + .coord = &coordinate_eo_coord, + .cube = &coordinate_eo_cube, + .gendata = coordinate_eo_gendata, + .max = POW_2_11, + .trans_mask = TM_ALLTRANS, + .moves_mask = MM_ALLMOVES, +}; + +STATIC uint64_t +coordinate_eo_coord(cube_t c, const void *data) +{ + return (uint64_t)coord_eo(c); +} + +STATIC cube_t +coordinate_eo_cube(uint64_t c, const void *data) +{ + cube_t cube = SOLVED_CUBE; + set_eo(&cube, (int64_t)c); + return cube; +} + +STATIC size_t +coordinate_eo_gendata(void *data) +{ + return 0; +} diff --git a/src/solvers/coord/gendata_coord.h b/src/solvers/coord/gendata_coord.h @@ -0,0 +1,134 @@ +STATIC size_t gendata_coordinate(const coord_t *, void *); +STATIC size_t gendata_coordinate_name(const char *, void *); +STATIC tableinfo_t genptable_coordinate(const coord_t *, const void *, uint8_t *); +STATIC uint8_t get_coord_pval(const coord_t *, const uint8_t *, uint64_t); +STATIC void set_coord_pval(const coord_t *, uint8_t *, uint64_t, uint8_t); + +STATIC size_t +gendata_coordinate_name(const char *name, void *buf) +{ + int i; + + for (i = 0; all_coordinates[i] != NULL; i++) + if (strcmp(all_coordinates[i]->name, name) == 0) + return gendata_coordinate(all_coordinates[i], buf); + + LOG("Cannot generate data for coordinate '%s': not found\n", name); + return 0; +} + +STATIC size_t +gendata_coordinate(const coord_t *coord, void *buf) +{ + uint64_t coord_dsize, tablesize, ninfo; + void *pruningbuf, *coord_data; + uint8_t *table; + tableinfo_t coord_data_info, pruning_info; + + coord_data = buf == NULL ? NULL : ((uint8_t *)buf) + INFOSIZE; + coord_dsize = coord->gendata(coord_data); + ninfo = coord_dsize == 0 ? 1 : 2; + tablesize = DIV_ROUND_UP(coord->max, 2); + + if (buf == NULL) + goto gendata_coordinate_return_size; + + if (ninfo == 2) { + coord_data_info = (tableinfo_t) { + .solver = "coord helper table for ", + .type = TABLETYPE_SPECIAL, + .infosize = INFOSIZE, + .fullsize = INFOSIZE + coord_dsize, + .hash = 0, /* TODO */ + .next = INFOSIZE + coord_dsize, + + /* Unknown / non-applicable values */ + .entries = 0, + .classes = 0, + .bits = 0, + .base = 0, + .maxvalue = 0, + }; + + append_coord_name(coord, coord_data_info.solver); + + writetableinfo(&coord_data_info, INFOSIZE + coord_dsize, buf); + + pruningbuf = ((uint8_t *)buf) + INFOSIZE + coord_dsize; + } else { + pruningbuf = buf; + } + + table = ((uint8_t *)pruningbuf) + INFOSIZE; + pruning_info = genptable_coordinate(coord, coord_data, table); + writetableinfo(&pruning_info, INFOSIZE + tablesize, pruningbuf); + +gendata_coordinate_return_size: + return ninfo * INFOSIZE + coord_dsize + tablesize; +} + +STATIC tableinfo_t +genptable_coordinate(const coord_t *coord, const void *data, uint8_t *table) +{ + uint64_t tablesize, i, j, d, tot; + tableinfo_t info; + uint8_t m; + cube_t c, cc; + + tablesize = DIV_ROUND_UP(coord->max, 2); + + memset(table, 0xFF, tablesize); + + info = (tableinfo_t) { + .solver = "coordinate solver for ", + .type = TABLETYPE_PRUNING, + .infosize = INFOSIZE, + .fullsize = INFOSIZE + tablesize, + .hash = 0, /* TODO */ + .entries = coord->max, + .classes = 0, + .bits = 4, + .base = 0, + .maxvalue = 0, + .next = 0 + }; + + memset(info.distribution, 0, INFO_DISTRIBUTION_LEN * sizeof(uint64_t)); + append_coord_name(coord, info.solver); + + i = coord->coord(SOLVED_CUBE, data); + set_coord_pval(coord, table, i, 0); + info.distribution[0] = 1; + for (d = 1, tot = 1; tot < coord->max; d++) { + for (i = 0; i < coord->max; i++) { + if (get_coord_pval(coord, table, i) == d-1) { + c = coord->cube(i, data); + for (m = 0; m < 18; m++) { + cc = move(c, m); + j = coord->coord(cc, data); + if (get_coord_pval(coord, table, j) > d) { + set_coord_pval(coord, table, j, d); + tot++; + info.distribution[d]++; + } + } + } + } + } + info.maxvalue = d-1; + + return info; +} + +STATIC uint8_t +get_coord_pval(const coord_t *coord, const uint8_t *table, uint64_t i) +{ + return (table[COORD_INDEX(i)] & COORD_MASK(i)) >> COORD_SHIFT(i); +} + +STATIC void +set_coord_pval(const coord_t *coord, uint8_t *table, uint64_t i, uint8_t val) +{ + table[COORD_INDEX(i)] = (table[COORD_INDEX(i)] & (~COORD_MASK(i))) + | (val << COORD_SHIFT(i)); +} diff --git a/src/solvers/solvers.h b/src/solvers/solvers.h @@ -1,2 +1,3 @@ #include "tables.h" #include "h48/h48.h" +#include "coord/coord_solve.h" diff --git a/src/utils/constants.h b/src/utils/constants.h @@ -99,6 +99,8 @@ STATIC int64_t binomial[12][12] = { #define MM_ALLMOVES UINT32_C(0x3FFFF) #define MM_NOHALFTURNS UINT32_C(0x2DB6D) +#define TM_ALLTRANS UINT64_C(0xFFFFFFFFFFFF) + #define CORNER_UFR UINT8_C(0) #define CORNER_UBL UINT8_C(1) #define CORNER_DFL UINT8_C(2) diff --git a/test/120_gendata_eo/00_all.in b/test/120_gendata_eo/00_all.in diff --git a/test/120_gendata_eo/00_all.out b/test/120_gendata_eo/00_all.out @@ -0,0 +1,12 @@ +1536 +0: 1 +1: 2 +2: 25 +3: 202 +4: 620 +5: 900 +6: 285 +7: 13 +8: 0 +9: 0 +10: 0 diff --git a/test/120_gendata_eo/gendata_eo_tests.c b/test/120_gendata_eo/gendata_eo_tests.c @@ -0,0 +1,37 @@ +/* +Pruning table values (from nissy): +0: 1 +1: 2 +2: 25 +3: 202 +4: 620 +5: 900 +6: 285 +7: 13 +*/ + +#include "../test.h" + +#define ISIZE 512 +#define FULLSIZE (ISIZE + 1024) + +char buf[FULLSIZE]; + +size_t gendata_coordinate_name(const char *, void *); +bool readtableinfo(uint64_t, const char *, tableinfo_t *); + +void run(void) { + uint32_t i; + size_t result; + tableinfo_t info; + + result = gendata_coordinate_name("EO", buf); + if (readtableinfo(FULLSIZE, buf, &info) != NISSY_OK) { + printf("Error reading info from table\n"); + return; + } + + printf("%zu\n", result); + for (i = 0; i <= 10; i++) + printf("%" PRIu32 ": %" PRIu64 "\n", i, info.distribution[i]); +} diff --git a/test/test.h b/test/test.h @@ -14,6 +14,7 @@ #include "../src/solvers/h48/coordinate_macros.h" #include "../src/solvers/h48/map_types_macros.h" #include "../src/solvers/h48/gendata_types_macros.h" +#include "../src/solvers/coord/coord_types_macros.h" #define STRLENMAX 10000