diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/cube_public.h | 21 | ||||
| -rw-r--r-- | src/solve_h48.h | 94 |
2 files changed, 58 insertions, 57 deletions
diff --git a/src/cube_public.h b/src/cube_public.h index b537019..e080f40 100644 --- a/src/cube_public.h +++ b/src/cube_public.h | |||
| @@ -156,17 +156,22 @@ nissy_gendata( | |||
| 156 | int64_t ret; | 156 | int64_t ret; |
| 157 | uint8_t maxdepth, h, i, j; | 157 | uint8_t maxdepth, h, i, j; |
| 158 | 158 | ||
| 159 | if (!strcmp(solver, "H48")) { | 159 | if (!strcmp(solver, "h48")) { |
| 160 | /* options are in the form "h;maxdepth" */ | 160 | /* options are in the form "h;maxdepth" */ |
| 161 | for (i = 0; options[i] != ';'; i++) ; | 161 | for (i = 0; options[i] != ';'; i++) ; |
| 162 | for (j = i; options[j]; j++) ; | 162 | for (j = i; options[j]; j++) ; |
| 163 | h = atoi(options); | 163 | h = atoi(options); |
| 164 | maxdepth = atoi(&options[i+1]); | 164 | if (h != 0) { |
| 165 | ret = gendata_h48(data, h, maxdepth); | 165 | LOG("Temporarily only h=0 is supported\n"); |
| 166 | } else if (!strcmp(solver, "H48stats")) { | 166 | ret = -1; |
| 167 | ret = gendata_cocsep(data, NULL, NULL); | 167 | } else { |
| 168 | maxdepth = atoi(&options[i+1]); | ||
| 169 | ret = gendata_h48h0k4(data, maxdepth); | ||
| 170 | } | ||
| 171 | } else if (!strcmp(solver, "h48stats")) { | ||
| 172 | ret = gendata_h48h0k4(data, 20); | ||
| 168 | } else { | 173 | } else { |
| 169 | LOG("gendata: implemented only for H48 solver\n"); | 174 | LOG("gendata: implemented only for h48 solver\n"); |
| 170 | ret = -1; | 175 | ret = -1; |
| 171 | } | 176 | } |
| 172 | 177 | ||
| @@ -224,13 +229,13 @@ nissy_solve( | |||
| 224 | } | 229 | } |
| 225 | 230 | ||
| 226 | /* TODO define and use solve_options_t */ | 231 | /* TODO define and use solve_options_t */ |
| 227 | if (!strcmp(solver, "H48")) { | 232 | if (!strcmp(solver, "h48")) { |
| 228 | h = atoi(options); /* TODO: better parsing */ | 233 | h = atoi(options); /* TODO: better parsing */ |
| 229 | ret = solve_h48( | 234 | ret = solve_h48( |
| 230 | c, minmoves, maxmoves, maxsolutions, | 235 | c, minmoves, maxmoves, maxsolutions, |
| 231 | (uint8_t)h, data, solutions); | 236 | (uint8_t)h, data, solutions); |
| 232 | ret = -1; | 237 | ret = -1; |
| 233 | } else if (!strcmp(solver, "H48stats")) { | 238 | } else if (!strcmp(solver, "h48stats")) { |
| 234 | ret = solve_h48stats(c, maxmoves, data, solutions); | 239 | ret = solve_h48stats(c, maxmoves, data, solutions); |
| 235 | } else if (!strcmp(solver, "simple")) { | 240 | } else if (!strcmp(solver, "simple")) { |
| 236 | ret = solve_simple( | 241 | ret = solve_simple( |
diff --git a/src/solve_h48.h b/src/solve_h48.h index c2c541d..5f99d15 100644 --- a/src/solve_h48.h +++ b/src/solve_h48.h | |||
| @@ -36,7 +36,6 @@ typedef struct { | |||
| 36 | 36 | ||
| 37 | typedef struct { | 37 | typedef struct { |
| 38 | uint8_t depth; | 38 | uint8_t depth; |
| 39 | uint8_t h; | ||
| 40 | uint32_t *cocsepdata; | 39 | uint32_t *cocsepdata; |
| 41 | uint32_t *buf32; | 40 | uint32_t *buf32; |
| 42 | uint64_t *selfsim; | 41 | uint64_t *selfsim; |
| @@ -63,6 +62,7 @@ typedef struct { | |||
| 63 | int8_t depth; | 62 | int8_t depth; |
| 64 | uint8_t moves[MAX_SOLUTION_LENGTH]; | 63 | uint8_t moves[MAX_SOLUTION_LENGTH]; |
| 65 | uint32_t *cocsepdata; | 64 | uint32_t *cocsepdata; |
| 65 | uint32_t *h48data; | ||
| 66 | char *s; | 66 | char *s; |
| 67 | } dfsarg_solveh48stats_t; | 67 | } dfsarg_solveh48stats_t; |
| 68 | 68 | ||
| @@ -72,8 +72,8 @@ _static_inline cube_t invcoord_h48(int64_t, const cube_t *, uint8_t); | |||
| 72 | 72 | ||
| 73 | _static size_t gendata_cocsep(void *, uint64_t *, cube_t *); | 73 | _static size_t gendata_cocsep(void *, uint64_t *, cube_t *); |
| 74 | _static uint32_t gendata_cocsep_dfs(dfsarg_cocsep_t *); | 74 | _static uint32_t gendata_cocsep_dfs(dfsarg_cocsep_t *); |
| 75 | _static size_t gendata_h48(void *, uint8_t, uint8_t); | 75 | _static size_t gendata_h48h0k4(void *, uint8_t); |
| 76 | _static uint64_t gendata_esep_bfs(bfsarg_esep_t *); | 76 | _static uint64_t gendata_h48h0k4_bfs(bfsarg_esep_t *); |
| 77 | 77 | ||
| 78 | _static_inline bool get_visited(const uint8_t *, int64_t); | 78 | _static_inline bool get_visited(const uint8_t *, int64_t); |
| 79 | _static_inline void set_visited(uint8_t *, int64_t); | 79 | _static_inline void set_visited(uint8_t *, int64_t); |
| @@ -88,7 +88,7 @@ _static int64_t solve_h48_dfs(dfsarg_solveh48_t *); | |||
| 88 | _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 *); |
| 89 | 89 | ||
| 90 | _static int64_t solve_h48stats_dfs(dfsarg_solveh48stats_t *); | 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]); | 91 | _static int64_t solve_h48stats(cube_t, int8_t, const void *, char [static 12]); |
| 92 | 92 | ||
| 93 | _static_inline int64_t | 93 | _static_inline int64_t |
| 94 | 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) |
| @@ -119,12 +119,6 @@ coord_h48_edges(cube_t c, int64_t coclass, uint8_t t, uint8_t h) | |||
| 119 | edges = (esep << 11) + eo; | 119 | edges = (esep << 11) + eo; |
| 120 | 120 | ||
| 121 | return (coclass * H48_ESIZE(11) + edges) >> (11 - (int64_t)h); | 121 | return (coclass * H48_ESIZE(11) + edges) >> (11 - (int64_t)h); |
| 122 | |||
| 123 | /* | ||
| 124 | TODO: decide which alternative is better, if above or below | ||
| 125 | edges = (esep << (int64_t)h) + (eo >> (11 - (int64_t)h)); | ||
| 126 | return coclass * H48_ESIZE(h) + edges; | ||
| 127 | */ | ||
| 128 | } | 122 | } |
| 129 | 123 | ||
| 130 | /* | 124 | /* |
| @@ -133,7 +127,8 @@ the given value, because it works up to symmetry. This means that the | |||
| 133 | returned cube is a transformed cube of one that gives the correct value. | 127 | returned cube is a transformed cube of one that gives the correct value. |
| 134 | */ | 128 | */ |
| 135 | _static_inline cube_t | 129 | _static_inline cube_t |
| 136 | invcoord_h48(int64_t i, const cube_t *crep, uint8_t h) { | 130 | invcoord_h48(int64_t i, const cube_t *crep, uint8_t h) |
| 131 | { | ||
| 137 | cube_t ret; | 132 | cube_t ret; |
| 138 | int64_t hh, coclass, ee, esep, eo; | 133 | int64_t hh, coclass, ee, esep, eo; |
| 139 | 134 | ||
| @@ -274,9 +269,8 @@ TODO description | |||
| 274 | generating fixed table with h=0, k=4 | 269 | generating fixed table with h=0, k=4 |
| 275 | */ | 270 | */ |
| 276 | _static size_t | 271 | _static size_t |
| 277 | gendata_h48(void *buf, uint8_t h, uint8_t maxdepth) | 272 | gendata_h48h0k4(void *buf, uint8_t maxdepth) |
| 278 | { | 273 | { |
| 279 | const int k = 4; /* TODO: other cases? */ | ||
| 280 | uint32_t j, *buf32, *info, *cocsepdata; | 274 | uint32_t j, *buf32, *info, *cocsepdata; |
| 281 | bfsarg_esep_t arg; | 275 | bfsarg_esep_t arg; |
| 282 | int64_t sc, cc, tot, esep_max; | 276 | int64_t sc, cc, tot, esep_max; |
| @@ -290,19 +284,18 @@ gendata_h48(void *buf, uint8_t h, uint8_t maxdepth) | |||
| 290 | infosize = 88; | 284 | infosize = 88; |
| 291 | 285 | ||
| 292 | if (buf == NULL) | 286 | if (buf == NULL) |
| 293 | goto gendata_h48_return_size; | 287 | goto gendata_h48h0k4_return_size; |
| 294 | 288 | ||
| 295 | esep_max = (int64_t)ESEP_MAX(h); | 289 | esep_max = (int64_t)ESEP_MAX(0); |
| 296 | cocsepdata = (uint32_t *)buf; | 290 | cocsepdata = (uint32_t *)buf; |
| 297 | buf32 = cocsepdata + cocsepsize / 4; | 291 | buf32 = cocsepdata + cocsepsize / 4; |
| 298 | info = buf32 + (ESEP_TABLESIZE(h, k) / sizeof(uint32_t)); | 292 | info = buf32 + (ESEP_TABLESIZE(0, 4) / sizeof(uint32_t)); |
| 299 | memset(buf32, 0xFF, ESEP_TABLESIZE(h, k)); | 293 | memset(buf32, 0xFF, ESEP_TABLESIZE(0, 4)); |
| 300 | 294 | ||
| 301 | sc = coord_h48(solved, cocsepdata, h); | 295 | sc = coord_h48(solved, cocsepdata, 0); |
| 302 | set_esep_pval(buf32, sc, 0); | 296 | set_esep_pval(buf32, sc, 0); |
| 303 | info[1] = 1; | 297 | info[1] = 1; |
| 304 | arg = (bfsarg_esep_t) { | 298 | arg = (bfsarg_esep_t) { |
| 305 | .h = h, | ||
| 306 | .cocsepdata = cocsepdata, | 299 | .cocsepdata = cocsepdata, |
| 307 | .buf32 = buf32, | 300 | .buf32 = buf32, |
| 308 | .crep = crep, | 301 | .crep = crep, |
| @@ -314,7 +307,7 @@ gendata_h48(void *buf, uint8_t h, uint8_t maxdepth) | |||
| 314 | arg.depth++ | 307 | arg.depth++ |
| 315 | ) { | 308 | ) { |
| 316 | LOG("esep: generating depth %" PRIu8 "\n", arg.depth); | 309 | LOG("esep: generating depth %" PRIu8 "\n", arg.depth); |
| 317 | cc = gendata_esep_bfs(&arg); | 310 | cc = gendata_h48h0k4_bfs(&arg); |
| 318 | tot += cc; | 311 | tot += cc; |
| 319 | info[arg.depth+1] = cc; | 312 | info[arg.depth+1] = cc; |
| 320 | LOG("found %" PRIu64 "\n", cc); | 313 | LOG("found %" PRIu64 "\n", cc); |
| @@ -328,25 +321,25 @@ gendata_h48(void *buf, uint8_t h, uint8_t maxdepth) | |||
| 328 | for (j = 0; j <= info[0]; j++) | 321 | for (j = 0; j <= info[0]; j++) |
| 329 | LOG("%" PRIu8 ":\t%" PRIu32 "\n", j, info[j+1]); | 322 | LOG("%" PRIu8 ":\t%" PRIu32 "\n", j, info[j+1]); |
| 330 | 323 | ||
| 331 | gendata_h48_return_size: | 324 | gendata_h48h0k4_return_size: |
| 332 | return cocsepsize + ESEP_TABLESIZE(h, k) + infosize; | 325 | return cocsepsize + ESEP_TABLESIZE(0, 4) + infosize; |
| 333 | } | 326 | } |
| 334 | 327 | ||
| 335 | _static uint64_t | 328 | _static uint64_t |
| 336 | gendata_esep_bfs(bfsarg_esep_t *arg) | 329 | gendata_h48h0k4_bfs(bfsarg_esep_t *arg) |
| 337 | { | 330 | { |
| 338 | uint8_t c, m, x; | 331 | uint8_t c, m, x; |
| 339 | uint32_t cc; | 332 | uint32_t cc; |
| 340 | int64_t i, j, k, t, cocsep_coord, sim, esep_max; | 333 | int64_t i, j, k, t, cocsep_coord, sim, esep_max; |
| 341 | cube_t cube, moved, transd; | 334 | cube_t cube, moved, transd; |
| 342 | 335 | ||
| 343 | esep_max = (uint64_t)ESEP_MAX(arg->h); | 336 | esep_max = (uint64_t)ESEP_MAX(0); |
| 344 | 337 | ||
| 345 | for (i = 0, cc = 0; i < esep_max; i++) { | 338 | for (i = 0, cc = 0; i < esep_max; i++) { |
| 346 | c = get_esep_pval(arg->buf32, i); | 339 | c = get_esep_pval(arg->buf32, i); |
| 347 | if (c != arg->depth - 1) | 340 | if (c != arg->depth - 1) |
| 348 | continue; | 341 | continue; |
| 349 | cube = invcoord_h48(i, arg->crep, arg->h); | 342 | cube = invcoord_h48(i, arg->crep, 0); |
| 350 | for (m = 0; m < 18; m++) { | 343 | for (m = 0; m < 18; m++) { |
| 351 | /* | 344 | /* |
| 352 | * TODO: here we can optimize by computing at first | 345 | * TODO: here we can optimize by computing at first |
| @@ -354,19 +347,19 @@ gendata_esep_bfs(bfsarg_esep_t *arg) | |||
| 354 | * the edge parts for each transformation. | 347 | * the edge parts for each transformation. |
| 355 | */ | 348 | */ |
| 356 | moved = move(cube, m); | 349 | moved = move(cube, m); |
| 357 | j = coord_h48(moved, arg->cocsepdata, arg->h); | 350 | j = coord_h48(moved, arg->cocsepdata, 0); |
| 358 | x = get_esep_pval(arg->buf32, j); | 351 | x = get_esep_pval(arg->buf32, j); |
| 359 | if (x <= arg->depth) | 352 | if (x <= arg->depth) |
| 360 | continue; | 353 | continue; |
| 361 | set_esep_pval(arg->buf32, j, arg->depth); | 354 | set_esep_pval(arg->buf32, j, arg->depth); |
| 362 | cc += x != arg->depth; | 355 | cc += x != arg->depth; |
| 363 | cocsep_coord = j / H48_ESIZE(arg->h); | 356 | cocsep_coord = j / H48_ESIZE(0); |
| 364 | sim = arg->selfsim[cocsep_coord] >> 1; | 357 | sim = arg->selfsim[cocsep_coord] >> 1; |
| 365 | for (t = 1; t < 48 && sim; t++, sim >>= 1) { | 358 | for (t = 1; t < 48 && sim; t++, sim >>= 1) { |
| 366 | if (!(sim & 1)) | 359 | if (!(sim & 1)) |
| 367 | continue; | 360 | continue; |
| 368 | transd = transform(moved, t); | 361 | transd = transform(moved, t); |
| 369 | k = coord_h48(transd, arg->cocsepdata, arg->h); | 362 | k = coord_h48(transd, arg->cocsepdata, 0); |
| 370 | x = get_esep_pval(arg->buf32, k); | 363 | x = get_esep_pval(arg->buf32, k); |
| 371 | if (x <= arg->depth) | 364 | if (x <= arg->depth) |
| 372 | continue; | 365 | continue; |
| @@ -539,46 +532,45 @@ solve_h48( | |||
| 539 | solve_h48_dfs(&arg); | 532 | solve_h48_dfs(&arg); |
| 540 | } | 533 | } |
| 541 | 534 | ||
| 542 | /* | ||
| 543 | for (int64_t i = 0; i < 4; i++) | ||
| 544 | LOG("Data for coord = %" PRId64 ": %" PRIu8 "\n", | ||
| 545 | i, get_esep_pval(arg.h48data, i)); | ||
| 546 | */ | ||
| 547 | return nsols; | 535 | return nsols; |
| 548 | } | 536 | } |
| 549 | 537 | ||
| 550 | /* | 538 | /* |
| 551 | The h48stats solver computes how many moves it takes to solve to each of | 539 | The h48stats solver computes how many moves it takes to solve to |
| 552 | the 13 h48 coordinates: the corner-only coordinate, and 12 cocsep+esep | 540 | each of the 12 h48 coordinates, one for each value of h from 0 to 11. |
| 553 | coordinates with h from 0 to 11. The solutions array is filled with | 541 | The solutions array is filled with the length of the solutions. The |
| 554 | the length of the solutions: solutions[0] contains the value for the | 542 | solution array is therefore not a printable string. |
| 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 | */ | 543 | */ |
| 559 | _static int64_t | 544 | _static int64_t |
| 560 | solve_h48stats_dfs(dfsarg_solveh48stats_t *arg) | 545 | solve_h48stats_dfs(dfsarg_solveh48stats_t *arg) |
| 561 | { | 546 | { |
| 547 | const int64_t limit = 11; | ||
| 548 | |||
| 562 | int8_t bound, u; | 549 | int8_t bound, u; |
| 563 | uint8_t m; | 550 | uint8_t m; |
| 564 | uint32_t d; | 551 | uint32_t d; |
| 565 | int64_t coord, h; | 552 | int64_t coord, h; |
| 566 | dfsarg_solveh48stats_t nextarg; | 553 | dfsarg_solveh48stats_t nextarg; |
| 567 | 554 | ||
| 555 | /* Check cocsep lower bound (corners only) */ | ||
| 568 | bound = get_h48_cdata(arg->cube, arg->cocsepdata, &d); | 556 | bound = get_h48_cdata(arg->cube, arg->cocsepdata, &d); |
| 569 | if (bound + arg->nmoves > arg->depth) | 557 | if (bound + arg->nmoves > arg->depth) |
| 570 | return 0; | 558 | return 0; |
| 571 | 559 | ||
| 572 | u = COCLASS(d) == 0 && arg->s[0] == 99; | 560 | /* Check h48 lower bound for h=0 (esep, but no eo) */ |
| 573 | arg->s[0] = u * arg->nmoves + (1-u) * arg->s[0]; | 561 | coord = coord_h48_edges(arg->cube, COCLASS(d), TTREP(d), 0); |
| 562 | bound = get_esep_pval(arg->h48data, coord); | ||
| 563 | if (bound + arg->nmoves > arg->depth) | ||
| 564 | return 0; | ||
| 574 | 565 | ||
| 566 | /* Update all other values, if solved */ | ||
| 575 | coord = coord_h48_edges(arg->cube, COCLASS(d), TTREP(d), 11); | 567 | coord = coord_h48_edges(arg->cube, COCLASS(d), TTREP(d), 11); |
| 576 | for (h = 0; h <= 11; h++) { | 568 | for (h = 0; h <= limit; h++) { |
| 577 | u = coord >> (11-h) == 0 && arg->s[h+1] == 99; | 569 | u = coord >> (11-h) == 0 && arg->s[h] == 99; |
| 578 | arg->s[h+1] = u * arg->nmoves + (1-u) * arg->s[h+1]; | 570 | arg->s[h] = u * arg->nmoves + (1-u) * arg->s[h]; |
| 579 | } | 571 | } |
| 580 | 572 | ||
| 581 | if (arg->s[12] != 99) | 573 | if (arg->s[limit] != 99) |
| 582 | return 0; | 574 | return 0; |
| 583 | 575 | ||
| 584 | nextarg = *arg; | 576 | nextarg = *arg; |
| @@ -603,23 +595,27 @@ solve_h48stats( | |||
| 603 | cube_t cube, | 595 | cube_t cube, |
| 604 | int8_t maxmoves, | 596 | int8_t maxmoves, |
| 605 | const void *data, | 597 | const void *data, |
| 606 | char solutions[static 13] | 598 | char solutions[static 12] |
| 607 | ) | 599 | ) |
| 608 | { | 600 | { |
| 609 | int i; | 601 | int i; |
| 602 | size_t cocsepsize; | ||
| 610 | dfsarg_solveh48stats_t arg; | 603 | dfsarg_solveh48stats_t arg; |
| 611 | 604 | ||
| 605 | cocsepsize = gendata_cocsep(NULL, NULL, NULL); | ||
| 606 | |||
| 612 | arg = (dfsarg_solveh48stats_t) { | 607 | arg = (dfsarg_solveh48stats_t) { |
| 613 | .cube = cube, | 608 | .cube = cube, |
| 614 | .cocsepdata = (uint32_t *)data, | 609 | .cocsepdata = (uint32_t *)data, |
| 610 | .h48data = ((uint32_t *)data) + (cocsepsize/4), | ||
| 615 | .s = solutions | 611 | .s = solutions |
| 616 | }; | 612 | }; |
| 617 | 613 | ||
| 618 | for (i = 0; i < 13; i++) | 614 | for (i = 0; i < 12; i++) |
| 619 | solutions[i] = (char)99; | 615 | solutions[i] = (char)99; |
| 620 | 616 | ||
| 621 | for (arg.depth = 0; | 617 | for (arg.depth = 0; |
| 622 | arg.depth <= maxmoves && solutions[12] == 99; | 618 | arg.depth <= maxmoves && solutions[11] == 99; |
| 623 | arg.depth++) | 619 | arg.depth++) |
| 624 | { | 620 | { |
| 625 | arg.nmoves = 0; | 621 | arg.nmoves = 0; |
