diff options
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | Makefile | 6 | ||||
| -rw-r--r-- | README.md | 17 | ||||
| -rw-r--r-- | TODO.txt | 12 | ||||
| -rw-r--r-- | shell.c | 97 | ||||
| -rw-r--r-- | src/cube_public.h | 11 | ||||
| -rw-r--r-- | src/solve_generic.h | 3 | ||||
| -rw-r--r-- | src/solve_h48.h | 174 | ||||
| -rw-r--r-- | test/103_gendata_h48/00_h_0.out | 2 | ||||
| -rw-r--r-- | test/103_gendata_h48/01_h_1.out | 2 |
10 files changed, 265 insertions, 60 deletions
| @@ -5,6 +5,7 @@ gen | |||
| 5 | debuggen | 5 | debuggen |
| 6 | perf.data | 6 | perf.data |
| 7 | perf.data.old | 7 | perf.data.old |
| 8 | run | ||
| 8 | tables/* | 9 | tables/* |
| 9 | test/*/runtest | 10 | test/*/runtest |
| 10 | test/run | 11 | test/run |
| @@ -24,4 +24,8 @@ shell: cube.o | |||
| 24 | mkdir -p tables | 24 | mkdir -p tables |
| 25 | ${CC} ${CFLAGS} -o run cube.o shell.c | 25 | ${CC} ${CFLAGS} -o run cube.o shell.c |
| 26 | 26 | ||
| 27 | .PHONY: all clean test benchmark shell | 27 | debugshell: debugcube.o |
| 28 | mkdir -p tables | ||
| 29 | ${CC} ${DBGFLAGS} -o run debugcube.o shell.c | ||
| 30 | |||
| 31 | .PHONY: all clean test benchmark shell debugshell | ||
| @@ -27,3 +27,20 @@ $ TEST=coord make test | |||
| 27 | ``` | 27 | ``` |
| 28 | 28 | ||
| 29 | Due to ongoing changes, benchmarks are currently broken. | 29 | Due to ongoing changes, benchmarks are currently broken. |
| 30 | |||
| 31 | ## Solving | ||
| 32 | |||
| 33 | Notes for myself while this is work in progress | ||
| 34 | |||
| 35 | ``` | ||
| 36 | $ make shell | ||
| 37 | $ ./run frommoves -moves (scramble) | ||
| 38 | ``` | ||
| 39 | |||
| 40 | copy the result, then | ||
| 41 | |||
| 42 | ``` | ||
| 43 | $ ./run solve -solver "H48" -options "2;20" -n 1 -M 10 -cube (paste here) | ||
| 44 | ``` | ||
| 45 | |||
| 46 | Options can be changed from `2;20` to `n;20` for larger tables. | ||
| @@ -1,8 +1,16 @@ | |||
| 1 | Solver | 1 | Solver |
| 2 | - write a solver (how many tricks? some, but not all are needed) | 2 | - fix and cleanup current implementation |
| 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 | ||
| 6 | - implement and use premove (and test) instead of inverting | ||
| 3 | - benchmark for solve | 7 | - benchmark for solve |
| 4 | table generation, where to keep tables? in benchmark folder or in tables/? | 8 | table generation, where to keep tables? in benchmark folder or in tables/? |
| 9 | - more tricks for solver, optimize, try larger tables | ||
| 5 | - remove solve_simple and maybe the whole solve_generic | 10 | - remove solve_simple and maybe the whole solve_generic |
| 11 | - shell: silently accept other formats too? | ||
| 12 | - shell: allow generating multiple tables for different options | ||
| 13 | - gendata: move info at start of tables? | ||
| 6 | 14 | ||
| 7 | Cleanup cube_public and interface | 15 | Cleanup cube_public and interface |
| 8 | - remove options, use only solver name | 16 | - remove options, use only solver name |
| @@ -17,6 +25,8 @@ Goal: find out which k value is best | |||
| 17 | 25 | ||
| 18 | Improvements | 26 | Improvements |
| 19 | - check hash of generated data | 27 | - check hash of generated data |
| 28 | - use interleaved tables (e.g. big table with k=2 or k=1 and interleaved | ||
| 29 | small table with k=4 for better backup pruning) | ||
| 20 | 30 | ||
| 21 | ## H48 optimal solver (some has already been implemented) | 31 | ## H48 optimal solver (some has already been implemented) |
| 22 | 32 | ||
| @@ -1,5 +1,6 @@ | |||
| 1 | #include <inttypes.h> | 1 | #include <inttypes.h> |
| 2 | #include <errno.h> | 2 | #include <errno.h> |
| 3 | #include <stdarg.h> | ||
| 3 | #include <stdbool.h> | 4 | #include <stdbool.h> |
| 4 | #include <stdio.h> | 5 | #include <stdio.h> |
| 5 | #include <stdlib.h> | 6 | #include <stdlib.h> |
| @@ -28,7 +29,6 @@ typedef struct { | |||
| 28 | int8_t maxmoves; | 29 | int8_t maxmoves; |
| 29 | int8_t optimal; | 30 | int8_t optimal; |
| 30 | int64_t maxsolutions; | 31 | int64_t maxsolutions; |
| 31 | int64_t datasize; /* Option for gendata + solve, TODO change? */ | ||
| 32 | } args_t; | 32 | } args_t; |
| 33 | 33 | ||
| 34 | static void print_cube_result(int64_t, char [static 22]); | 34 | static void print_cube_result(int64_t, char [static 22]); |
| @@ -39,9 +39,7 @@ static int64_t inverse_exec(args_t *); | |||
| 39 | static int64_t applymoves_exec(args_t *); | 39 | static int64_t applymoves_exec(args_t *); |
| 40 | static int64_t applytrans_exec(args_t *); | 40 | static int64_t applytrans_exec(args_t *); |
| 41 | static int64_t frommoves_exec(args_t *); | 41 | static int64_t frommoves_exec(args_t *); |
| 42 | static int64_t readcube_exec(args_t *); | 42 | static int64_t convert_exec(args_t *); |
| 43 | static int64_t writecube_exec(args_t *); | ||
| 44 | static int64_t convertcube_exec(args_t *); | ||
| 45 | static int64_t datasize_exec(args_t *); | 43 | static int64_t datasize_exec(args_t *); |
| 46 | static int64_t gendata_exec(args_t *); | 44 | static int64_t gendata_exec(args_t *); |
| 47 | static int64_t solve_exec(args_t *); | 45 | static int64_t solve_exec(args_t *); |
| @@ -76,9 +74,7 @@ struct { | |||
| 76 | COMMAND("applymoves", applymoves_exec), | 74 | COMMAND("applymoves", applymoves_exec), |
| 77 | COMMAND("applytrans", applytrans_exec), | 75 | COMMAND("applytrans", applytrans_exec), |
| 78 | COMMAND("frommoves", frommoves_exec), | 76 | COMMAND("frommoves", frommoves_exec), |
| 79 | COMMAND("readcube", readcube_exec), | 77 | COMMAND("convert", convert_exec), |
| 80 | COMMAND("writecube", writecube_exec), | ||
| 81 | COMMAND("convertcube", convertcube_exec), | ||
| 82 | COMMAND("datasize", datasize_exec), | 78 | COMMAND("datasize", datasize_exec), |
| 83 | COMMAND("gendata", gendata_exec), | 79 | COMMAND("gendata", gendata_exec), |
| 84 | COMMAND("solve", solve_exec), | 80 | COMMAND("solve", solve_exec), |
| @@ -199,43 +195,19 @@ frommoves_exec(args_t *args) | |||
| 199 | char result[22]; | 195 | char result[22]; |
| 200 | int64_t ret; | 196 | int64_t ret; |
| 201 | 197 | ||
| 202 | ret = nissy_frommoves(args->str_trans, result); | 198 | ret = nissy_frommoves(args->str_moves, result); |
| 203 | print_cube_result(ret, result); | 199 | print_cube_result(ret, result); |
| 204 | 200 | ||
| 205 | return ret; | 201 | return ret; |
| 206 | } | 202 | } |
| 207 | 203 | ||
| 208 | static int64_t | 204 | static int64_t |
| 209 | readcube_exec(args_t *args) | 205 | convert_exec(args_t *args) |
| 210 | { | ||
| 211 | char result[22]; | ||
| 212 | int64_t ret; | ||
| 213 | |||
| 214 | ret = nissy_readcube(args->str_format, args->str_cube, result); | ||
| 215 | print_cube_result(ret, result); | ||
| 216 | |||
| 217 | return ret; | ||
| 218 | } | ||
| 219 | |||
| 220 | static int64_t | ||
| 221 | writecube_exec(args_t *args) | ||
| 222 | { | ||
| 223 | char result[PRINTCUBE_BUFFER_SIZE]; | ||
| 224 | int64_t ret; | ||
| 225 | |||
| 226 | ret = nissy_writecube(args->str_format, args->str_cube, result); | ||
| 227 | print_str_result(ret, result); | ||
| 228 | |||
| 229 | return ret; | ||
| 230 | } | ||
| 231 | |||
| 232 | static int64_t | ||
| 233 | convertcube_exec(args_t *args) | ||
| 234 | { | 206 | { |
| 235 | char result[PRINTCUBE_BUFFER_SIZE]; | 207 | char result[PRINTCUBE_BUFFER_SIZE]; |
| 236 | int64_t ret; | 208 | int64_t ret; |
| 237 | 209 | ||
| 238 | ret = nissy_convertcube( | 210 | ret = nissy_convert( |
| 239 | args->str_format_in, args->str_format_out, args->str_cube, result); | 211 | args->str_format_in, args->str_format_out, args->str_cube, result); |
| 240 | print_str_result(ret, result); | 212 | print_str_result(ret, result); |
| 241 | 213 | ||
| @@ -275,14 +247,17 @@ gendata_exec(args_t *args) | |||
| 275 | 247 | ||
| 276 | if (tablepaths[i] == NULL) { | 248 | if (tablepaths[i] == NULL) { |
| 277 | fprintf(stderr, "Cannot write data to file\n"); | 249 | fprintf(stderr, "Cannot write data to file\n"); |
| 250 | fclose(file); | ||
| 278 | return -2; | 251 | return -2; |
| 279 | } | 252 | } |
| 280 | 253 | ||
| 281 | size = nissy_datasize(args->str_solver, args->str_options); | 254 | size = nissy_datasize(args->str_solver, args->str_options); |
| 255 | |||
| 282 | if (size < 0) { | 256 | if (size < 0) { |
| 283 | fprintf(stderr, | 257 | fprintf(stderr, |
| 284 | "Unknown error in retrieving data size" | 258 | "Unknown error in retrieving data size" |
| 285 | "(make sure solver is valid)\n"); | 259 | "(make sure solver is valid)\n"); |
| 260 | fclose(file); | ||
| 286 | return -3; | 261 | return -3; |
| 287 | } | 262 | } |
| 288 | 263 | ||
| @@ -291,19 +266,23 @@ gendata_exec(args_t *args) | |||
| 291 | ret = nissy_gendata(args->str_solver, args->str_options, buf); | 266 | ret = nissy_gendata(args->str_solver, args->str_options, buf); |
| 292 | if (ret < 0) { | 267 | if (ret < 0) { |
| 293 | fprintf(stderr, "Unknown error in generating data\n"); | 268 | fprintf(stderr, "Unknown error in generating data\n"); |
| 269 | fclose(file); | ||
| 294 | free(buf); | 270 | free(buf); |
| 295 | return -4; | 271 | return -4; |
| 296 | } | 272 | } |
| 297 | if (ret != size) { | 273 | if (ret != size) { |
| 298 | fprintf(stderr, "Unknown error: unexpected data size\n"); | 274 | fprintf(stderr, "Unknown error: unexpected data size " |
| 275 | "(got %zu, expected %zu)\n", ret, size); | ||
| 276 | fclose(file); | ||
| 299 | free(buf); | 277 | free(buf); |
| 300 | return -5; | 278 | return -5; |
| 301 | } | 279 | } |
| 302 | 280 | ||
| 303 | written = fwrite(buf, size, 1, file); | 281 | written = fwrite(buf, size, 1, file); |
| 282 | fclose(file); | ||
| 304 | free(buf); | 283 | free(buf); |
| 305 | 284 | ||
| 306 | if (written != (int64_t)size) { | 285 | if (written != 1) { |
| 307 | fprintf(stderr, | 286 | fprintf(stderr, |
| 308 | "Error: data was generated correctly, but could not be " | 287 | "Error: data was generated correctly, but could not be " |
| 309 | "written to file (generated %" PRId64 " bytes, written " | 288 | "written to file (generated %" PRId64 " bytes, written " |
| @@ -311,7 +290,6 @@ gendata_exec(args_t *args) | |||
| 311 | return -6; | 290 | return -6; |
| 312 | } | 291 | } |
| 313 | 292 | ||
| 314 | args->datasize = size; | ||
| 315 | fprintf(stderr, "Data written to %s\n", path); | 293 | fprintf(stderr, "Data written to %s\n", path); |
| 316 | 294 | ||
| 317 | return 0; | 295 | return 0; |
| @@ -323,7 +301,7 @@ solve_exec(args_t *args) | |||
| 323 | int i; | 301 | int i; |
| 324 | FILE *file; | 302 | FILE *file; |
| 325 | char *buf, solutions[SOLUTIONS_BUFFER_SIZE], path[MAX_PATH_LENGTH]; | 303 | char *buf, solutions[SOLUTIONS_BUFFER_SIZE], path[MAX_PATH_LENGTH]; |
| 326 | int64_t ret, gendata_ret; | 304 | int64_t ret, gendata_ret, size; |
| 327 | size_t read; | 305 | size_t read; |
| 328 | 306 | ||
| 329 | for (i = 0; tablepaths[i] != NULL; i++) { | 307 | for (i = 0; tablepaths[i] != NULL; i++) { |
| @@ -344,23 +322,30 @@ solve_exec(args_t *args) | |||
| 344 | } | 322 | } |
| 345 | 323 | ||
| 346 | /* Ugh, this is not elegant TODO */ | 324 | /* Ugh, this is not elegant TODO */ |
| 347 | for (i = 0; tablepaths[i] != NULL; i++) { | 325 | if (file == NULL) { |
| 348 | strcpy(path, tablepaths[i]); | 326 | for (i = 0; tablepaths[i] != NULL; i++) { |
| 349 | strcat(path, args->str_solver); | 327 | strcpy(path, tablepaths[i]); |
| 350 | file = fopen(path, "rb"); | 328 | strcat(path, args->str_solver); |
| 351 | if (file != NULL) | 329 | file = fopen(path, "rb"); |
| 352 | break; | 330 | if (file != NULL) |
| 331 | break; | ||
| 332 | } | ||
| 353 | } | 333 | } |
| 354 | 334 | ||
| 355 | if (tablepaths[i] == NULL) { | 335 | if (tablepaths[i] == NULL) { |
| 356 | fprintf(stderr, "Error: data file not found\n"); | 336 | fprintf(stderr, "Error: data file not found\n"); |
| 337 | fclose(file); | ||
| 357 | return -1; | 338 | return -1; |
| 358 | } | 339 | } |
| 359 | 340 | ||
| 360 | buf = malloc(args->datasize); | 341 | size = nissy_datasize(args->str_solver, args->str_options); |
| 361 | read = fread(buf, args->datasize, 1, file); | 342 | buf = malloc(size); |
| 362 | if (read != args->datasize) { | 343 | read = fread(buf, size, 1, file); |
| 363 | fprintf(stderr, "Error reading data from file\n"); | 344 | fclose(file); |
| 345 | if (read != 1) { | ||
| 346 | fprintf(stderr, "Error reading data from file: " | ||
| 347 | "fread() returned %zu instead of 1 when attempting to" | ||
| 348 | "read %" PRId64 " bytes from file %s\n", read, size, path); | ||
| 364 | return -2; | 349 | return -2; |
| 365 | } | 350 | } |
| 366 | 351 | ||
| @@ -413,7 +398,7 @@ parse_args(int argc, char **argv, args_t *args) | |||
| 413 | options[j].name); | 398 | options[j].name); |
| 414 | return 1; | 399 | return 1; |
| 415 | } | 400 | } |
| 416 | if (!options[j].set(n, argv+i, args)) { | 401 | if (!options[j].set(n, argv+i+1, args)) { |
| 417 | fprintf(stderr, | 402 | fprintf(stderr, |
| 418 | "Error parsing arguments for option %s\n", | 403 | "Error parsing arguments for option %s\n", |
| 419 | options[j].name); | 404 | options[j].name); |
| @@ -448,7 +433,8 @@ parse_int64(char *argv, int64_t *result) | |||
| 448 | { | 433 | { |
| 449 | *result = strtoll(argv, NULL, 10); | 434 | *result = strtoll(argv, NULL, 10); |
| 450 | 435 | ||
| 451 | return errno != 0; | 436 | /* TODO: figure out how errno works and use it */ |
| 437 | return true; | ||
| 452 | } | 438 | } |
| 453 | 439 | ||
| 454 | static bool | 440 | static bool |
| @@ -565,11 +551,22 @@ set_maxsolutions(int argc, char **argv, args_t *args) | |||
| 565 | return parse_int64(argv[0], &args->maxsolutions); | 551 | return parse_int64(argv[0], &args->maxsolutions); |
| 566 | } | 552 | } |
| 567 | 553 | ||
| 554 | void log_stderr(const char *str, ...) | ||
| 555 | { | ||
| 556 | va_list args; | ||
| 557 | |||
| 558 | va_start(args, str); | ||
| 559 | vfprintf(stderr, str, args); | ||
| 560 | va_end(args); | ||
| 561 | } | ||
| 562 | |||
| 568 | int main(int argc, char **argv) | 563 | int main(int argc, char **argv) |
| 569 | { | 564 | { |
| 570 | int parse_error; | 565 | int parse_error; |
| 571 | args_t args; | 566 | args_t args; |
| 572 | 567 | ||
| 568 | nissy_setlogger(log_stderr); | ||
| 569 | |||
| 573 | parse_error = parse_args(argc-1, argv+1, &args); | 570 | parse_error = parse_args(argc-1, argv+1, &args); |
| 574 | if (parse_error) | 571 | if (parse_error) |
| 575 | return parse_error; | 572 | return parse_error; |
diff --git a/src/cube_public.h b/src/cube_public.h index ea1d28d..a1c4b90 100644 --- a/src/cube_public.h +++ b/src/cube_public.h | |||
| @@ -89,7 +89,7 @@ nissy_frommoves( | |||
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | int64_t | 91 | int64_t |
| 92 | nissy_convertcube( | 92 | nissy_convert( |
| 93 | const char *format_in, | 93 | const char *format_in, |
| 94 | const char *format_out, | 94 | const char *format_out, |
| 95 | const char *cube_string, | 95 | const char *cube_string, |
| @@ -155,6 +155,7 @@ nissy_solve( | |||
| 155 | { | 155 | { |
| 156 | cube_t c; | 156 | cube_t c; |
| 157 | int64_t ret; | 157 | int64_t ret; |
| 158 | int h; | ||
| 158 | 159 | ||
| 159 | c = readcube_B32(cube); | 160 | c = readcube_B32(cube); |
| 160 | 161 | ||
| @@ -188,8 +189,12 @@ nissy_solve( | |||
| 188 | return -1; | 189 | return -1; |
| 189 | } | 190 | } |
| 190 | 191 | ||
| 191 | if (!strcmp(solver, "h48")) { | 192 | /* TODO define and use solve_options_t */ |
| 192 | LOG("h48 solver not implemented yet\n"); | 193 | if (!strcmp(solver, "H48")) { |
| 194 | h = atoi(options); /* TODO: better parsing */ | ||
| 195 | ret = solve_h48( | ||
| 196 | c, minmoves, maxmoves, maxsolutions, | ||
| 197 | (uint8_t)h, data, solutions); | ||
| 193 | ret = -1; | 198 | ret = -1; |
| 194 | } else if (!strcmp(solver, "simple")) { | 199 | } else if (!strcmp(solver, "simple")) { |
| 195 | ret = solve_simple( | 200 | ret = solve_simple( |
diff --git a/src/solve_generic.h b/src/solve_generic.h index d1d1469..41d995a 100644 --- a/src/solve_generic.h +++ b/src/solve_generic.h | |||
| @@ -21,7 +21,7 @@ solve_generic_appendsolution(dfsarg_generic_t *arg) | |||
| 21 | { | 21 | { |
| 22 | int strl; | 22 | int strl; |
| 23 | 23 | ||
| 24 | strl = writemoves(arg->moves, arg->depth, *arg->nextsol); | 24 | strl = writemoves(arg->moves, arg->nmoves, *arg->nextsol); |
| 25 | LOG("Solution found: %s\n", *arg->nextsol); | 25 | LOG("Solution found: %s\n", *arg->nextsol); |
| 26 | *arg->nextsol += strl; | 26 | *arg->nextsol += strl; |
| 27 | **arg->nextsol = '\n'; | 27 | **arg->nextsol = '\n'; |
| @@ -53,7 +53,6 @@ solve_generic_dfs(dfsarg_generic_t *arg) | |||
| 53 | return 1; | 53 | return 1; |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | /* memcpy(&nextarg, arg, sizeof(dfsarg_generic_t)); */ | ||
| 57 | nextarg = *arg; | 56 | nextarg = *arg; |
| 58 | nextarg.nmoves = arg->nmoves + 1; | 57 | nextarg.nmoves = arg->nmoves + 1; |
| 59 | for (m = 0, ret = 0; m < 18; m++) { | 58 | for (m = 0, ret = 0; m < 18; m++) { |
diff --git a/src/solve_h48.h b/src/solve_h48.h index 1646f49..201c7c6 100644 --- a/src/solve_h48.h +++ b/src/solve_h48.h | |||
| @@ -11,6 +11,8 @@ | |||
| 11 | #define COCLASS(x) (((x) & COCLASS_MASK) >> UINT32_C(16)) | 11 | #define COCLASS(x) (((x) & COCLASS_MASK) >> UINT32_C(16)) |
| 12 | #define TTREP_MASK (UINT32_C(0xFF) << UINT32_C(8)) | 12 | #define TTREP_MASK (UINT32_C(0xFF) << UINT32_C(8)) |
| 13 | #define TTREP(x) (((x) & TTREP_MASK) >> UINT32_C(8)) | 13 | #define TTREP(x) (((x) & TTREP_MASK) >> UINT32_C(8)) |
| 14 | #define CBOUND_MASK UINT32_C(0xFF) | ||
| 15 | #define CBOUND(x) ((x) & CBOUND_MASK) | ||
| 14 | #define H48_ESIZE(h) ((_12c4 * _8c4) << (int64_t)(h)) | 16 | #define H48_ESIZE(h) ((_12c4 * _8c4) << (int64_t)(h)) |
| 15 | 17 | ||
| 16 | #define ESEP_IND(i) ((uint32_t)(i) / UINT32_C(8)) | 18 | #define ESEP_IND(i) ((uint32_t)(i) / UINT32_C(8)) |
| @@ -19,6 +21,8 @@ | |||
| 19 | #define VISITED_IND(i) ((uint32_t)(i) / UINT32_C(8)) | 21 | #define VISITED_IND(i) ((uint32_t)(i) / UINT32_C(8)) |
| 20 | #define VISITED_MASK(i) (UINT32_C(1) << ((uint32_t)(i) % UINT32_C(8))) | 22 | #define VISITED_MASK(i) (UINT32_C(1) << ((uint32_t)(i) % UINT32_C(8))) |
| 21 | 23 | ||
| 24 | #define MAX_SOLUTION_LENGTH 20 | ||
| 25 | |||
| 22 | typedef struct { | 26 | typedef struct { |
| 23 | cube_t cube; | 27 | cube_t cube; |
| 24 | uint8_t depth; | 28 | uint8_t depth; |
| @@ -39,6 +43,20 @@ typedef struct { | |||
| 39 | cube_t *crep; | 43 | cube_t *crep; |
| 40 | } bfsarg_esep_t; | 44 | } bfsarg_esep_t; |
| 41 | 45 | ||
| 46 | typedef struct { | ||
| 47 | cube_t cube; | ||
| 48 | cube_t inverse; | ||
| 49 | int8_t nmoves; | ||
| 50 | int8_t depth; | ||
| 51 | uint8_t moves[MAX_SOLUTION_LENGTH]; | ||
| 52 | int64_t *nsols; | ||
| 53 | int64_t maxsolutions; | ||
| 54 | uint8_t h; | ||
| 55 | uint32_t *cocsepdata; | ||
| 56 | uint32_t *h48data; | ||
| 57 | char **nextsol; | ||
| 58 | } dfsarg_solveh48_t; | ||
| 59 | |||
| 42 | _static_inline int64_t coord_h48(cube_t, const uint32_t *, uint8_t); | 60 | _static_inline int64_t coord_h48(cube_t, const uint32_t *, uint8_t); |
| 43 | _static_inline int64_t coord_h48_edges(cube_t, int64_t, uint8_t, uint8_t); | 61 | _static_inline int64_t coord_h48_edges(cube_t, int64_t, uint8_t, uint8_t); |
| 44 | _static_inline cube_t invcoord_h48(int64_t, const cube_t *, uint8_t); | 62 | _static_inline cube_t invcoord_h48(int64_t, const cube_t *, uint8_t); |
| @@ -53,6 +71,13 @@ _static_inline void set_visited(uint8_t *, int64_t); | |||
| 53 | _static_inline uint8_t get_esep_pval(const uint32_t *, int64_t); | 71 | _static_inline uint8_t get_esep_pval(const uint32_t *, int64_t); |
| 54 | _static_inline void set_esep_pval(uint32_t *, int64_t, uint8_t); | 72 | _static_inline void set_esep_pval(uint32_t *, int64_t, uint8_t); |
| 55 | 73 | ||
| 74 | _static void solve_h48_appendsolution(dfsarg_solveh48_t *); | ||
| 75 | _static_inline int8_t get_h48_cdata(cube_t, uint32_t *, uint32_t *); | ||
| 76 | _static_inline int8_t get_h48_bound(cube_t, uint32_t, uint8_t, uint32_t *); | ||
| 77 | _static_inline bool solve_h48_stop(dfsarg_solveh48_t *); | ||
| 78 | _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 *); | ||
| 80 | |||
| 56 | _static_inline int64_t | 81 | _static_inline int64_t |
| 57 | coord_h48(cube_t c, const uint32_t *cocsepdata, uint8_t h) | 82 | coord_h48(cube_t c, const uint32_t *cocsepdata, uint8_t h) |
| 58 | { | 83 | { |
| @@ -238,8 +263,11 @@ gendata_h48(void *buf, uint8_t h, uint8_t maxdepth) | |||
| 238 | cube_t crep[COCSEP_CLASSES]; | 263 | cube_t crep[COCSEP_CLASSES]; |
| 239 | size_t cocsepsize, infosize; | 264 | size_t cocsepsize, infosize; |
| 240 | 265 | ||
| 266 | /* TODO: move info at start of tables (all tables!) */ | ||
| 241 | infosize = 4 * maxdepth; | 267 | infosize = 4 * maxdepth; |
| 242 | cocsepsize = gendata_cocsep(buf, selfsim, crep); | 268 | cocsepsize = gendata_cocsep(buf, selfsim, crep); |
| 269 | infosize = 88; | ||
| 270 | |||
| 243 | if (buf == NULL) | 271 | if (buf == NULL) |
| 244 | goto gendata_h48_return_size; | 272 | goto gendata_h48_return_size; |
| 245 | 273 | ||
| @@ -272,7 +300,6 @@ gendata_h48(void *buf, uint8_t h, uint8_t maxdepth) | |||
| 272 | } | 300 | } |
| 273 | 301 | ||
| 274 | info[0] = arg.depth-1; | 302 | info[0] = arg.depth-1; |
| 275 | infosize = 4 * (size_t)(info[0] + 2); | ||
| 276 | 303 | ||
| 277 | LOG("h48 pruning table computed\n"); | 304 | LOG("h48 pruning table computed\n"); |
| 278 | LOG("Maximum pruning value: %" PRIu32 "\n", info[0]); | 305 | LOG("Maximum pruning value: %" PRIu32 "\n", info[0]); |
| @@ -353,3 +380,148 @@ set_esep_pval(uint32_t *buf32, int64_t i, uint8_t val) | |||
| 353 | buf32[ESEP_IND(i)] = | 380 | buf32[ESEP_IND(i)] = |
| 354 | (buf32[ESEP_IND(i)] & (~ESEP_MASK(i))) | (val << ESEP_SHIFT(i)); | 381 | (buf32[ESEP_IND(i)] & (~ESEP_MASK(i))) | (val << ESEP_SHIFT(i)); |
| 355 | } | 382 | } |
| 383 | |||
| 384 | _static void | ||
| 385 | solve_h48_appendsolution(dfsarg_solveh48_t *arg) | ||
| 386 | { | ||
| 387 | int strl; | ||
| 388 | |||
| 389 | strl = writemoves(arg->moves, arg->nmoves, *arg->nextsol); | ||
| 390 | LOG("Solution found: %s\n", *arg->nextsol); | ||
| 391 | *arg->nextsol += strl; | ||
| 392 | **arg->nextsol = '\n'; | ||
| 393 | (*arg->nextsol)++; | ||
| 394 | (*arg->nsols)++; | ||
| 395 | } | ||
| 396 | |||
| 397 | _static_inline int8_t | ||
| 398 | get_h48_cdata(cube_t cube, uint32_t *cocsepdata, uint32_t *cdata) | ||
| 399 | { | ||
| 400 | int64_t coord; | ||
| 401 | |||
| 402 | coord = coord_cocsep(cube); | ||
| 403 | *cdata = cocsepdata[coord]; | ||
| 404 | |||
| 405 | return CBOUND(*cdata); | ||
| 406 | } | ||
| 407 | |||
| 408 | _static_inline int8_t | ||
| 409 | get_h48_bound(cube_t cube, uint32_t cdata, uint8_t h, uint32_t *h48data) | ||
| 410 | { | ||
| 411 | int64_t coord; | ||
| 412 | |||
| 413 | coord = coord_h48_edges(cube, COCLASS(cdata), TTREP(cdata), h); | ||
| 414 | return get_esep_pval(h48data, coord); | ||
| 415 | } | ||
| 416 | |||
| 417 | _static_inline bool | ||
| 418 | solve_h48_stop(dfsarg_solveh48_t *arg) | ||
| 419 | { | ||
| 420 | uint32_t data, data_inv; | ||
| 421 | int8_t bound; | ||
| 422 | |||
| 423 | bound = get_h48_cdata(arg->cube, arg->cocsepdata, &data); | ||
| 424 | if (bound + arg->nmoves > arg->depth) | ||
| 425 | return true; | ||
| 426 | |||
| 427 | bound = get_h48_cdata(arg->inverse, arg->cocsepdata, &data_inv); | ||
| 428 | if (bound + arg->nmoves > arg->depth) | ||
| 429 | return true; | ||
| 430 | |||
| 431 | /* | ||
| 432 | bound = get_h48_bound(arg->cube, data, arg->h, arg->h48data); | ||
| 433 | LOG("Using pval %" PRId8 "\n", bound); | ||
| 434 | if (bound + arg->nmoves > arg->depth) | ||
| 435 | return true; | ||
| 436 | |||
| 437 | bound = get_h48_bound(arg->inverse, data_inv, arg->h, arg->h48data); | ||
| 438 | if (bound + arg->nmoves > arg->depth) | ||
| 439 | return true; | ||
| 440 | */ | ||
| 441 | |||
| 442 | return false; | ||
| 443 | } | ||
| 444 | |||
| 445 | _static int64_t | ||
| 446 | solve_h48_dfs(dfsarg_solveh48_t *arg) | ||
| 447 | { | ||
| 448 | dfsarg_solveh48_t nextarg; | ||
| 449 | int64_t ret; | ||
| 450 | uint8_t m; | ||
| 451 | |||
| 452 | if (*arg->nsols == arg->maxsolutions) | ||
| 453 | return 0; | ||
| 454 | |||
| 455 | if (solve_h48_stop(arg)) | ||
| 456 | return 0; | ||
| 457 | |||
| 458 | if (issolved(arg->cube)) { | ||
| 459 | if (arg->nmoves != arg->depth) | ||
| 460 | return 0; | ||
| 461 | solve_h48_appendsolution(arg); | ||
| 462 | return 1; | ||
| 463 | } | ||
| 464 | |||
| 465 | /* TODO: avoid copy, change arg and undo changes after recursion */ | ||
| 466 | nextarg = *arg; | ||
| 467 | nextarg.nmoves = arg->nmoves + 1; | ||
| 468 | ret = 0; | ||
| 469 | for (m = 0; m < 18; m++) { | ||
| 470 | nextarg.moves[arg->nmoves] = m; | ||
| 471 | if (!allowednextmove(nextarg.moves, nextarg.nmoves)) { | ||
| 472 | /* If a move is not allowed, neither are its 180 | ||
| 473 | * and 270 degree variations */ | ||
| 474 | m += 2; | ||
| 475 | continue; | ||
| 476 | } | ||
| 477 | nextarg.cube = move(arg->cube, m); | ||
| 478 | nextarg.inverse = inverse(nextarg.cube); /* TODO: use premove */ | ||
| 479 | ret += solve_h48_dfs(&nextarg); | ||
| 480 | } | ||
| 481 | |||
| 482 | return ret; | ||
| 483 | } | ||
| 484 | |||
| 485 | _static int64_t | ||
| 486 | solve_h48( | ||
| 487 | cube_t cube, | ||
| 488 | int8_t minmoves, | ||
| 489 | int8_t maxmoves, | ||
| 490 | int8_t maxsolutions, | ||
| 491 | uint8_t h, | ||
| 492 | const void *data, | ||
| 493 | char *solutions | ||
| 494 | ) | ||
| 495 | { | ||
| 496 | int64_t nsols; | ||
| 497 | dfsarg_solveh48_t arg; | ||
| 498 | |||
| 499 | arg = (dfsarg_solveh48_t) { | ||
| 500 | .cube = cube, | ||
| 501 | .inverse = inverse(cube), | ||
| 502 | .nsols = &nsols, | ||
| 503 | .maxsolutions = maxsolutions, | ||
| 504 | .h = h, | ||
| 505 | .cocsepdata = (uint32_t *)data, | ||
| 506 | .h48data = ((uint32_t *)data) + COCSEP_FULLSIZE / 4, | ||
| 507 | .nextsol = &solutions | ||
| 508 | }; | ||
| 509 | |||
| 510 | nsols = 0; | ||
| 511 | for (arg.depth = minmoves; | ||
| 512 | arg.depth <= maxmoves && nsols < maxsolutions; | ||
| 513 | arg.depth++) | ||
| 514 | { | ||
| 515 | LOG("Found %" PRId64 " solutions, searching at depth %" | ||
| 516 | PRId8 "\n", nsols, arg.depth); | ||
| 517 | arg.nmoves = 0; | ||
| 518 | solve_h48_dfs(&arg); | ||
| 519 | } | ||
| 520 | |||
| 521 | /* | ||
| 522 | for (int64_t i = 0; i < 4; i++) | ||
| 523 | LOG("Data for coord = %" PRId64 ": %" PRIu8 "\n", | ||
| 524 | i, get_esep_pval(arg.h48data, i)); | ||
| 525 | */ | ||
| 526 | return nsols; | ||
| 527 | } | ||
diff --git a/test/103_gendata_h48/00_h_0.out b/test/103_gendata_h48/00_h_0.out index db6e121..cc5cf9b 100644 --- a/test/103_gendata_h48/00_h_0.out +++ b/test/103_gendata_h48/00_h_0.out | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | 59903545 | 1 | 59903605 |
| 2 | 2 | ||
| 3 | cocsepdata: | 3 | cocsepdata: |
| 4 | Classes: 3393 | 4 | Classes: 3393 |
diff --git a/test/103_gendata_h48/01_h_1.out b/test/103_gendata_h48/01_h_1.out index 456305d..bd0931c 100644 --- a/test/103_gendata_h48/01_h_1.out +++ b/test/103_gendata_h48/01_h_1.out | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | 118687270 | 1 | 118687330 |
| 2 | 2 | ||
| 3 | cocsepdata: | 3 | cocsepdata: |
| 4 | Classes: 3393 | 4 | Classes: 3393 |
