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 ae0e5295daa7618b6facebac31c3a88eaccfc368
parent 29f61e2b4e0f73c83d6d86e4f09d79e129358750
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Tue,  1 Apr 2025 22:26:44 +0200

Make symcoord logic generic

Diffstat:
Msrc/solvers/coord/common.h | 133+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/solvers/coord/dr.h | 142++++++++++++++++++-------------------------------------------------------------
Msrc/solvers/coord/eo.h | 1+
Msrc/solvers/coord/types_macros.h | 30+++++++++++++++++++++++++++---
4 files changed, 191 insertions(+), 115 deletions(-)

diff --git a/src/solvers/coord/common.h b/src/solvers/coord/common.h @@ -1,10 +1,139 @@ -STATIC void append_coord_name(const coord_t *, char *); +STATIC uint64_t coord_coord_generic( + const coord_t [static 1], cube_t, const void *); +STATIC cube_t coord_cube_generic( + const coord_t [static 1], uint64_t, const void *); +STATIC bool coord_isnasty_generic( + const coord_t [static 1], uint64_t, const void *); +STATIC size_t coord_gendata_generic(const coord_t [static 1], void *); + +STATIC void append_coord_name(const coord_t [static 1], char *); STATIC bool solution_lastqt_cw(const solution_moves_t [static 1]); STATIC bool coord_can_switch( const coord_t [static 1], const void *, size_t n, const uint8_t [n]); +STATIC uint64_t +coord_coord_generic(const coord_t coord[static 1], cube_t c, const void *data) +{ + const char *datanoinfo; + const uint32_t *data32; + uint32_t d; + cube_t tr; + + datanoinfo = (const char *)data + INFOSIZE; + data32 = (const uint32_t *)datanoinfo; + d = data32[coord->sym.coord(c)]; + tr = transform(c, COORD_TTREP(d)); + + return COORD_CLASS(d) * coord->sym.max2 + coord->sym.coord2(tr); +} + +STATIC cube_t +coord_cube_generic(const coord_t coord[static 1], uint64_t i, const void *data) +{ + const char *datanoinfo; + const uint32_t *rep32; + cube_t c; + + datanoinfo = (const char *)data + INFOSIZE; + rep32 = (const uint32_t *)(datanoinfo + 4 * (size_t)coord->sym.max); + c = coord->sym.cube(rep32[i / coord->sym.max2]); + + return coord->sym.merge(c, coord->sym.cube2(i % coord->sym.max2)); +} + +STATIC bool +coord_isnasty_generic( + const coord_t coord[static 1], + uint64_t i, + const void *data +) +{ + const char *datanoinfo; + const uint32_t *classttrep, *rep32; + uint32_t r; + + datanoinfo = (const char *)data + INFOSIZE; + classttrep = (const uint32_t *)datanoinfo; + rep32 = (const uint32_t *)(datanoinfo + 4 * (size_t)coord->sym.max); + r = rep32[i / coord->sym.max2]; + + return COORD_ISNASTY(classttrep[r]); +} + +STATIC size_t +coord_gendata_generic( + const coord_t coord[static 1], + void *data +) +{ + uint64_t i, j, n, t, nasty; + char *datanoinfo; + uint32_t *classttrep, *rep; + size_t coord_datasize; + cube_t c; + tableinfo_t info; + + coord_datasize = INFOSIZE + 4*(coord->sym.classes + coord->sym.max); + + if (data == NULL) + return coord_datasize; + + datanoinfo = (char *)data + INFOSIZE; + classttrep = (uint32_t *)datanoinfo; + rep = classttrep + coord->sym.max; + memset(data, 0xFF, coord_datasize); + + info = (tableinfo_t) { + .solver = "coord data for ", + .type = TABLETYPE_SPECIAL, + .infosize = INFOSIZE, + .fullsize = coord_datasize, + .hash = 0, + .entries = coord->sym.classes + coord->sym.max, + .classes = coord->sym.classes, + .bits = 32, + .base = 0, + .maxvalue = 0, + .next = 0 + }; + append_coord_name(coord, info.solver); + + for (i = 0, n = 0; i < coord->sym.max; i++) { + if (classttrep[i] != 0xFFFFFFFF) + continue; + + c = coord->sym.cube(i); + for (t = 1, nasty = 0; t < NTRANS && !nasty; t++) { + if (!((UINT64_C(1) << t) & coord->trans_mask)) + continue; + + nasty = i == coord->sym.coord(transform(c, t)); + } + + for (t = 0; t < NTRANS; t++) { + if (!((UINT64_C(1) << t) & coord->trans_mask)) + continue; + + j = coord->sym.coord(transform(c, t)); + classttrep[j] = + (n << COORD_CLASS_SHIFT) | + (nasty << COORD_ISNASTY_SHIFT) | + (inverse_trans(t) << COORD_TTREP_SHIFT); + } + rep[n++] = i; + } + + writetableinfo(&info, coord_datasize, data); + + DBG_ASSERT(n == coord->sym.classes, 0, + "%s coordinate data: computed %" PRIu64 " classes, " + "expected %" PRIu64 "\n", coord->name, n, coord->sym.classes); + + return coord_datasize; +} + STATIC void -append_coord_name(const coord_t *coord, char *str) +append_coord_name(const coord_t coord[static 1], char *str) { int i, j; diff --git a/src/solvers/coord/dr.h b/src/solvers/coord/dr.h @@ -1,30 +1,19 @@ #define DREOESEP_CLASSES UINT64_C(64430) #define DREOESEP_MAX (POW_2_11 * COMB_12_4) -#define DR_CLASS_TABLESIZE (sizeof(uint32_t) * (size_t)DREOESEP_MAX) -#define DR_REP_TABLESIZE (sizeof(uint32_t) * (size_t)DREOESEP_CLASSES) -#define DR_COORD_DATASIZE (INFOSIZE + DR_CLASS_TABLESIZE + DR_REP_TABLESIZE) - -#define DR_CLASS_SHIFT UINT32_C(16) -#define DR_CLASS_MASK (UINT32_C(0xFFFF) << DR_CLASS_SHIFT) -#define DR_CLASS(d) (((d) & DR_CLASS_MASK) >> DR_CLASS_SHIFT) - -#define DR_TTREP_SHIFT UINT32_C(0) -#define DR_TTREP_MASK (UINT32_C(0xFF) << DR_TTREP_SHIFT) -#define DR_TTREP(d) (((d) & DR_TTREP_MASK) >> DR_TTREP_SHIFT) - -#define DR_ISNASTY_SHIFT UINT32_C(8) -#define DR_ISNASTY_MASK (UINT32_C(0xFF) << DR_ISNASTY_SHIFT) -#define DR_ISNASTY(d) (((d) & DR_ISNASTY_MASK) >> DR_ISNASTY_SHIFT) - STATIC uint64_t coord_dreoesep_nosym(cube_t); STATIC cube_t invcoord_dreoesep_nosym(uint64_t); +STATIC cube_t coordinate_dr_merge(cube_t, cube_t); STATIC uint64_t coordinate_dr_coord(cube_t, const void *); STATIC cube_t coordinate_dr_cube(uint64_t, const void *); STATIC bool coordinate_dr_isnasty(uint64_t, const void *); STATIC size_t coordinate_dr_gendata(void *); +/* TODO: remove the following two when all coordinates are converted to unsigned */ +STATIC uint64_t coord_co_u(cube_t c) { return (uint64_t)coord_co(c); } +STATIC cube_t invcoord_co_u(uint64_t i) { return invcoord_co((int64_t)i); } + STATIC coord_t coordinate_dr = { .name = "DR", .coord = &coordinate_dr_coord, @@ -40,6 +29,16 @@ STATIC coord_t coordinate_dr = { [AXIS_FB] = TRANS_FDr, }, .is_admissible = &solution_lastqt_cw, + .sym = { + .classes = DREOESEP_CLASSES, + .max = DREOESEP_MAX, + .coord = &coord_dreoesep_nosym, + .cube = &invcoord_dreoesep_nosym, + .max2 = POW_3_7, + .coord2 = &coord_co_u, + .cube2 = &invcoord_co_u, + .merge = &coordinate_dr_merge, + }, }; STATIC uint64_t @@ -67,114 +66,37 @@ invcoord_dreoesep_nosym(uint64_t coord) return cube; } +STATIC cube_t +coordinate_dr_merge(cube_t c1, cube_t c2) +{ + cube_t merged; + + merged = c1; + copy_corners(&merged, c2); + + return merged; +} + STATIC uint64_t coordinate_dr_coord(cube_t cube, const void *data) { - const char *datanoinfo; - const uint32_t *data32; - uint32_t d; - cube_t transformed; - - datanoinfo = (const char *)data + INFOSIZE; - data32 = (const uint32_t *)datanoinfo; - d = data32[coord_dreoesep_nosym(cube)]; - transformed = transform(cube, DR_TTREP(d)); - - return DR_CLASS(d) * POW_3_7 + coord_co(transformed); + return coord_coord_generic(&coordinate_dr, cube, data); } STATIC cube_t -coordinate_dr_cube(uint64_t coord, const void *data) +coordinate_dr_cube(uint64_t i, const void *data) { - const char *datanoinfo; - const uint32_t *rep32; - cube_t cube; - - datanoinfo = (const char *)data + INFOSIZE; - rep32 = (const uint32_t *)(datanoinfo + DR_CLASS_TABLESIZE); - cube = invcoord_dreoesep_nosym(rep32[coord / POW_3_7]); - copy_corners(&cube, invcoord_co(coord % POW_3_7)); - - return cube; + return coord_cube_generic(&coordinate_dr, i, data); } STATIC bool -coordinate_dr_isnasty(uint64_t coord, const void *data) +coordinate_dr_isnasty(uint64_t i, const void *data) { - const char *datanoinfo; - const uint32_t *classttrep, *rep32; - uint32_t r; - - datanoinfo = (const char *)data + INFOSIZE; - classttrep = (const uint32_t *)datanoinfo; - rep32 = (const uint32_t *)(datanoinfo + DR_CLASS_TABLESIZE); - r = rep32[coord / POW_3_7]; - - return DR_ISNASTY(classttrep[r]); + return coord_isnasty_generic(&coordinate_dr, i, data); } STATIC size_t coordinate_dr_gendata(void *data) { - uint64_t i, j, n, t, nasty; - char *datanoinfo; - uint32_t *classttrep, *rep; - cube_t c; - tableinfo_t info; - - if (data == NULL) - goto coordinate_dr_gendata_returnsize; - - datanoinfo = (char *)data + INFOSIZE; - classttrep = (uint32_t *)datanoinfo; - rep = classttrep + (DR_CLASS_TABLESIZE / sizeof(uint32_t)); - memset(data, 0xFF, DR_COORD_DATASIZE); - - info = (tableinfo_t) { - .solver = "coord data for DR", - .type = TABLETYPE_SPECIAL, - .infosize = INFOSIZE, - .fullsize = DR_COORD_DATASIZE, - .hash = 0, - .entries = DREOESEP_CLASSES + DREOESEP_MAX, - .classes = DREOESEP_CLASSES, - .bits = 32, - .base = 0, - .maxvalue = 0, - .next = 0 - }; - - for (i = 0, n = 0; i < COMB_12_4 * POW_2_11; i++) { - if (classttrep[i] != 0xFFFFFFFF) - continue; - - c = invcoord_dreoesep_nosym(i); - for (t = 1, nasty = 0; t < NTRANS && !nasty; t++) { - if (!((UINT64_C(1) << t) & coordinate_dr.trans_mask)) - continue; - - nasty = i == coord_dreoesep_nosym(transform(c, t)); - } - - for (t = 0; t < NTRANS; t++) { - if (!((UINT64_C(1) << t) & coordinate_dr.trans_mask)) - continue; - - j = coord_dreoesep_nosym(transform(c, t)); - classttrep[j] = - (n << DR_CLASS_SHIFT) | - (nasty << DR_ISNASTY_SHIFT) | - (inverse_trans(t) << DR_TTREP_SHIFT); - } - rep[n++] = i; - } - - writetableinfo(&info, DR_COORD_DATASIZE, data); - - DBG_ASSERT(n == DREOESEP_CLASSES, 0, - "dr coordinate data: computed %" PRIu64 " classes, " - "expected %" PRIu64 "\n", n, DREOESEP_CLASSES); - -coordinate_dr_gendata_returnsize: - return DR_COORD_DATASIZE; + return coord_gendata_generic(&coordinate_dr, data); } diff --git a/src/solvers/coord/eo.h b/src/solvers/coord/eo.h @@ -18,6 +18,7 @@ STATIC coord_t coordinate_eo = { [AXIS_FB] = TRANS_UFr, }, .is_admissible = &solution_lastqt_cw, + .sym = {0}, }; STATIC uint64_t diff --git a/src/solvers/coord/types_macros.h b/src/solvers/coord/types_macros.h @@ -1,6 +1,29 @@ -#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)) +#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)) + +#define COORD_CLASS_SHIFT UINT32_C(16) +#define COORD_CLASS_MASK (UINT32_C(0xFFFF) << COORD_CLASS_SHIFT) +#define COORD_CLASS(d) (((d) & COORD_CLASS_MASK) >> COORD_CLASS_SHIFT) + +#define COORD_TTREP_SHIFT UINT32_C(0) +#define COORD_TTREP_MASK (UINT32_C(0xFF) << COORD_TTREP_SHIFT) +#define COORD_TTREP(d) (((d) & COORD_TTREP_MASK) >> COORD_TTREP_SHIFT) + +#define COORD_ISNASTY_SHIFT UINT32_C(8) +#define COORD_ISNASTY_MASK (UINT32_C(0xFF) << COORD_ISNASTY_SHIFT) +#define COORD_ISNASTY(d) (((d) & COORD_ISNASTY_MASK) >> COORD_ISNASTY_SHIFT) + +typedef struct { + size_t classes; + uint64_t max; + uint64_t (*coord)(cube_t); + cube_t (*cube)(uint64_t); + uint64_t max2; + uint64_t (*coord2)(cube_t); + cube_t (*cube2)(uint64_t); + cube_t (*merge)(cube_t, cube_t); +} symcoord_t; typedef struct { const char name[255]; @@ -13,4 +36,5 @@ typedef struct { uint64_t trans_mask; uint8_t axistrans[3]; bool (*is_admissible)(const solution_moves_t[static 1]); + symcoord_t sym; } coord_t;