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 0b32395de2500ad87e15fbb0ff4a852e313037e9
parent bb09e52a7481718ae1fe324d16b99970450908f8
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Fri, 27 Sep 2024 08:19:53 +0200

First try for derive tables

Diffstat:
Msrc/nissy.h | 7+++++++
Msrc/solvers/h48/gendata_h48.h | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
Atools/1002_derive_h48h0k2/derive_h48h0k2.c | 21+++++++++++++++++++++
Atools/nissy_extra.h | 6++++++
Mtools/tool.h | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 186 insertions(+), 7 deletions(-)

diff --git a/src/nissy.h b/src/nissy.h @@ -86,6 +86,13 @@ int64_t nissy_gendata( void *generated_data ); +/* Temporarily added to test h48 intermediate tables */ +int64_t nissy_derivedata( + const char *options, + const void *fulltable, + void *generated_data +); + /* Print information on a data table via the provided callback writer */ int64_t nissy_datainfo( const void *table, diff --git a/src/solvers/h48/gendata_h48.h b/src/solvers/h48/gendata_h48.h @@ -103,7 +103,7 @@ STATIC_INLINE bool gendata_h48k2_dfs_stop(cube_t, int8_t, h48k2_dfs_arg_t *); STATIC size_t gendata_h48k2_realcoord(gendata_h48_arg_t *); STATIC void gendata_h48k2_dfs(h48k2_dfs_arg_t *arg); STATIC void * gendata_h48k2_runthread(void *); -STATIC tableinfo_t makeinfo_h48k2(gendata_h48_arg_t *, uint8_t); +STATIC tableinfo_t makeinfo_h48k2(gendata_h48_arg_t *); STATIC uint32_t *get_cocsepdata_ptr(const void *); STATIC uint8_t *get_h48data_ptr(const void *); @@ -112,6 +112,8 @@ STATIC_INLINE uint8_t get_h48_pval(const uint8_t *, int64_t, uint8_t); STATIC_INLINE void set_h48_pval(uint8_t *, int64_t, uint8_t, uint8_t); STATIC_INLINE uint8_t get_h48_bound(cube_t, uint32_t, uint8_t, uint8_t, uint8_t *); +size_t gendata_h48_derive(uint8_t, const void *, void *); + STATIC uint64_t gendata_h48short(gendata_h48short_arg_t *arg) { @@ -387,7 +389,7 @@ gendata_h48k2(gendata_h48_arg_t *arg) [11] = 10 }; - uint8_t t, selectedbase, *table; + uint8_t t, *table; int64_t j; uint64_t i, ii, inext, count; h48map_t shortcubes; @@ -414,8 +416,9 @@ gendata_h48k2(gendata_h48_arg_t *arg) }; gendata_h48short(&shortarg); - selectedbase = arg->base < 20 ? arg->base : base[arg->h]; - arg->info = makeinfo_h48k2(arg, selectedbase); + if (arg->base >= 20) + arg->base = base[arg->h]; + arg->info = makeinfo_h48k2(arg); inext = count = 0; pthread_mutex_init(&shortcubes_mutex, NULL); @@ -425,7 +428,7 @@ gendata_h48k2(gendata_h48_arg_t *arg) dfsarg[i] = (h48k2_dfs_arg_t){ .h = arg->h, .k = arg->k, - .base = selectedbase, + .base = arg->base, .shortdepth = shortdepth, .cocsepdata = arg->cocsepdata, .table = table, @@ -637,7 +640,7 @@ gendata_h48k2_realcoord_runthread(void *arg) } STATIC tableinfo_t -makeinfo_h48k2(gendata_h48_arg_t *arg, uint8_t base) +makeinfo_h48k2(gendata_h48_arg_t *arg) { tableinfo_t info; @@ -651,7 +654,7 @@ makeinfo_h48k2(gendata_h48_arg_t *arg, uint8_t base) .classes = 0, .h48h = arg->h, .bits = 2, - .base = base, + .base = arg->base, .maxvalue = 3, .next = 0, }; @@ -695,3 +698,81 @@ get_h48_bound(cube_t cube, uint32_t cdata, uint8_t h, uint8_t k, uint8_t *table) coord = coord_h48_edges(cube, COCLASS(cdata), TTREP(cdata), h); return get_h48_pval(table, coord, k); } + +size_t +gendata_h48_derive(uint8_t h, const void *fulltable, void *buf) +{ + size_t cocsepsize, h48size; + uint8_t val_full, val_derive, val_new, *h48full, *h48derive; + int64_t i, j, h48max; + gendata_h48_arg_t arg; + tableinfo_t cocsepinfo, fulltableinfo; + + /* Initializing values in case of error */ + fulltableinfo.bits = 2; + fulltableinfo.base = 8; + + readtableinfo_n(fulltable, 2, &fulltableinfo); + arg.h = h; + arg.k = fulltableinfo.bits; + arg.maxdepth = 20; + arg.buf = buf; + arg.cocsepdata = (uint32_t *)((char *)buf + INFOSIZE); + arg.base = fulltableinfo.base; + arg.info = makeinfo_h48k2(&arg); + + /* Technically this step is redundant, except that we + need selfsim and crep */ + cocsepsize = gendata_cocsep(buf, arg.selfsim, arg.crep); + arg.h48buf = (char *)buf + cocsepsize; + h48size = H48_TABLESIZE(h, arg.k) + INFOSIZE; + + if (buf == NULL) + goto gendata_h48_derive_return_size; + + if (!readtableinfo(buf, &cocsepinfo)) { + LOG("gendata_h48: could not read info for cocsep table\n"); + goto gendata_h48_derive_error; + } + + cocsepinfo.next = cocsepsize; + if (!writetableinfo(&cocsepinfo, buf)) { + LOG("gendata_h48_derive: could not write info for cocsep table" + " with updated 'next' value\n"); + goto gendata_h48_derive_error; + } + + h48full = (uint8_t *)fulltable + INFOSIZE; + h48derive = (uint8_t *)arg.h48buf + INFOSIZE; + memset(h48derive, 0xFF, H48_TABLESIZE(h, arg.k)); + memset(arg.info.distribution, 0, + INFO_DISTRIBUTION_LEN * sizeof(uint64_t)); + + h48max = H48_COORDMAX(11); + for (i = 0; i < h48max; i++) { + if (i % INT64_C(1000000000) == 0) + LOG("Processing %" PRId64 "th coordinate\n", i); + j = i >> (int64_t)(11-h); + val_full = get_h48_pval(h48full, i, arg.k); + val_derive = get_h48_pval(h48derive, j, arg.k); + val_new = MIN(val_full, val_derive); + set_h48_pval(h48derive, j, arg.k, val_new); + } + + h48max = H48_COORDMAX(h); + for (i = 0; i < h48max; i++) { + val_derive = get_h48_pval(h48derive, i, arg.k); + arg.info.distribution[val_derive]++; + } + + if (!writetableinfo(&arg.info, buf)) { + LOG("gendata_h48_derive: could not write info for table\n"); + goto gendata_h48_derive_error; + } + +gendata_h48_derive_return_size: + return cocsepsize + h48size; + +gendata_h48_derive_error: + return 0; +} diff --git a/tools/1002_derive_h48h0k2/derive_h48h0k2.c b/tools/1002_derive_h48h0k2/derive_h48h0k2.c @@ -0,0 +1,21 @@ +#include "../tool.h" + +uint64_t expected[21] = { + /* Base value is 8 */ + [0] = 5473562, + [1] = 34776317, + [2] = 68566704, + [3] = 8750867, +}; + +void run(void) { + derivedata_run(0, "tables/h48h0k2_derived", expected); +} + +int main(void) { + nissy_setlogger(log_stderr); + + timerun(run, "benchmark derivedata_h48 h = 0, k = 2"); + + return 0; +} diff --git a/tools/nissy_extra.h b/tools/nissy_extra.h @@ -0,0 +1,6 @@ +/* +This header file exposes certain functions that are meant to be used +for testing purposes only. +*/ + +size_t gendata_h48_derive(uint8_t, const void *, void *); diff --git a/tools/tool.h b/tools/tool.h @@ -6,14 +6,17 @@ #include <stdlib.h> #include "../src/nissy.h" +#include "nissy_extra.h" static void log_stderr(const char *, ...); static void log_stdout(const char *, ...); static double timerun(void (*)(void), const char *); static void writetable(const char *, int64_t, const char *); static int64_t generatetable(const char *, const char *, char **); +static int64_t derivetable(uint8_t, char **); static int getdata(const char *, const char *, char **, const char *); static void gendata_run(const char *, const char *, const char *, uint64_t[static 21]); +static void derivedata_run(uint8_t, const char *, uint64_t[static 21]); static void log_stderr(const char *str, ...) @@ -109,6 +112,41 @@ generatetable(const char *solver, const char *options, char **buf) return gensize; } +static int64_t +derivetable(uint8_t h, char **buf) +{ + int64_t size, gensize; + char *fulltable; + + char options[20] = " ;2;20"; /* Fixed for k = 2 for now */ + options[0] = (char)(h + '0'); /* h = 10 not supported for now */ + + /* Support only b8 for now */ + if (getdata("h48", "11;2;20", &fulltable, "tables/h48h11k2_b8") != 0) { + printf("Error reading full table.\n"); + return -1; + } + + size = nissy_datasize("h48", options); + if (size == -1) { + printf("Error getting table size.\n"); + free(fulltable); + return -1; + } + + *buf = malloc(size); + gensize = gendata_h48_derive(h, fulltable, *buf); + + if (gensize != size) { + fprintf(stderr, "Error deriving table\n"); + free(fulltable); + return -2; + } + + free(fulltable); + return gensize; +} + static int getdata( const char *solver, @@ -182,3 +220,29 @@ gendata_run( gendata_run_finish: free(buf); } + +static void +derivedata_run(uint8_t h, const char *filename, uint64_t expected[static 21]) +{ + int64_t size; + char *buf; + + size = derivetable(h, &buf); + switch (size) { + case -1: + return; + case -2: + goto derivedata_run_finish; + default: + nissy_datainfo(buf, write_stdout); + printf("\n"); + printf("Succesfully generated %" PRId64 " bytes. " + "See above for details on the tables.\n", size); + + writetable(buf, size, filename); + break; + } + +derivedata_run_finish: + free(buf); +}