diff options
| author | Sebastiano Tronto <sebastiano@tronto.net> | 2025-12-24 11:43:24 +0100 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano@tronto.net> | 2025-12-24 11:43:24 +0100 |
| commit | 78dd90e360865af2685c1bb291d7926415fc53bb (patch) | |
| tree | 78f01fee6e51343eed62897caf1a41fb15ebf6cd /src/solvers | |
| parent | 83f6533c384a617181e818d1941b08e40aa40b7d (diff) | |
| download | nissy-core-78dd90e360865af2685c1bb291d7926415fc53bb.tar.gz nissy-core-78dd90e360865af2685c1bb291d7926415fc53bb.zip | |
First small improvements
Diffstat (limited to 'src/solvers')
| -rw-r--r-- | src/solvers/h48/solve.h | 245 |
1 files changed, 235 insertions, 10 deletions
diff --git a/src/solvers/h48/solve.h b/src/solvers/h48/solve.h index 4aa3799..10b22b9 100644 --- a/src/solvers/h48/solve.h +++ b/src/solvers/h48/solve.h | |||
| @@ -27,8 +27,8 @@ typedef struct { | |||
| 27 | solution_list_t *solution_list; | 27 | solution_list_t *solution_list; |
| 28 | int8_t lb_normal; | 28 | int8_t lb_normal; |
| 29 | int8_t lb_inverse; | 29 | int8_t lb_inverse; |
| 30 | bool use_lb_normal; | 30 | bool use_lb_normal; /* TODO remove? */ |
| 31 | bool use_lb_inverse; | 31 | bool use_lb_inverse; /* TODO remove? */ |
| 32 | uint8_t h; | 32 | uint8_t h; |
| 33 | uint8_t base; | 33 | uint8_t base; |
| 34 | const uint32_t *cocsepdata; | 34 | const uint32_t *cocsepdata; |
| @@ -58,11 +58,34 @@ typedef struct { | |||
| 58 | uint64_t tmask[H48_STARTING_MOVES]; | 58 | uint64_t tmask[H48_STARTING_MOVES]; |
| 59 | } dfsarg_solve_h48_maketasks_t; | 59 | } dfsarg_solve_h48_maketasks_t; |
| 60 | 60 | ||
| 61 | typedef struct { | ||
| 62 | uint8_t stop; | ||
| 63 | uint8_t pn; | ||
| 64 | uint8_t pi; | ||
| 65 | uint8_t lookups; | ||
| 66 | uint8_t fallbacks; | ||
| 67 | uint8_t nohalf_normal; | ||
| 68 | uint8_t nohalf_inverse; | ||
| 69 | } solve_h48_prune_return_t; | ||
| 70 | |||
| 71 | typedef struct { | ||
| 72 | cube_t cube; | ||
| 73 | cube_t inverse; | ||
| 74 | const uint32_t *cocsepdata; | ||
| 75 | const unsigned char *h48data; | ||
| 76 | const unsigned char *eoesepdata; | ||
| 77 | uint8_t target; | ||
| 78 | uint8_t h48base; | ||
| 79 | uint8_t h48h; | ||
| 80 | uint8_t lb_inverse; | ||
| 81 | } solve_h48_prune_arg_t; | ||
| 82 | |||
| 61 | STATIC long long solve_h48_dispatch(oriented_cube_t, const char *, unsigned, | 83 | STATIC long long solve_h48_dispatch(oriented_cube_t, const char *, unsigned, |
| 62 | unsigned, unsigned, unsigned, unsigned, unsigned, unsigned long long, | 84 | unsigned, unsigned, unsigned, unsigned, unsigned, unsigned long long, |
| 63 | const unsigned char *, unsigned, char *, | 85 | const unsigned char *, unsigned, char *, |
| 64 | long long [static NISSY_SIZE_SOLVE_STATS], int (*)(void *), void *); | 86 | long long [static NISSY_SIZE_SOLVE_STATS], int (*)(void *), void *); |
| 65 | STATIC_INLINE bool solve_h48_stop(dfsarg_solve_h48_t [static 1]); | 87 | STATIC_INLINE bool solve_h48_stop(dfsarg_solve_h48_t [static 1]); |
| 88 | STATIC_INLINE solve_h48_prune_return_t solve_h48_prune(solve_h48_prune_arg_t); | ||
| 66 | STATIC int64_t solve_h48_maketasks( | 89 | STATIC int64_t solve_h48_maketasks( |
| 67 | dfsarg_solve_h48_t [static 1], dfsarg_solve_h48_maketasks_t [static 1], | 90 | dfsarg_solve_h48_t [static 1], dfsarg_solve_h48_maketasks_t [static 1], |
| 68 | solve_h48_task_t [static H48_STARTING_CUBES], int [static 1]); | 91 | solve_h48_task_t [static H48_STARTING_CUBES], int [static 1]); |
| @@ -113,7 +136,6 @@ solve_h48_stop(dfsarg_solve_h48_t arg[static 1]) | |||
| 113 | uint8_t pval, pval_min, pval_eoesep; | 136 | uint8_t pval, pval_min, pval_eoesep; |
| 114 | 137 | ||
| 115 | arg->movemask_normal = arg->movemask_inverse = MM18_ALLMOVES; | 138 | arg->movemask_normal = arg->movemask_inverse = MM18_ALLMOVES; |
| 116 | arg->nodes_visited++; | ||
| 117 | 139 | ||
| 118 | n = arg->solution_moves->nmoves + arg->solution_moves->npremoves; | 140 | n = arg->solution_moves->nmoves + arg->solution_moves->npremoves; |
| 119 | target = arg->target_depth - n; | 141 | target = arg->target_depth - n; |
| @@ -123,13 +145,11 @@ solve_h48_stop(dfsarg_solve_h48_t arg[static 1]) | |||
| 123 | return false; | 145 | return false; |
| 124 | 146 | ||
| 125 | /* Preliminary probing using last computed bound, if possible */ | 147 | /* Preliminary probing using last computed bound, if possible */ |
| 126 | |||
| 127 | if ((arg->use_lb_normal && arg->lb_normal > target) || | 148 | if ((arg->use_lb_normal && arg->lb_normal > target) || |
| 128 | (arg->use_lb_inverse && arg->lb_inverse > target)) | 149 | (arg->use_lb_inverse && arg->lb_inverse > target)) |
| 129 | return true; | 150 | return true; |
| 130 | 151 | ||
| 131 | /* Preliminary corner probing */ | 152 | /* Get cdata and do preliminary corner probing */ |
| 132 | |||
| 133 | if (get_h48_cdata(arg->cube, arg->cocsepdata, &data) > target || | 153 | if (get_h48_cdata(arg->cube, arg->cocsepdata, &data) > target || |
| 134 | get_h48_cdata(arg->inverse, arg->cocsepdata, &data_inv) > target) | 154 | get_h48_cdata(arg->inverse, arg->cocsepdata, &data_inv) > target) |
| 135 | return true; | 155 | return true; |
| @@ -191,15 +211,218 @@ solve_h48_stop(dfsarg_solve_h48_t arg[static 1]) | |||
| 191 | return false; | 211 | return false; |
| 192 | } | 212 | } |
| 193 | 213 | ||
| 214 | STATIC_INLINE solve_h48_prune_return_t | ||
| 215 | solve_h48_prune(solve_h48_prune_arg_t arg) | ||
| 216 | { | ||
| 217 | solve_h48_prune_return_t ret = {0}; | ||
| 218 | uint64_t c; | ||
| 219 | uint32_t dn, di; | ||
| 220 | uint8_t pmin, pe; | ||
| 221 | |||
| 222 | ret.pi = arg.lb_inverse; | ||
| 223 | |||
| 224 | /* We'll never get a bound higher than base + 3 */ | ||
| 225 | if (arg.h48base + 3 <= arg.target) | ||
| 226 | goto solve_h48_prune_return_false; | ||
| 227 | |||
| 228 | /* Preliminary probing using last computed bound, if possible */ | ||
| 229 | if (arg.lb_inverse > arg.target) | ||
| 230 | goto solve_h48_prune_return_true; | ||
| 231 | |||
| 232 | /* Get cdata and do preliminary corner probing */ | ||
| 233 | if (get_h48_cdata(arg.inverse, arg.cocsepdata, &di) > arg.target || | ||
| 234 | get_h48_cdata(arg.cube, arg.cocsepdata, &dn) > arg.target) | ||
| 235 | goto solve_h48_prune_return_true; | ||
| 236 | |||
| 237 | if (arg.lb_inverse == 0) { | ||
| 238 | ret.lookups++; | ||
| 239 | c = coord_h48_edges( | ||
| 240 | arg.inverse, COCLASS(di), TTREP(di), arg.h48h); | ||
| 241 | ret.pi = get_h48_pval_and_min(arg.h48data, c, &pmin); | ||
| 242 | |||
| 243 | if (ret.pi == 0) { | ||
| 244 | ret.fallbacks++; | ||
| 245 | pe = get_eoesep_pval_cube(arg.eoesepdata, arg.inverse); | ||
| 246 | ret.pi = MAX(pmin, pe); | ||
| 247 | } else { | ||
| 248 | ret.pi += arg.h48base; | ||
| 249 | } | ||
| 250 | } | ||
| 251 | |||
| 252 | if (ret.pi > arg.target) | ||
| 253 | goto solve_h48_prune_return_true; | ||
| 254 | |||
| 255 | ret.nohalf_normal = ret.pi == arg.target; | ||
| 256 | |||
| 257 | ret.lookups++; | ||
| 258 | c = coord_h48_edges(arg.cube, COCLASS(dn), TTREP(dn), arg.h48h); | ||
| 259 | ret.pn = get_h48_pval_and_min(arg.h48data, c, &pmin); | ||
| 260 | |||
| 261 | if (ret.pn == 0) { | ||
| 262 | ret.fallbacks++; | ||
| 263 | pe = get_eoesep_pval_cube(arg.eoesepdata, arg.cube); | ||
| 264 | ret.pn = MAX(pmin, pe); | ||
| 265 | } else { | ||
| 266 | ret.pn += arg.h48base; | ||
| 267 | } | ||
| 268 | |||
| 269 | if (ret.pn > arg.target) | ||
| 270 | goto solve_h48_prune_return_true; | ||
| 271 | |||
| 272 | ret.nohalf_inverse = ret.pn == arg.target; | ||
| 273 | |||
| 274 | solve_h48_prune_return_false: | ||
| 275 | ret.stop = false; | ||
| 276 | return ret; | ||
| 277 | |||
| 278 | solve_h48_prune_return_true: | ||
| 279 | ret.stop = true; | ||
| 280 | return ret; | ||
| 281 | } | ||
| 282 | |||
| 283 | #if 1 | ||
| 284 | |||
| 285 | STATIC int64_t | ||
| 286 | solve_h48_dfs(dfsarg_solve_h48_t arg[static 1]) | ||
| 287 | { | ||
| 288 | int64_t ret, n; | ||
| 289 | uint8_t m, nm, nn, ni, lbn, lbi; | ||
| 290 | uint64_t mm_normal, mm_inverse; | ||
| 291 | cube_t backup_cube, backup_inverse; | ||
| 292 | solve_h48_prune_arg_t prune_arg; | ||
| 293 | solve_h48_prune_return_t prune; | ||
| 294 | |||
| 295 | nn = arg->solution_moves->nmoves; | ||
| 296 | ni = arg->solution_moves->npremoves; | ||
| 297 | nm = nn + ni; | ||
| 298 | if (equal(arg->cube, SOLVED_CUBE)) { | ||
| 299 | if (arg->target_depth != nm) | ||
| 300 | return 0; | ||
| 301 | wrapthread_mutex_lock(arg->solutions_mutex); | ||
| 302 | ret = appendsolution(arg->solution_moves, H48_STARTING_MOVES, | ||
| 303 | arg->tmask, arg->solution_settings, arg->solution_list); | ||
| 304 | wrapthread_mutex_unlock(arg->solutions_mutex); | ||
| 305 | return ret; | ||
| 306 | } | ||
| 307 | |||
| 308 | if (nm + 1 > arg->target_depth || | ||
| 309 | arg->solution_list->nsols >= arg->solution_settings->maxsolutions) | ||
| 310 | return 0; | ||
| 311 | |||
| 312 | backup_cube = arg->cube; | ||
| 313 | backup_inverse = arg->inverse; | ||
| 314 | lbn = arg->lb_normal; | ||
| 315 | lbi = arg->lb_inverse; | ||
| 316 | mm_normal = arg->movemask_normal; | ||
| 317 | mm_inverse = arg->movemask_inverse; | ||
| 318 | |||
| 319 | ret = 0; | ||
| 320 | |||
| 321 | prune_arg = (solve_h48_prune_arg_t){ | ||
| 322 | .cocsepdata = arg->cocsepdata, | ||
| 323 | .h48data = arg->h48data, | ||
| 324 | .eoesepdata = arg->h48data_fallback_eoesep, /* TODO rmove? */ | ||
| 325 | .target = arg->target_depth - (nm + 1), | ||
| 326 | .h48base = arg->base, | ||
| 327 | .h48h = arg->h, | ||
| 328 | .lb_inverse = 0, | ||
| 329 | }; | ||
| 330 | if (popcount_u32(mm_normal) <= popcount_u32(mm_inverse)) { | ||
| 331 | arg->solution_moves->nmoves++; | ||
| 332 | for (m = 0; m < 18; m++) { | ||
| 333 | if (!(mm_normal & MM_SINGLE(m))) | ||
| 334 | continue; | ||
| 335 | |||
| 336 | prune_arg.cube = move(backup_cube, m); | ||
| 337 | prune_arg.inverse = premove(backup_inverse, m); | ||
| 338 | prune_arg.lb_inverse = m % 3 == 1 ? lbi : 0; | ||
| 339 | |||
| 340 | prune = solve_h48_prune(prune_arg); | ||
| 341 | |||
| 342 | arg->nodes_visited++; | ||
| 343 | arg->table_lookups += prune.lookups; | ||
| 344 | arg->table_fallbacks += prune.fallbacks; | ||
| 345 | |||
| 346 | if (prune.stop) | ||
| 347 | continue; | ||
| 348 | |||
| 349 | arg->solution_moves->moves[nn] = m; | ||
| 350 | arg->cube = prune_arg.cube; | ||
| 351 | arg->inverse = prune_arg.inverse; | ||
| 352 | arg->lb_inverse = prune.pi; | ||
| 353 | arg->lb_normal = prune.pn; | ||
| 354 | arg->movemask_normal = allowedmask[movebase(m)]; | ||
| 355 | if (prune.nohalf_normal) | ||
| 356 | arg->movemask_normal &= MM18_NOHALFTURNS; | ||
| 357 | arg->movemask_inverse = mm_inverse; | ||
| 358 | if (prune.nohalf_inverse) | ||
| 359 | arg->movemask_inverse &= MM18_NOHALFTURNS; | ||
| 360 | |||
| 361 | n = solve_h48_dfs(arg); | ||
| 362 | |||
| 363 | if (n < 0) | ||
| 364 | return n; | ||
| 365 | ret += n; | ||
| 366 | } | ||
| 367 | arg->solution_moves->nmoves--; | ||
| 368 | } else { | ||
| 369 | arg->solution_moves->npremoves++; | ||
| 370 | for (m = 0; m < 18; m++) { | ||
| 371 | if(!(mm_inverse & MM_SINGLE(m))) | ||
| 372 | continue; | ||
| 373 | |||
| 374 | prune_arg.cube = move(backup_inverse, m); | ||
| 375 | prune_arg.inverse = premove(backup_cube, m); | ||
| 376 | prune_arg.lb_inverse = m % 3 == 1 ? lbn : 0; | ||
| 377 | prune = solve_h48_prune(prune_arg); | ||
| 378 | |||
| 379 | arg->nodes_visited++; | ||
| 380 | arg->table_lookups += prune.lookups; | ||
| 381 | arg->table_fallbacks += prune.fallbacks; | ||
| 382 | |||
| 383 | if (prune.stop) | ||
| 384 | continue; | ||
| 385 | |||
| 386 | arg->solution_moves->premoves[ni] = m; | ||
| 387 | arg->inverse = prune_arg.cube; | ||
| 388 | arg->cube = prune_arg.inverse; | ||
| 389 | arg->lb_normal = prune.pi; | ||
| 390 | arg->lb_inverse = prune.pn; | ||
| 391 | arg->movemask_normal = mm_normal; | ||
| 392 | if (prune.nohalf_inverse) | ||
| 393 | arg->movemask_normal &= MM18_NOHALFTURNS; | ||
| 394 | arg->movemask_inverse = allowedmask[movebase(m)]; | ||
| 395 | if (prune.nohalf_normal) | ||
| 396 | arg->movemask_inverse &= MM18_NOHALFTURNS; | ||
| 397 | |||
| 398 | n = solve_h48_dfs(arg); | ||
| 399 | |||
| 400 | if (n < 0) | ||
| 401 | return n; | ||
| 402 | ret += n; | ||
| 403 | } | ||
| 404 | arg->solution_moves->npremoves--; | ||
| 405 | } | ||
| 406 | |||
| 407 | arg->cube = backup_cube; | ||
| 408 | arg->inverse = backup_inverse; | ||
| 409 | |||
| 410 | return ret; | ||
| 411 | } | ||
| 412 | |||
| 413 | #else | ||
| 414 | |||
| 194 | STATIC int64_t | 415 | STATIC int64_t |
| 195 | solve_h48_dfs(dfsarg_solve_h48_t arg[static 1]) | 416 | solve_h48_dfs(dfsarg_solve_h48_t arg[static 1]) |
| 196 | { | 417 | { |
| 197 | int64_t ret, n; | 418 | int64_t ret, n; |
| 198 | uint8_t m, nm, lbn, lbi, t; | 419 | uint8_t m, nm, lbn, lbi; |
| 199 | uint64_t mm_normal, mm_inverse; | 420 | uint64_t mm_normal, mm_inverse; |
| 200 | bool ulbi, ulbn; | 421 | bool ulbi, ulbn; |
| 201 | cube_t backup_cube, backup_inverse; | 422 | cube_t backup_cube, backup_inverse; |
| 202 | 423 | ||
| 424 | arg->nodes_visited++; | ||
| 425 | |||
| 203 | nm = arg->solution_moves->nmoves + arg->solution_moves->npremoves; | 426 | nm = arg->solution_moves->nmoves + arg->solution_moves->npremoves; |
| 204 | if (equal(arg->cube, SOLVED_CUBE)) { | 427 | if (equal(arg->cube, SOLVED_CUBE)) { |
| 205 | if (arg->target_depth != nm) | 428 | if (arg->target_depth != nm) |
| @@ -214,8 +437,7 @@ solve_h48_dfs(dfsarg_solve_h48_t arg[static 1]) | |||
| 214 | if (solve_h48_stop(arg)) | 437 | if (solve_h48_stop(arg)) |
| 215 | return 0; | 438 | return 0; |
| 216 | 439 | ||
| 217 | t = arg->solution_list->shortest_sol + arg->solution_settings->optimal; | 440 | if (nm + 1 > arg->target_depth || |
| 218 | if (nm + 1 > MIN(t, arg->target_depth) || | ||
| 219 | arg->solution_list->nsols >= arg->solution_settings->maxsolutions) | 441 | arg->solution_list->nsols >= arg->solution_settings->maxsolutions) |
| 220 | return 0; | 442 | return 0; |
| 221 | 443 | ||
| @@ -281,6 +503,8 @@ solve_h48_dfs(dfsarg_solve_h48_t arg[static 1]) | |||
| 281 | return ret; | 503 | return ret; |
| 282 | } | 504 | } |
| 283 | 505 | ||
| 506 | #endif | ||
| 507 | |||
| 284 | STATIC void * | 508 | STATIC void * |
| 285 | solve_h48_runthread(void *arg) | 509 | solve_h48_runthread(void *arg) |
| 286 | { | 510 | { |
| @@ -313,7 +537,8 @@ solve_h48_runthread(void *arg) | |||
| 313 | dfsarg->lb_inverse = 0; | 537 | dfsarg->lb_inverse = 0; |
| 314 | dfsarg->use_lb_normal = false; | 538 | dfsarg->use_lb_normal = false; |
| 315 | dfsarg->use_lb_inverse = false; | 539 | dfsarg->use_lb_inverse = false; |
| 316 | dfsarg->movemask_normal = MM18_ALLMOVES; | 540 | dfsarg->movemask_normal = allowedmask[ |
| 541 | movebase(dfsarg->tasks[i].moves[H48_STARTING_MOVES-1])]; | ||
| 317 | dfsarg->movemask_inverse = MM18_ALLMOVES; | 542 | dfsarg->movemask_inverse = MM18_ALLMOVES; |
| 318 | dfsarg->tmask = dfsarg->tasks[i].tmask; | 543 | dfsarg->tmask = dfsarg->tasks[i].tmask; |
| 319 | 544 | ||
