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 1e1fd628207034b0412c50e289f146d34c5baf71
parent bfb7b1ab9d2c85a256c42c006060ffe7c2652638
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Fri, 14 Mar 2025 16:18:29 +0100

Replaced datasize with solverinfo

Diffstat:
MTODO_COORDINATES | 2++
Mpython/nissy_module.c | 26++++++++++++++++----------
Mshell/shell.c | 55+++++++++++++++++++++++++++++++------------------------
Msrc/nissy.c | 37++++++++++++++++++++++++++++++++-----
Msrc/nissy.h | 14++++++++++----
Msrc/solvers/coord/common.h | 18++++++++++++++++++
Msrc/solvers/coord/types_macros.h | 2+-
Mtools/000_gendata/gendata.c | 6+++---
Mtools/100_checkdata/checkdata.c | 6+++---
Mtools/300_solve_small/solve_small.c | 4++--
Mtools/301_solve_file/solve_file.c | 4++--
Mtools/302_solve_multisol/solve_multisol.c | 4++--
Mtools/400_solvetest/solve_test.c | 4++--
Mtools/tool.h | 26++++++++++++++++----------
14 files changed, 140 insertions(+), 68 deletions(-)

diff --git a/TODO_COORDINATES b/TODO_COORDINATES @@ -1,4 +1,5 @@ - coord solver + - add checkdata for coord - return to fully qualified solver name x undo chnages to API - add a parameter to gendata to get a shortname (filename) for the table @@ -30,3 +31,4 @@ - refactor common parts of coord and h48 solvers - move parse_h48 to h48 module? + then maybe do like for coordinate and exclude the "h48" part diff --git a/python/nissy_module.c b/python/nissy_module.c @@ -219,27 +219,33 @@ getcube(PyObject *self, PyObject *args) return string_result(err, result); } -PyDoc_STRVAR(datasize_doc, -"datasize(solver)\n" +PyDoc_STRVAR(solverinfo_doc, +"solverinfo(solver)\n" "--\n\n" -"Returns the size of the data (pruning table) for the given solver\n" +"Returns the size and the short name of the data for the given solver\n" "\n" "Parameters:\n" " - solver: the name of the solver\n" "\n" -"Returns: the size of the data for the solver, in bytes\n" +"Returns: a pair containing the size and the short name " +"of the data for the solver, in bytes\n" ); static PyObject * -datasize(PyObject *self, PyObject *args) +solverinfo(PyObject *self, PyObject *args) { long long result; const char *solver; + char buf[NISSY_DATAID_SIZE]; + PyObject *py_result, *py_buf; if (!PyArg_ParseTuple(args, "s", &solver)) return NULL; - result = nissy_datasize(solver); - return long_result(result); + result = nissy_solverinfo(solver, buf); + + py_result = PyLong_FromLong(result); + py_buf = PyUnicode_FromString(buf); + return PyTuple_Pack(2, py_result, py_buf); } PyDoc_STRVAR(gendata_doc, @@ -257,12 +263,12 @@ gendata(PyObject *self, PyObject *args) { long long size, err; const char *solver; - char *buf; + char *buf, dataid[NISSY_DATAID_SIZE]; if (!PyArg_ParseTuple(args, "s", &solver)) return NULL; - size = nissy_datasize(solver); + size = nissy_solverinfo(solver, dataid); if (!check_error(size)) return NULL; @@ -394,7 +400,7 @@ static PyMethodDef nissy_methods[] = { { "applytrans", applytrans, METH_VARARGS, applytrans_doc }, { "convert", convert, METH_VARARGS, convert_doc }, { "getcube", getcube, METH_VARARGS, getcube_doc }, - { "datasize", datasize, METH_VARARGS, datasize_doc }, + { "solverinfo", solverinfo, METH_VARARGS, solverinfo_doc }, { "gendata", gendata, METH_VARARGS, gendata_doc }, { "checkdata", checkdata, METH_VARARGS, checkdata_doc }, { "solve", solve, METH_VARARGS, solve_doc }, diff --git a/shell/shell.c b/shell/shell.c @@ -65,7 +65,7 @@ static int64_t applytrans_exec(args_t *); static int64_t frommoves_exec(args_t *); static int64_t convert_exec(args_t *); static int64_t randomcube_exec(args_t *); -static int64_t datasize_exec(args_t *); +static int64_t solverinfo_exec(args_t *); static int64_t gendata_exec(args_t *); static int64_t solve_exec(args_t *); static int64_t solve_scramble_exec(args_t *); @@ -180,11 +180,11 @@ struct { randomcube_exec ), COMMAND( - "datasize", - "datasize " FLAG_SOLVER " SOLVER", - "Return the size in bytes of the data table used by " - "SOLVER when called with the given OPTIONS.", - datasize_exec + "solverinfo", + "solverinfo " FLAG_SOLVER " SOLVER", + "Return the size in bytes and the id of the data table " + "used by SOLVER when called with the given OPTIONS.", + solverinfo_exec ), COMMAND( "gendata", @@ -340,14 +340,15 @@ randomcube_exec(args_t *args) } static int64_t -datasize_exec(args_t *args) +solverinfo_exec(args_t *args) { int64_t ret; + char buf[NISSY_DATAID_SIZE]; - ret = nissy_datasize(args->str_solver); + ret = nissy_solverinfo(args->str_solver, buf); if (ret < 0) fprintf(stderr, "Unknown error (make sure solver is valid)\n"); - printf("%" PRId64 "\n", ret); + printf("%" PRId64 "\n%s\n", ret, buf); return ret; } @@ -357,14 +358,22 @@ gendata_exec(args_t *args) { int i; FILE *file; - char *buf, path[MAX_PATH_LENGTH]; + char *buf, path[MAX_PATH_LENGTH], dataid[NISSY_DATAID_SIZE]; int64_t ret, size; size_t written; + size = nissy_solverinfo(args->str_solver, dataid); + + if (size < 0) { + fprintf(stderr, "gendata: unknown solver %s\n", + args->str_solver); + return -3; + } + /* TODO: should give warning if overwriting existing file */ for (i = 0; tablepaths[i] != NULL; i++) { strcpy(path, tablepaths[i]); - strcat(path, args->str_solver); + strcat(path, dataid); file = fopen(path, "wb"); if (file != NULL) break; @@ -376,16 +385,6 @@ gendata_exec(args_t *args) return -2; } - size = nissy_datasize(args->str_solver); - - if (size < 0) { - fprintf(stderr, - "Unknown error in retrieving data size" - "(make sure solver is valid)\n"); - fclose(file); - return -3; - } - buf = malloc(size); ret = nissy_gendata(args->str_solver, size, buf); @@ -427,15 +426,24 @@ solve_exec(args_t *args) uint8_t nissflag; FILE *file; char *buf, solutions[SOLUTIONS_BUFFER_SIZE], path[MAX_PATH_LENGTH]; + char dataid[NISSY_DATAID_SIZE]; long long stats[NISSY_SIZE_SOLVE_STATS]; int64_t ret, gendata_ret, size; size_t read; nissflag = NISSY_NISSFLAG_NORMAL; /* TODO: parse str_nisstype */ + size = nissy_solverinfo(args->str_solver, dataid); + + if (size < 0) { + fprintf(stderr, "solve: unknown solver %s\n", + args->str_solver); + return size; + } + for (i = 0; tablepaths[i] != NULL; i++) { strcpy(path, tablepaths[i]); - strcat(path, args->str_solver); + strcat(path, dataid); file = fopen(path, "rb"); if (file != NULL) break; @@ -454,7 +462,7 @@ solve_exec(args_t *args) if (file == NULL) { for (i = 0; tablepaths[i] != NULL; i++) { strcpy(path, tablepaths[i]); - strcat(path, args->str_solver); + strcat(path, dataid); file = fopen(path, "rb"); if (file != NULL) break; @@ -467,7 +475,6 @@ solve_exec(args_t *args) return -1; } - size = nissy_datasize(args->str_solver); buf = malloc(size); read = fread(buf, size, 1, file); fclose(file); diff --git a/src/nissy.c b/src/nissy.c @@ -19,6 +19,7 @@ STATIC bool distribution_equal(const uint64_t [static INFO_DISTRIBUTION_LEN], const uint64_t [static INFO_DISTRIBUTION_LEN], uint8_t); STATIC long long write_result(cube_t, char [static NISSY_SIZE_B32]); STATIC size_t my_strnlen(const char *, size_t); +STATIC long long nissy_dataid(const char *, char [static NISSY_DATAID_SIZE]); STATIC long long nissy_gendata_unsafe( const char *, unsigned long long, char *); @@ -412,11 +413,37 @@ nissy_datainfo( return NISSY_OK; } +STATIC long long +nissy_dataid(const char *solver, char dataid[static NISSY_DATAID_SIZE]) +{ + if (!strncmp(solver, "h48", 3)) { + uint8_t h, k; + long long err; + if ((err = parse_h48_solver(solver, &h, &k)) != NISSY_OK) + return err; + /* TODO: also check that h and k are admissible */ + else strcpy(dataid, solver); + return err; + /* TODO: do this when moved parser */ + /* return dataid_h48(solver, dataid); */ + } else if (!strncmp(solver, "coord_", 6)) { + return dataid_coord(solver+6, dataid); + } else { + LOG("gendata: unknown solver %s\n", solver); + return NISSY_ERROR_INVALID_SOLVER; + } +} + long long -nissy_datasize( - const char *solver +nissy_solverinfo( + const char *solver, + char dataid[static NISSY_DATAID_SIZE] ) { + long long err; + if ((err = nissy_dataid(solver, dataid)) != NISSY_OK) + return err; + /* gendata() handles a NULL *data as a "dryrun" request */ return nissy_gendata_unsafe(solver, 0, NULL); } @@ -447,7 +474,7 @@ nissy_gendata_unsafe( } if ((size_t)data % 8 != 0) { - LOG("nissy_datainfo: buffere is not 8-byte aligned\n"); + LOG("nissy_gendata: buffere is not 8-byte aligned\n"); return NISSY_ERROR_DATA; } @@ -478,7 +505,7 @@ nissy_checkdata( int64_t err; if ((size_t)data % 8 != 0) { - LOG("nissy_datainfo: buffere is not 8-byte aligned\n"); + LOG("nissy_checkdata: buffere is not 8-byte aligned\n"); return NISSY_ERROR_DATA; } @@ -560,7 +587,7 @@ nissy_solve( } if ((size_t)data % 8 != 0) { - LOG("nissy_datainfo: buffere is not 8-byte aligned\n"); + LOG("nissy_solve: buffere is not 8-byte aligned\n"); return NISSY_ERROR_DATA; } diff --git a/src/nissy.h b/src/nissy.h @@ -25,6 +25,7 @@ for example 'rotation UF' or 'mirrored BL'. #define NISSY_SIZE_H48 88U #define NISSY_SIZE_TRANSFORMATION 12U #define NISSY_SIZE_SOLVE_STATS 10U +#define NISSY_DATAID_SIZE 255U /* Flags for NISS options */ #define NISSY_NISSFLAG_NORMAL 1U @@ -191,11 +192,15 @@ nissy_getcube( ); /* -Compute the size of the data generated by nissy_gendata, when called with -the same parameters, or -1 in case of error. +Compute the size of the data generated by nissy_gendata when called for +the given solver, and other useful information. Parameters: solver - The name of the solver. + dataid - An identifier for the data computed for the solver. Different + solver may use equivalent data. This identifier can be used + e.g. as a filename or database key to save and retrieve the + correct data for each solver, without duplication. Return values: NISSY_ERROR_INVALID_SOLVER - The given solver is not known. @@ -204,8 +209,9 @@ Return values: Any value >= 0 - The size of the data, in bytes. */ long long -nissy_datasize( - const char *solver +nissy_solverinfo( + const char *solver, + char dataid[static NISSY_DATAID_SIZE] ); /* diff --git a/src/solvers/coord/common.h b/src/solvers/coord/common.h @@ -7,6 +7,7 @@ STATIC void append_coord_name(const coord_t *, char *); STATIC coord_t *parse_coord(const char *, int); STATIC uint8_t parse_axis(const char *, int); STATIC void parse_coord_and_axis(const char *, int, coord_t **, uint8_t *); +STATIC int64_t dataid_coord(const char *, char [static NISSY_DATAID_SIZE]); STATIC void append_coord_name(const coord_t *coord, char *str) @@ -61,3 +62,20 @@ parse_coord_and_axis(const char *str, int n, coord_t **coord, uint8_t *axis) if (axis != NULL) *axis = i == n ? UINT8_ERROR : parse_axis(str+i+1, n-i-1); } + +STATIC int64_t +dataid_coord(const char *ca, char dataid[static NISSY_DATAID_SIZE]) +{ + coord_t *c; + + parse_coord_and_axis(ca, strlen(ca), &c, NULL); + + if (c == NULL) { + LOG("dataid_coord: cannot parse coordinate from '%s'\n", ca); + return NISSY_ERROR_INVALID_SOLVER; + } + + strcpy(dataid, c->name); + + return NISSY_OK; +} diff --git a/src/solvers/coord/types_macros.h b/src/solvers/coord/types_macros.h @@ -3,7 +3,7 @@ #define COORD_MASK(i) (UINT8_C(0xF) << COORD_SHIFT(i)) typedef struct { - char name[255]; + const char name[255]; uint64_t (*coord)(cube_t, const void *); cube_t (*cube)(uint64_t, const void *); size_t (*gendata)(void *); diff --git a/tools/000_gendata/gendata.c b/tools/000_gendata/gendata.c @@ -8,9 +8,9 @@ static void run(void) { int64_t size; bool consistent, expected; - char *buf, filename[1024]; + char *buf, filename[1024], dataid[NISSY_DATAID_SIZE]; - size = generatetable(solver, &buf); + size = generatetable(solver, &buf, dataid); switch (size) { case -1: return; @@ -23,7 +23,7 @@ run(void) { if (consistent && expected) { printf("\n"); printf("Generated %" PRId64 " bytes.\n", size); - sprintf(filename, "tables/%s", solver); + sprintf(filename, "tables/%s", dataid); writetable(buf, size, filename); } if (!consistent) diff --git a/tools/100_checkdata/checkdata.c b/tools/100_checkdata/checkdata.c @@ -6,13 +6,13 @@ char *solver, *filename; static void run(void) { long long int size, result; - char *buf; + char *buf, dataid[NISSY_DATAID_SIZE]; FILE *f; - size = nissy_datasize(solver); + size = nissy_solverinfo(solver, dataid); if (size <= 0) { - printf("Error in datasize\n"); + printf("Error in solverinfo\n"); return; } diff --git a/tools/300_solve_small/solve_small.c b/tools/300_solve_small/solve_small.c @@ -46,7 +46,7 @@ void run(void) { } int main(int argc, char **argv) { - char filename[255]; + char filename[255], dataid[NISSY_DATAID_SIZE]; if (argc < 2) { printf("Error: not enough arguments. " @@ -63,7 +63,7 @@ int main(int argc, char **argv) { if (getdata(solver, &buf, filename) != 0) return 1; - size = nissy_datasize(solver); + size = nissy_solverinfo(solver, dataid); timerun(run); diff --git a/tools/301_solve_file/solve_file.c b/tools/301_solve_file/solve_file.c @@ -33,7 +33,7 @@ void run(void) { } int main(int argc, char **argv) { - char filename[255], *scrfilename; + char filename[255], dataid[NISSY_DATAID_SIZE], *scrfilename; FILE *scrfile; if (argc < 3) { @@ -52,7 +52,7 @@ int main(int argc, char **argv) { if (getdata(solver, &buf, filename) != 0) return 1; - size = nissy_datasize(solver); + size = nissy_solverinfo(solver, dataid); if ((scrfile = fopen(scrfilename, "r")) == NULL) { printf("Error: could not read given file '%s'.\n", diff --git a/tools/302_solve_multisol/solve_multisol.c b/tools/302_solve_multisol/solve_multisol.c @@ -39,7 +39,7 @@ void run(void) { } int main(int argc, char **argv) { - char filename[255]; + char filename[255], dataid[NISSY_DATAID_SIZE]; if (argc < 3) { printf("Error: not enough arguments. " @@ -57,7 +57,7 @@ int main(int argc, char **argv) { if (getdata(solver, &buf, filename) != 0) return 1; - size = nissy_datasize(solver); + size = nissy_solverinfo(solver, dataid); timerun(run); diff --git a/tools/400_solvetest/solve_test.c b/tools/400_solvetest/solve_test.c @@ -94,7 +94,7 @@ void run(void) { } int main(int argc, char **argv) { - char filename[255]; + char filename[255], dataid[NISSY_DATAID_SIZE]; if (argc < 2) { printf("Error: not enough arguments. " @@ -110,7 +110,7 @@ int main(int argc, char **argv) { if (getdata(solver, &buf, filename) != 0) return 1; - size = nissy_datasize(solver); + size = nissy_solverinfo(solver, dataid); timerun(run); diff --git a/tools/tool.h b/tools/tool.h @@ -13,7 +13,8 @@ static void log_stderr(const char *, ...); static void log_stdout(const char *, ...); static double timerun(void (*)(void)); static void writetable(const char *, int64_t, const char *); -static long long int generatetable(const char *, char **); +static long long int generatetable(const char *, char **, + char [static NISSY_DATAID_SIZE]); static long long int derivetable( const char *, const char *, const char *, char **); static int getdata(const char *, char **, const char *); @@ -86,11 +87,15 @@ writetable(const char *buf, int64_t size, const char *filename) } static long long int -generatetable(const char *solver, char **buf) +generatetable( + const char *solver, + char **buf, + char dataid[static NISSY_DATAID_SIZE] +) { long long int size, gensize; - size = nissy_datasize(solver); + size = nissy_solverinfo(solver, dataid); if (size < 0) { printf("Error getting table size.\n"); return -1; @@ -120,7 +125,7 @@ derivetable( { uint8_t h, k; long long int size, gensize; - char *fulltable; + char *fulltable, dataid[NISSY_DATAID_SIZE]; if (getdata(solver_large, &fulltable, filename_large) != 0) { printf("Error reading full table.\n"); @@ -128,7 +133,7 @@ derivetable( goto derivetable_error_nofree; } - size = nissy_datasize(solver_small); + size = nissy_solverinfo(solver_small, dataid); if (size == -1) { printf("Error getting table size.\n"); gensize = -2; @@ -164,10 +169,11 @@ getdata( ) { long long int size, sizeread; FILE *f; + char dataid[NISSY_DATAID_SIZE]; if ((f = fopen(filename, "rb")) == NULL) { printf("Table file not found, generating it.\n"); - size = generatetable(solver, buf); + size = generatetable(solver, buf, dataid); switch (size) { case -1: goto getdata_error_nofree; @@ -179,7 +185,7 @@ getdata( } } else { printf("Reading tables from file %s\n", filename); - size = nissy_datasize(solver); + size = nissy_solverinfo(solver, dataid); *buf = malloc(size); sizeread = fread(*buf, size, 1, f); fclose(f); @@ -203,10 +209,10 @@ gendata_run( uint64_t expected[static 21] ) { long long int size; - char *buf, filename[1024]; + char *buf, filename[1024], dataid[NISSY_DATAID_SIZE]; - sprintf(filename, "tables/%s", solver); - size = generatetable(solver, &buf); + size = generatetable(solver, &buf, dataid); + sprintf(filename, "tables/%s", dataid); switch (size) { case -1: return;