diff options
| -rw-r--r-- | TODO.txt | 28 | ||||
| -rw-r--r-- | shell.c | 32 | ||||
| -rw-r--r-- | src/cube.h | 6 | ||||
| -rw-r--r-- | src/cube_public.h | 16 | ||||
| -rw-r--r-- | src/solve_h48.h | 111 | ||||
| -rw-r--r-- | tools/stats_tables_h48/stats_tables_h48.c | 69 |
6 files changed, 255 insertions, 7 deletions
| @@ -1,7 +1,29 @@ | |||
| 1 | Check stats for all tables using H48stats solver | ||
| 2 | - implement gencube | ||
| 3 | - move cubefromarray from cube_io to where needed | ||
| 4 | - implement in cube_generic | ||
| 5 | - fix in cube_public | ||
| 6 | - add tests | ||
| 7 | - test shell | ||
| 8 | - optional: dr states (just to check options) | ||
| 9 | - implement tool for stats | ||
| 10 | - output to file, only write cocsep to stdout | ||
| 11 | |||
| 12 | Bug in esep table generation | ||
| 13 | - Fails for UFRUFU, try command | ||
| 14 | ./run solve -solver H48 -options "2;20" -n 1 -M 10 -cube \ | ||
| 15 | "$(./run frommoves -moves "UFRUFU")" | ||
| 16 | - Fundamental error in how tables are generated, each coordinate has too | ||
| 17 | many representative. I need to use the big table with the full coordinate | ||
| 18 | first (h=11, ~241 billion positions, 60Gb with k=2). From this the smaller | ||
| 19 | tables can be easily deduced. | ||
| 20 | - Investigate the possibility of computing smaller tables directly in some | ||
| 21 | other way, even if slow. | ||
| 22 | - use dfs for computing big table, save distance %3 until the last two steps, | ||
| 23 | then clean the table and double loop over moves to fill the value | ||
| 24 | |||
| 1 | Solver | 25 | Solver |
| 2 | - fix and cleanup current implementation | 26 | - cleanup h48 solver |
| 3 | - fails for UFRUFU when using full table | ||
| 4 | SOMETHING IS WRONG FOR coord_h48 = 3! (pvalue 15??) | ||
| 5 | - do not copy dfsarg, change and undo | 27 | - do not copy dfsarg, change and undo |
| 6 | - implement and use premove (and test) instead of inverting | 28 | - implement and use premove (and test) instead of inverting |
| 7 | - benchmark for solve | 29 | - benchmark for solve |
| @@ -29,6 +29,7 @@ typedef struct { | |||
| 29 | int8_t maxmoves; | 29 | int8_t maxmoves; |
| 30 | int8_t optimal; | 30 | int8_t optimal; |
| 31 | int64_t maxsolutions; | 31 | int64_t maxsolutions; |
| 32 | uint8_t id[16]; | ||
| 32 | } args_t; | 33 | } args_t; |
| 33 | 34 | ||
| 34 | static void print_cube_result(int64_t, char [static 22]); | 35 | static void print_cube_result(int64_t, char [static 22]); |
| @@ -40,6 +41,7 @@ static int64_t applymoves_exec(args_t *); | |||
| 40 | static int64_t applytrans_exec(args_t *); | 41 | static int64_t applytrans_exec(args_t *); |
| 41 | static int64_t frommoves_exec(args_t *); | 42 | static int64_t frommoves_exec(args_t *); |
| 42 | static int64_t convert_exec(args_t *); | 43 | static int64_t convert_exec(args_t *); |
| 44 | static int64_t gencube_exec(args_t *); | ||
| 43 | static int64_t datasize_exec(args_t *); | 45 | static int64_t datasize_exec(args_t *); |
| 44 | static int64_t gendata_exec(args_t *); | 46 | static int64_t gendata_exec(args_t *); |
| 45 | static int64_t solve_exec(args_t *); | 47 | static int64_t solve_exec(args_t *); |
| @@ -63,6 +65,7 @@ static bool set_minmoves(int, char **, args_t *); | |||
| 63 | static bool set_maxmoves(int, char **, args_t *); | 65 | static bool set_maxmoves(int, char **, args_t *); |
| 64 | static bool set_optimal(int, char **, args_t *); | 66 | static bool set_optimal(int, char **, args_t *); |
| 65 | static bool set_maxsolutions(int, char **, args_t *); | 67 | static bool set_maxsolutions(int, char **, args_t *); |
| 68 | static bool set_id(int, char **, args_t *); | ||
| 66 | 69 | ||
| 67 | #define COMMAND(N, E) { .name = N, .exec = E } | 70 | #define COMMAND(N, E) { .name = N, .exec = E } |
| 68 | struct { | 71 | struct { |
| @@ -75,6 +78,7 @@ struct { | |||
| 75 | COMMAND("applytrans", applytrans_exec), | 78 | COMMAND("applytrans", applytrans_exec), |
| 76 | COMMAND("frommoves", frommoves_exec), | 79 | COMMAND("frommoves", frommoves_exec), |
| 77 | COMMAND("convert", convert_exec), | 80 | COMMAND("convert", convert_exec), |
| 81 | COMMAND("gencube", gencube_exec), | ||
| 78 | COMMAND("datasize", datasize_exec), | 82 | COMMAND("datasize", datasize_exec), |
| 79 | COMMAND("gendata", gendata_exec), | 83 | COMMAND("gendata", gendata_exec), |
| 80 | COMMAND("solve", solve_exec), | 84 | COMMAND("solve", solve_exec), |
| @@ -102,6 +106,7 @@ struct { | |||
| 102 | OPTION("-M", 1, set_maxmoves), | 106 | OPTION("-M", 1, set_maxmoves), |
| 103 | OPTION("-O", 1, set_optimal), | 107 | OPTION("-O", 1, set_optimal), |
| 104 | OPTION("-n", 1, set_maxsolutions), | 108 | OPTION("-n", 1, set_maxsolutions), |
| 109 | OPTION("-id", 16, set_id), | ||
| 105 | OPTION(NULL, 0, NULL) | 110 | OPTION(NULL, 0, NULL) |
| 106 | }; | 111 | }; |
| 107 | 112 | ||
| @@ -215,6 +220,18 @@ convert_exec(args_t *args) | |||
| 215 | } | 220 | } |
| 216 | 221 | ||
| 217 | static int64_t | 222 | static int64_t |
| 223 | gencube_exec(args_t *args) | ||
| 224 | { | ||
| 225 | char result[PRINTCUBE_BUFFER_SIZE]; | ||
| 226 | int64_t ret; | ||
| 227 | |||
| 228 | ret = nissy_gencube(args->id, args->str_options, result); | ||
| 229 | print_str_result(ret, result); | ||
| 230 | |||
| 231 | return ret; | ||
| 232 | } | ||
| 233 | |||
| 234 | static int64_t | ||
| 218 | datasize_exec(args_t *args) | 235 | datasize_exec(args_t *args) |
| 219 | { | 236 | { |
| 220 | int64_t ret; | 237 | int64_t ret; |
| @@ -551,6 +568,21 @@ set_maxsolutions(int argc, char **argv, args_t *args) | |||
| 551 | return parse_int64(argv[0], &args->maxsolutions); | 568 | return parse_int64(argv[0], &args->maxsolutions); |
| 552 | } | 569 | } |
| 553 | 570 | ||
| 571 | static bool | ||
| 572 | set_id(int argc, char **argv, args_t *args) | ||
| 573 | { | ||
| 574 | int i; | ||
| 575 | int64_t n; | ||
| 576 | |||
| 577 | for (i = 0; i < 16; i++) { | ||
| 578 | if (!parse_int64(argv[i], &n)) | ||
| 579 | return false; | ||
| 580 | args->id[i] = (uint8_t)n; | ||
| 581 | } | ||
| 582 | |||
| 583 | return true; | ||
| 584 | } | ||
| 585 | |||
| 554 | void log_stderr(const char *str, ...) | 586 | void log_stderr(const char *str, ...) |
| 555 | { | 587 | { |
| 556 | va_list args; | 588 | va_list args; |
| @@ -41,6 +41,12 @@ int64_t nissy_convert( | |||
| 41 | char *result | 41 | char *result |
| 42 | ); | 42 | ); |
| 43 | 43 | ||
| 44 | int64_t nissy_gencube( | ||
| 45 | uint8_t id[16], | ||
| 46 | const char *options, | ||
| 47 | char result[static 22] | ||
| 48 | ); | ||
| 49 | |||
| 44 | /* | 50 | /* |
| 45 | Returns the size of the data generated by nissy_gendata, when called with | 51 | Returns the size of the data generated by nissy_gendata, when called with |
| 46 | the same parameters, or -1 in case of error. The returned value can be | 52 | the same parameters, or -1 in case of error. The returned value can be |
diff --git a/src/cube_public.h b/src/cube_public.h index a1c4b90..fe003c9 100644 --- a/src/cube_public.h +++ b/src/cube_public.h | |||
| @@ -105,6 +105,18 @@ nissy_convert( | |||
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | int64_t | 107 | int64_t |
| 108 | nissy_gencube( | ||
| 109 | uint8_t id[16], | ||
| 110 | const char *options, | ||
| 111 | char result[static 22] | ||
| 112 | ) | ||
| 113 | { | ||
| 114 | /* TODO: compute cube from id % (number of positions) */ | ||
| 115 | /* options can be used for generating e.g. DR-state cube */ | ||
| 116 | return -1; | ||
| 117 | } | ||
| 118 | |||
| 119 | int64_t | ||
| 108 | nissy_datasize( | 120 | nissy_datasize( |
| 109 | const char *solver, | 121 | const char *solver, |
| 110 | const char *options | 122 | const char *options |
| @@ -131,6 +143,8 @@ nissy_gendata( | |||
| 131 | h = atoi(options); | 143 | h = atoi(options); |
| 132 | maxdepth = atoi(&options[i+1]); | 144 | maxdepth = atoi(&options[i+1]); |
| 133 | ret = gendata_h48(data, h, maxdepth); | 145 | ret = gendata_h48(data, h, maxdepth); |
| 146 | } else if (!strcmp(solver, "H48stats")) { | ||
| 147 | ret = gendata_cocsep(data, NULL, NULL); | ||
| 134 | } else { | 148 | } else { |
| 135 | LOG("gendata: implemented only for H48 solver\n"); | 149 | LOG("gendata: implemented only for H48 solver\n"); |
| 136 | ret = -1; | 150 | ret = -1; |
| @@ -196,6 +210,8 @@ nissy_solve( | |||
| 196 | c, minmoves, maxmoves, maxsolutions, | 210 | c, minmoves, maxmoves, maxsolutions, |
| 197 | (uint8_t)h, data, solutions); | 211 | (uint8_t)h, data, solutions); |
| 198 | ret = -1; | 212 | ret = -1; |
| 213 | } else if (!strcmp(solver, "H48stats")) { | ||
| 214 | ret = solve_h48stats(c, maxmoves, data, solutions); | ||
| 199 | } else if (!strcmp(solver, "simple")) { | 215 | } else if (!strcmp(solver, "simple")) { |
| 200 | ret = solve_simple( | 216 | ret = solve_simple( |
| 201 | c, minmoves, maxmoves, maxsolutions, optimal, solutions); | 217 | c, minmoves, maxmoves, maxsolutions, optimal, solutions); |
diff --git a/src/solve_h48.h b/src/solve_h48.h index 201c7c6..c2c541d 100644 --- a/src/solve_h48.h +++ b/src/solve_h48.h | |||
| @@ -57,6 +57,15 @@ typedef struct { | |||
| 57 | char **nextsol; | 57 | char **nextsol; |
| 58 | } dfsarg_solveh48_t; | 58 | } dfsarg_solveh48_t; |
| 59 | 59 | ||
| 60 | typedef struct { | ||
| 61 | cube_t cube; | ||
| 62 | int8_t nmoves; | ||
| 63 | int8_t depth; | ||
| 64 | uint8_t moves[MAX_SOLUTION_LENGTH]; | ||
| 65 | uint32_t *cocsepdata; | ||
| 66 | char *s; | ||
| 67 | } dfsarg_solveh48stats_t; | ||
| 68 | |||
| 60 | _static_inline int64_t coord_h48(cube_t, const uint32_t *, uint8_t); | 69 | _static_inline int64_t coord_h48(cube_t, const uint32_t *, uint8_t); |
| 61 | _static_inline int64_t coord_h48_edges(cube_t, int64_t, uint8_t, uint8_t); | 70 | _static_inline int64_t coord_h48_edges(cube_t, int64_t, uint8_t, uint8_t); |
| 62 | _static_inline cube_t invcoord_h48(int64_t, const cube_t *, uint8_t); | 71 | _static_inline cube_t invcoord_h48(int64_t, const cube_t *, uint8_t); |
| @@ -78,6 +87,9 @@ _static_inline bool solve_h48_stop(dfsarg_solveh48_t *); | |||
| 78 | _static int64_t solve_h48_dfs(dfsarg_solveh48_t *); | 87 | _static int64_t solve_h48_dfs(dfsarg_solveh48_t *); |
| 79 | _static int64_t solve_h48(cube_t, int8_t, int8_t, int8_t, uint8_t, const void *, char *); | 88 | _static int64_t solve_h48(cube_t, int8_t, int8_t, int8_t, uint8_t, const void *, char *); |
| 80 | 89 | ||
| 90 | _static int64_t solve_h48stats_dfs(dfsarg_solveh48stats_t *); | ||
| 91 | _static int64_t solve_h48stats(cube_t, int8_t, const void *, char [static 13]); | ||
| 92 | |||
| 81 | _static_inline int64_t | 93 | _static_inline int64_t |
| 82 | coord_h48(cube_t c, const uint32_t *cocsepdata, uint8_t h) | 94 | coord_h48(cube_t c, const uint32_t *cocsepdata, uint8_t h) |
| 83 | { | 95 | { |
| @@ -104,9 +116,15 @@ coord_h48_edges(cube_t c, int64_t coclass, uint8_t t, uint8_t h) | |||
| 104 | d = transform_edges(c, t); | 116 | d = transform_edges(c, t); |
| 105 | esep = coord_esep(d); | 117 | esep = coord_esep(d); |
| 106 | eo = coord_eo(d); | 118 | eo = coord_eo(d); |
| 107 | edges = (esep << (int64_t)h) + (eo >> (11 - (int64_t)h)); | 119 | edges = (esep << 11) + eo; |
| 120 | |||
| 121 | return (coclass * H48_ESIZE(11) + edges) >> (11 - (int64_t)h); | ||
| 108 | 122 | ||
| 123 | /* | ||
| 124 | TODO: decide which alternative is better, if above or below | ||
| 125 | edges = (esep << (int64_t)h) + (eo >> (11 - (int64_t)h)); | ||
| 109 | return coclass * H48_ESIZE(h) + edges; | 126 | return coclass * H48_ESIZE(h) + edges; |
| 127 | */ | ||
| 110 | } | 128 | } |
| 111 | 129 | ||
| 112 | /* | 130 | /* |
| @@ -160,7 +178,8 @@ gendata_cocsep(void *buf, uint64_t *selfsim, cube_t *rep) | |||
| 160 | buf32 = (uint32_t *)buf; | 178 | buf32 = (uint32_t *)buf; |
| 161 | info = buf32 + COCSEP_TABLESIZE; | 179 | info = buf32 + COCSEP_TABLESIZE; |
| 162 | memset(buf32, 0xFF, sizeof(uint32_t) * COCSEP_TABLESIZE); | 180 | memset(buf32, 0xFF, sizeof(uint32_t) * COCSEP_TABLESIZE); |
| 163 | memset(selfsim, 0, sizeof(uint64_t) * COCSEP_CLASSES); | 181 | if (selfsim != NULL) |
| 182 | memset(selfsim, 0, sizeof(uint64_t) * COCSEP_CLASSES); | ||
| 164 | 183 | ||
| 165 | arg = (dfsarg_cocsep_t) { | 184 | arg = (dfsarg_cocsep_t) { |
| 166 | .cube = solved, | 185 | .cube = solved, |
| @@ -221,7 +240,8 @@ gendata_cocsep_dfs(dfsarg_cocsep_t *arg) | |||
| 221 | d = transform_corners(arg->cube, t); | 240 | d = transform_corners(arg->cube, t); |
| 222 | j = coord_cocsep(d); | 241 | j = coord_cocsep(d); |
| 223 | is = (i == j); | 242 | is = (i == j); |
| 224 | arg->selfsim[*arg->n] |= is << t; | 243 | if (arg->selfsim != NULL) |
| 244 | arg->selfsim[*arg->n] |= is << t; | ||
| 225 | set_visited(arg->visited, j); | 245 | set_visited(arg->visited, j); |
| 226 | tinv = inverse_trans(t); | 246 | tinv = inverse_trans(t); |
| 227 | olddepth = (uint8_t)(arg->buf32[j] & 0xFF); | 247 | olddepth = (uint8_t)(arg->buf32[j] & 0xFF); |
| @@ -232,7 +252,8 @@ gendata_cocsep_dfs(dfsarg_cocsep_t *arg) | |||
| 232 | depth = (uint32_t)arg->depth; | 252 | depth = (uint32_t)arg->depth; |
| 233 | arg->buf32[j] = class | ttrep | depth; | 253 | arg->buf32[j] = class | ttrep | depth; |
| 234 | } | 254 | } |
| 235 | arg->rep[*arg->n] = arg->cube; | 255 | if (arg->rep != NULL) |
| 256 | arg->rep[*arg->n] = arg->cube; | ||
| 236 | (*arg->n)++; | 257 | (*arg->n)++; |
| 237 | 258 | ||
| 238 | return cc; | 259 | return cc; |
| @@ -525,3 +546,85 @@ i, get_esep_pval(arg.h48data, i)); | |||
| 525 | */ | 546 | */ |
| 526 | return nsols; | 547 | return nsols; |
| 527 | } | 548 | } |
| 549 | |||
| 550 | /* | ||
| 551 | The h48stats solver computes how many moves it takes to solve to each of | ||
| 552 | the 13 h48 coordinates: the corner-only coordinate, and 12 cocsep+esep | ||
| 553 | coordinates with h from 0 to 11. The solutions array is filled with | ||
| 554 | the length of the solutions: solutions[0] contains the value for the | ||
| 555 | corner-only coordinate, and for i>0 solutions[i] contains the value for | ||
| 556 | the cocsep+esep coordinate with h=i-1. The solution array is therefore | ||
| 557 | not a printable string. | ||
| 558 | */ | ||
| 559 | _static int64_t | ||
| 560 | solve_h48stats_dfs(dfsarg_solveh48stats_t *arg) | ||
| 561 | { | ||
| 562 | int8_t bound, u; | ||
| 563 | uint8_t m; | ||
| 564 | uint32_t d; | ||
| 565 | int64_t coord, h; | ||
| 566 | dfsarg_solveh48stats_t nextarg; | ||
| 567 | |||
| 568 | bound = get_h48_cdata(arg->cube, arg->cocsepdata, &d); | ||
| 569 | if (bound + arg->nmoves > arg->depth) | ||
| 570 | return 0; | ||
| 571 | |||
| 572 | u = COCLASS(d) == 0 && arg->s[0] == 99; | ||
| 573 | arg->s[0] = u * arg->nmoves + (1-u) * arg->s[0]; | ||
| 574 | |||
| 575 | coord = coord_h48_edges(arg->cube, COCLASS(d), TTREP(d), 11); | ||
| 576 | for (h = 0; h <= 11; h++) { | ||
| 577 | u = coord >> (11-h) == 0 && arg->s[h+1] == 99; | ||
| 578 | arg->s[h+1] = u * arg->nmoves + (1-u) * arg->s[h+1]; | ||
| 579 | } | ||
| 580 | |||
| 581 | if (arg->s[12] != 99) | ||
| 582 | return 0; | ||
| 583 | |||
| 584 | nextarg = *arg; | ||
| 585 | nextarg.nmoves = arg->nmoves + 1; | ||
| 586 | for (m = 0; m < 18; m++) { | ||
| 587 | nextarg.moves[arg->nmoves] = m; | ||
| 588 | if (!allowednextmove(nextarg.moves, nextarg.nmoves)) { | ||
| 589 | /* If a move is not allowed, neither are its 180 | ||
| 590 | * and 270 degree variations */ | ||
| 591 | m += 2; | ||
| 592 | continue; | ||
| 593 | } | ||
| 594 | nextarg.cube = move(arg->cube, m); | ||
| 595 | solve_h48stats_dfs(&nextarg); | ||
| 596 | } | ||
| 597 | |||
| 598 | return 0; | ||
| 599 | } | ||
| 600 | |||
| 601 | _static int64_t | ||
| 602 | solve_h48stats( | ||
| 603 | cube_t cube, | ||
| 604 | int8_t maxmoves, | ||
| 605 | const void *data, | ||
| 606 | char solutions[static 13] | ||
| 607 | ) | ||
| 608 | { | ||
| 609 | int i; | ||
| 610 | dfsarg_solveh48stats_t arg; | ||
| 611 | |||
| 612 | arg = (dfsarg_solveh48stats_t) { | ||
| 613 | .cube = cube, | ||
| 614 | .cocsepdata = (uint32_t *)data, | ||
| 615 | .s = solutions | ||
| 616 | }; | ||
| 617 | |||
| 618 | for (i = 0; i < 13; i++) | ||
| 619 | solutions[i] = (char)99; | ||
| 620 | |||
| 621 | for (arg.depth = 0; | ||
| 622 | arg.depth <= maxmoves && solutions[12] == 99; | ||
| 623 | arg.depth++) | ||
| 624 | { | ||
| 625 | arg.nmoves = 0; | ||
| 626 | solve_h48stats_dfs(&arg); | ||
| 627 | } | ||
| 628 | |||
| 629 | return 0; | ||
| 630 | } | ||
diff --git a/tools/stats_tables_h48/stats_tables_h48.c b/tools/stats_tables_h48/stats_tables_h48.c new file mode 100644 index 0000000..9f9bacf --- /dev/null +++ b/tools/stats_tables_h48/stats_tables_h48.c | |||
| @@ -0,0 +1,69 @@ | |||
| 1 | #include <time.h> | ||
| 2 | #include "../timerun.h" | ||
| 3 | #include "../../src/cube.h" | ||
| 4 | |||
| 5 | #define MAXMOVES 20 | ||
| 6 | #define NCUBES 1000 | ||
| 7 | |||
| 8 | typedef struct { uint8_t n[16]; } i128; | ||
| 9 | |||
| 10 | char *buf; | ||
| 11 | |||
| 12 | i128 rand128(void) { | ||
| 13 | uint8_t i, j; | ||
| 14 | i128 ret = {0}; | ||
| 15 | |||
| 16 | for (i = 0; i < 16; i++) | ||
| 17 | for (j = 0; j < 8; j++) | ||
| 18 | ret.n[i] |= (uint8_t)(rand() % 2) << j; | ||
| 19 | |||
| 20 | return ret; | ||
| 21 | } | ||
| 22 | |||
| 23 | void output(int64_t v[13][100]) { | ||
| 24 | /* TODO: write to file and output only cocsepdata table stats */ | ||
| 25 | } | ||
| 26 | |||
| 27 | void run(void) { | ||
| 28 | uint32_t *h48info; | ||
| 29 | int i, j; | ||
| 30 | char sols[13], cube[22]; | ||
| 31 | int64_t s, v[13][100] = {0}; | ||
| 32 | |||
| 33 | s = nissy_gendata("H48stats", "", buf); | ||
| 34 | |||
| 35 | if (s == -1) { | ||
| 36 | printf("Error generating table\n"); | ||
| 37 | return; | ||
| 38 | } | ||
| 39 | |||
| 40 | for (i = 0; i < NCUBES; i++) { | ||
| 41 | nissy_gencube(rand128(), "", cube); | ||
| 42 | nissy_solve(cube, "H48stats", | ||
| 43 | "", "", "", 0, MAXMOVES, 1, -1, buf, sols); | ||
| 44 | for (j = 0; j < 13; j++) | ||
| 45 | v[j][(int)sols[j]]++; | ||
| 46 | } | ||
| 47 | |||
| 48 | output(v); | ||
| 49 | } | ||
| 50 | |||
| 51 | int main() { | ||
| 52 | int64_t size; | ||
| 53 | |||
| 54 | srand(time(NULL)); | ||
| 55 | |||
| 56 | size = nissy_datasize("H48", OPTIONS); | ||
| 57 | if (size == -1) { | ||
| 58 | printf("h48 stats: error in datasize\n"); | ||
| 59 | return 1; | ||
| 60 | } | ||
| 61 | |||
| 62 | buf = malloc(size); | ||
| 63 | |||
| 64 | timerun(run, "h48 table stats"); | ||
| 65 | |||
| 66 | free(buf); | ||
| 67 | |||
| 68 | return 0; | ||
| 69 | } | ||
