diff options
Diffstat (limited to 'src/solvers/h48/solve.h')
| -rw-r--r-- | src/solvers/h48/solve.h | 375 |
1 files changed, 242 insertions, 133 deletions
diff --git a/src/solvers/h48/solve.h b/src/solvers/h48/solve.h index 4aa3799..15ac6ea 100644 --- a/src/solvers/h48/solve.h +++ b/src/solvers/h48/solve.h | |||
| @@ -1,11 +1,5 @@ | |||
| 1 | #define H48_STARTING_MOVES 4 | 1 | #define H48_STARTING_MOVES 4 |
| 2 | 2 | #define H48_STARTING_CUBES 43254 | |
| 3 | #if H48_STARTING_MOVES == 3 | ||
| 4 | #define H48_STARTING_CUBES 3240 /* Number of 3-move sequences */ | ||
| 5 | #elif H48_STARTING_MOVES == 4 | ||
| 6 | #define H48_STARTING_CUBES 43254 /* Number of 4-move sequences */ | ||
| 7 | #endif | ||
| 8 | |||
| 9 | #define H48_SORT_TASKS_MIN_DEPTH 16 | 3 | #define H48_SORT_TASKS_MIN_DEPTH 16 |
| 10 | #define H48_LOG_PROGRESS_MIN_DEPTH 15 | 4 | #define H48_LOG_PROGRESS_MIN_DEPTH 15 |
| 11 | 5 | ||
| @@ -14,6 +8,7 @@ typedef struct { | |||
| 14 | uint8_t moves[H48_STARTING_MOVES]; | 8 | uint8_t moves[H48_STARTING_MOVES]; |
| 15 | int64_t rank; | 9 | int64_t rank; |
| 16 | uint64_t tmask[H48_STARTING_MOVES]; | 10 | uint64_t tmask[H48_STARTING_MOVES]; |
| 11 | uint8_t pval; | ||
| 17 | } solve_h48_task_t; | 12 | } solve_h48_task_t; |
| 18 | 13 | ||
| 19 | typedef struct { | 14 | typedef struct { |
| @@ -25,15 +20,13 @@ typedef struct { | |||
| 25 | solution_settings_t *solution_settings; | 20 | solution_settings_t *solution_settings; |
| 26 | const uint64_t *tmask; | 21 | const uint64_t *tmask; |
| 27 | solution_list_t *solution_list; | 22 | solution_list_t *solution_list; |
| 28 | int8_t lb_normal; | 23 | uint8_t lb_normal; |
| 29 | int8_t lb_inverse; | 24 | uint8_t lb_inverse; |
| 30 | bool use_lb_normal; | ||
| 31 | bool use_lb_inverse; | ||
| 32 | uint8_t h; | 25 | uint8_t h; |
| 33 | uint8_t base; | 26 | uint8_t base; |
| 34 | const uint32_t *cocsepdata; | 27 | const uint32_t *cocsepdata; |
| 35 | const unsigned char *h48data; | 28 | const unsigned char *h48data; |
| 36 | const unsigned char *h48data_fallback_eoesep; | 29 | const unsigned char *eoesepdata; |
| 37 | uint64_t movemask_normal; | 30 | uint64_t movemask_normal; |
| 38 | uint64_t movemask_inverse; | 31 | uint64_t movemask_inverse; |
| 39 | uint64_t nodes_visited; | 32 | uint64_t nodes_visited; |
| @@ -58,11 +51,30 @@ typedef struct { | |||
| 58 | uint64_t tmask[H48_STARTING_MOVES]; | 51 | uint64_t tmask[H48_STARTING_MOVES]; |
| 59 | } dfsarg_solve_h48_maketasks_t; | 52 | } dfsarg_solve_h48_maketasks_t; |
| 60 | 53 | ||
| 54 | typedef struct { | ||
| 55 | cube_t cube; | ||
| 56 | cube_t inverse; | ||
| 57 | uint64_t coord; | ||
| 58 | uint8_t m; | ||
| 59 | uint8_t pn; | ||
| 60 | uint8_t pi; | ||
| 61 | uint8_t stop; | ||
| 62 | } h48_prune_t; | ||
| 63 | |||
| 61 | STATIC long long solve_h48_dispatch(oriented_cube_t, const char *, unsigned, | 64 | STATIC long long solve_h48_dispatch(oriented_cube_t, const char *, unsigned, |
| 62 | unsigned, unsigned, unsigned, unsigned, unsigned, unsigned long long, | 65 | unsigned, unsigned, unsigned, unsigned, unsigned, unsigned long long, |
| 63 | const unsigned char *, unsigned, char *, | 66 | const unsigned char *, unsigned, char *, |
| 64 | long long [static NISSY_SIZE_SOLVE_STATS], int (*)(void *), void *); | 67 | long long [static NISSY_SIZE_SOLVE_STATS], int (*)(void *), void *); |
| 65 | STATIC_INLINE bool solve_h48_stop(dfsarg_solve_h48_t [static 1]); | 68 | STATIC_INLINE void h48_prune_pipeline(dfsarg_solve_h48_t [static 1], |
| 69 | h48_prune_t [static NMOVES], uint8_t, bool); | ||
| 70 | STATIC_INLINE uint8_t h48_prune_lookup( | ||
| 71 | uint64_t, cube_t, dfsarg_solve_h48_t [static 1]); | ||
| 72 | STATIC_INLINE uint8_t h48_prune_lookup_nocoord( | ||
| 73 | cube_t, dfsarg_solve_h48_t [static 1]); | ||
| 74 | STATIC_INLINE void h48_prune_restore_normal(const h48_prune_t [static 1], | ||
| 75 | dfsarg_solve_h48_t [static 1], uint8_t); | ||
| 76 | STATIC_INLINE void h48_prune_restore_inverse(const h48_prune_t [static 1], | ||
| 77 | dfsarg_solve_h48_t [static 1], uint8_t); | ||
| 66 | STATIC int64_t solve_h48_maketasks( | 78 | STATIC int64_t solve_h48_maketasks( |
| 67 | dfsarg_solve_h48_t [static 1], dfsarg_solve_h48_maketasks_t [static 1], | 79 | 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]); | 80 | solve_h48_task_t [static H48_STARTING_CUBES], int [static 1]); |
| @@ -104,151 +116,242 @@ STATIC long long solve_h48_dispatch( | |||
| 104 | poll_status, poll_status_data); | 116 | poll_status, poll_status_data); |
| 105 | } | 117 | } |
| 106 | 118 | ||
| 107 | STATIC_INLINE bool | 119 | STATIC_INLINE uint8_t |
| 108 | solve_h48_stop(dfsarg_solve_h48_t arg[static 1]) | 120 | h48_prune_lookup( |
| 121 | uint64_t coord, | ||
| 122 | cube_t cube, | ||
| 123 | dfsarg_solve_h48_t arg[static 1] | ||
| 124 | ) | ||
| 109 | { | 125 | { |
| 110 | uint32_t data, data_inv; | 126 | uint8_t p, pmin, pe; |
| 111 | int64_t coord; | ||
| 112 | int8_t target, nh, n; | ||
| 113 | uint8_t pval, pval_min, pval_eoesep; | ||
| 114 | 127 | ||
| 115 | arg->movemask_normal = arg->movemask_inverse = MM18_ALLMOVES; | 128 | arg->table_lookups++; |
| 116 | arg->nodes_visited++; | 129 | p = get_h48_pval_and_min(arg->h48data, coord, &pmin); |
| 130 | if (p == 0) { | ||
| 131 | arg->table_fallbacks++; | ||
| 132 | pe = get_eoesep_pval_cube(arg->eoesepdata, cube); | ||
| 133 | return MAX(pmin, pe); | ||
| 134 | } else { | ||
| 135 | return p + arg->base; | ||
| 136 | } | ||
| 137 | } | ||
| 117 | 138 | ||
| 118 | n = arg->solution_moves->nmoves + arg->solution_moves->npremoves; | 139 | STATIC_INLINE uint8_t |
| 119 | target = arg->target_depth - n; | 140 | h48_prune_lookup_nocoord( |
| 141 | cube_t cube, | ||
| 142 | dfsarg_solve_h48_t arg[static 1] | ||
| 143 | ) | ||
| 144 | { | ||
| 145 | uint32_t cdata; | ||
| 146 | uint64_t coord; | ||
| 120 | 147 | ||
| 121 | /* We'll never get a bound higher than base + 3 */ | 148 | get_h48_cdata(cube, arg->cocsepdata, &cdata); |
| 122 | if (arg->base + 3 <= target) | 149 | coord = coord_h48_edges(cube, COCLASS(cdata), TTREP(cdata), arg->h); |
| 123 | return false; | 150 | return h48_prune_lookup(coord, cube, arg); |
| 151 | } | ||
| 124 | 152 | ||
| 125 | /* Preliminary probing using last computed bound, if possible */ | 153 | STATIC_INLINE void |
| 154 | h48_prune_pipeline( | ||
| 155 | dfsarg_solve_h48_t arg[static 1], | ||
| 156 | h48_prune_t prune[static NMOVES], | ||
| 157 | uint8_t target, | ||
| 158 | bool normal | ||
| 159 | ) | ||
| 160 | { | ||
| 161 | uint64_t i; | ||
| 162 | uint32_t cdata; | ||
| 163 | uint8_t m, p; | ||
| 126 | 164 | ||
| 127 | if ((arg->use_lb_normal && arg->lb_normal > target) || | 165 | /* Stage 0: initialize the neighbors array */ |
| 128 | (arg->use_lb_inverse && arg->lb_inverse > target)) | 166 | memset(prune, 0, NMOVES * sizeof(h48_prune_t)); |
| 129 | return true; | 167 | if (normal) { |
| 168 | for (m = 0; m < NMOVES; m++) { | ||
| 169 | prune[m].pi = m % 3 == 1 ? arg->lb_inverse : 0; | ||
| 170 | if (!(arg->movemask_normal & MM_SINGLE(m)) || | ||
| 171 | prune[m].pi > target) { | ||
| 172 | prune[m].stop = 1; | ||
| 173 | continue; | ||
| 174 | } | ||
| 175 | prune[m].cube = move(arg->cube, m); | ||
| 176 | prune[m].inverse = premove(arg->inverse, m); | ||
| 177 | prune[m].m = m; | ||
| 178 | arg->nodes_visited++; | ||
| 179 | } | ||
| 180 | } else { | ||
| 181 | for (m = 0; m < NMOVES; m++) { | ||
| 182 | prune[m].pi = m % 3 == 1 ? arg->lb_normal : 0; | ||
| 183 | if (!(arg->movemask_inverse & MM_SINGLE(m)) || | ||
| 184 | prune[m].pi > target) { | ||
| 185 | prune[m].stop = 1; | ||
| 186 | continue; | ||
| 187 | } | ||
| 188 | prune[m].cube = move(arg->inverse, m); | ||
| 189 | prune[m].inverse = premove(arg->cube, m); | ||
| 190 | prune[m].m = m; | ||
| 191 | arg->nodes_visited++; | ||
| 192 | } | ||
| 193 | } | ||
| 130 | 194 | ||
| 131 | /* Preliminary corner probing */ | 195 | /* We'll never get a bound higher than base + 3 */ |
| 196 | if (target > arg->base + 3) | ||
| 197 | return; | ||
| 132 | 198 | ||
| 133 | if (get_h48_cdata(arg->cube, arg->cocsepdata, &data) > target || | 199 | /* Stage 1: cdata and prefetch inverse */ |
| 134 | get_h48_cdata(arg->inverse, arg->cocsepdata, &data_inv) > target) | 200 | for (m = 0; m < NMOVES; m++) { |
| 135 | return true; | 201 | if (prune[m].stop) |
| 202 | continue; | ||
| 136 | 203 | ||
| 137 | /* Inverse probing */ | 204 | p = get_h48_cdata(prune[m].inverse, arg->cocsepdata, &cdata); |
| 205 | if (p > target) { | ||
| 206 | prune[m].stop = 1; | ||
| 207 | continue; | ||
| 208 | } | ||
| 209 | if (prune[m].pi == 0) { | ||
| 210 | prune[m].coord = coord_h48_edges(prune[m].inverse, | ||
| 211 | COCLASS(cdata), TTREP(cdata), arg->h); | ||
| 212 | i = H48_INDEX(H48_LINE_EXT(prune[m].coord)); | ||
| 213 | prefetch(arg->h48data, i); | ||
| 214 | } | ||
| 215 | } | ||
| 138 | 216 | ||
| 139 | if (!arg->use_lb_inverse) { | 217 | /* Stage 2: get pval from inverse, prefetch normal */ |
| 140 | arg->table_lookups++; | 218 | for (m = 0; m < NMOVES; m++) { |
| 141 | arg->use_lb_inverse = true; | 219 | if (prune[m].stop) |
| 142 | coord = coord_h48_edges( | 220 | continue; |
| 143 | arg->inverse, COCLASS(data_inv), TTREP(data_inv), arg->h); | ||
| 144 | pval = get_h48_pval_and_min(arg->h48data, coord, &pval_min); | ||
| 145 | 221 | ||
| 146 | if (pval == 0) { | 222 | if (prune[m].pi == 0) { |
| 147 | arg->table_fallbacks++; | 223 | prune[m].pi = h48_prune_lookup( |
| 224 | prune[m].coord, prune[m].inverse, arg); | ||
| 225 | if (prune[m].pi > target) { | ||
| 226 | prune[m].stop = 1; | ||
| 227 | continue; | ||
| 228 | } | ||
| 229 | } | ||
| 148 | 230 | ||
| 149 | pval_eoesep = get_eoesep_pval_cube( | 231 | p = get_h48_cdata(prune[m].cube, arg->cocsepdata, &cdata); |
| 150 | arg->h48data_fallback_eoesep, arg->inverse); | 232 | if (p > target) { |
| 151 | pval = MAX(pval_min, pval_eoesep); | 233 | prune[m].stop = 1; |
| 152 | } else { | 234 | continue; |
| 153 | pval += arg->base; | ||
| 154 | } | 235 | } |
| 236 | prune[m].coord = coord_h48_edges( | ||
| 237 | prune[m].cube, COCLASS(cdata), TTREP(cdata), arg->h); | ||
| 238 | i = H48_INDEX(H48_LINE_EXT(prune[m].coord)); | ||
| 239 | prefetch(arg->h48data, i); | ||
| 240 | } | ||
| 155 | 241 | ||
| 156 | arg->lb_inverse = pval; | 242 | /* Stage 3: get pval from normal */ |
| 243 | for (m = 0; m < NMOVES; m++) { | ||
| 244 | if (prune[m].stop) | ||
| 245 | continue; | ||
| 246 | |||
| 247 | prune[m].pn = h48_prune_lookup( | ||
| 248 | prune[m].coord, prune[m].cube, arg); | ||
| 249 | prune[m].stop = prune[m].pn > target; | ||
| 157 | } | 250 | } |
| 251 | } | ||
| 158 | 252 | ||
| 159 | if (arg->lb_inverse > target) | 253 | STATIC_INLINE void |
| 160 | return true; | 254 | h48_prune_restore_normal( |
| 161 | nh = arg->lb_inverse == target; | 255 | const h48_prune_t prune[static 1], |
| 162 | arg->movemask_normal = nh * MM18_NOHALFTURNS + (1-nh) * MM18_ALLMOVES; | 256 | dfsarg_solve_h48_t arg[static 1], |
| 257 | uint8_t target | ||
| 258 | ) | ||
| 259 | { | ||
| 260 | uint8_t nm; | ||
| 163 | 261 | ||
| 164 | /* Normal probing */ | 262 | arg->cube = prune->cube; |
| 263 | arg->inverse = prune->inverse; | ||
| 264 | arg->lb_inverse = prune->pi; | ||
| 265 | arg->lb_normal = prune->pn; | ||
| 165 | 266 | ||
| 166 | if (!arg->use_lb_normal) { | 267 | nm = arg->solution_moves->nmoves; |
| 167 | arg->table_lookups++; | 268 | arg->solution_moves->moves[nm-1] = prune->m; |
| 168 | arg->use_lb_normal = true; | 269 | arg->movemask_normal = allowedmask[movebase(prune->m)]; |
| 169 | coord = coord_h48_edges( | ||
| 170 | arg->cube, COCLASS(data), TTREP(data), arg->h); | ||
| 171 | pval = get_h48_pval_and_min(arg->h48data, coord, &pval_min); | ||
| 172 | 270 | ||
| 173 | if (pval == 0) { | 271 | if (arg->lb_inverse == target) |
| 174 | arg->table_fallbacks++; | 272 | arg->movemask_normal &= MM18_NOHALFTURNS; |
| 273 | if (arg->lb_normal == target) | ||
| 274 | arg->movemask_inverse &= MM18_NOHALFTURNS; | ||
| 275 | } | ||
| 175 | 276 | ||
| 176 | pval_eoesep = get_eoesep_pval_cube( | 277 | STATIC_INLINE void |
| 177 | arg->h48data_fallback_eoesep, arg->cube); | 278 | h48_prune_restore_inverse( |
| 178 | pval = MAX(pval_min, pval_eoesep); | 279 | const h48_prune_t prune[static 1], |
| 179 | } else { | 280 | dfsarg_solve_h48_t arg[static 1], |
| 180 | pval += arg->base; | 281 | uint8_t target |
| 181 | } | 282 | ) |
| 283 | { | ||
| 284 | uint8_t nm; | ||
| 182 | 285 | ||
| 183 | arg->lb_normal = pval; | 286 | arg->cube = prune->inverse; |
| 184 | } | 287 | arg->inverse = prune->cube; |
| 288 | arg->lb_inverse = prune->pn; | ||
| 289 | arg->lb_normal = prune->pi; | ||
| 185 | 290 | ||
| 186 | if (arg->lb_normal > target) | 291 | nm = arg->solution_moves->npremoves; |
| 187 | return true; | 292 | arg->solution_moves->premoves[nm-1] = prune->m; |
| 188 | nh = arg->lb_normal == target; | 293 | arg->movemask_inverse = allowedmask[movebase(prune->m)]; |
| 189 | arg->movemask_inverse = nh * MM18_NOHALFTURNS + (1-nh) * MM18_ALLMOVES; | ||
| 190 | 294 | ||
| 191 | return false; | 295 | if (arg->lb_inverse == target) |
| 296 | arg->movemask_normal &= MM18_NOHALFTURNS; | ||
| 297 | if (arg->lb_normal == target) | ||
| 298 | arg->movemask_inverse &= MM18_NOHALFTURNS; | ||
| 192 | } | 299 | } |
| 193 | 300 | ||
| 194 | STATIC int64_t | 301 | STATIC int64_t |
| 195 | solve_h48_dfs(dfsarg_solve_h48_t arg[static 1]) | 302 | solve_h48_dfs(dfsarg_solve_h48_t arg[static 1]) |
| 196 | { | 303 | { |
| 197 | int64_t ret, n; | 304 | int64_t ret, n; |
| 198 | uint8_t m, nm, lbn, lbi, t; | 305 | uint8_t m, nm, nn, ni, target; |
| 199 | uint64_t mm_normal, mm_inverse; | 306 | uint64_t mm_normal, mm_inverse; |
| 200 | bool ulbi, ulbn; | 307 | cube_t cube, backup_cube, backup_inverse; |
| 201 | cube_t backup_cube, backup_inverse; | 308 | h48_prune_t prune[NMOVES]; |
| 202 | |||
| 203 | nm = arg->solution_moves->nmoves + arg->solution_moves->npremoves; | ||
| 204 | if (equal(arg->cube, SOLVED_CUBE)) { | ||
| 205 | if (arg->target_depth != nm) | ||
| 206 | return 0; | ||
| 207 | wrapthread_mutex_lock(arg->solutions_mutex); | ||
| 208 | ret = appendsolution(arg->solution_moves, H48_STARTING_MOVES, | ||
| 209 | arg->tmask, arg->solution_settings, arg->solution_list); | ||
| 210 | wrapthread_mutex_unlock(arg->solutions_mutex); | ||
| 211 | return ret; | ||
| 212 | } | ||
| 213 | 309 | ||
| 214 | if (solve_h48_stop(arg)) | 310 | if (equal(arg->cube, SOLVED_CUBE) || /* Solved before target depth */ |
| 311 | arg->solution_list->nsols >= arg->solution_settings->maxsolutions) | ||
| 215 | return 0; | 312 | return 0; |
| 216 | 313 | ||
| 217 | t = arg->solution_list->shortest_sol + arg->solution_settings->optimal; | 314 | nn = arg->solution_moves->nmoves; |
| 218 | if (nm + 1 > MIN(t, arg->target_depth) || | 315 | ni = arg->solution_moves->npremoves; |
| 219 | arg->solution_list->nsols >= arg->solution_settings->maxsolutions) | 316 | nm = nn + ni; |
| 317 | target = arg->target_depth - (nm + 1); | ||
| 318 | mm_normal = arg->movemask_normal; | ||
| 319 | mm_inverse = arg->movemask_inverse; | ||
| 320 | if (target == 0) { /* Last move */ | ||
| 321 | arg->solution_moves->nmoves++; | ||
| 322 | for (m = 0; m < NMOVES; m++) { | ||
| 323 | if (!(mm_normal & mm_inverse & MM_SINGLE(m))) | ||
| 324 | continue; | ||
| 325 | cube = move(arg->cube, m); | ||
| 326 | arg->solution_moves->moves[nn] = m; | ||
| 327 | arg->nodes_visited++; | ||
| 328 | if (!equal(cube, SOLVED_CUBE)) | ||
| 329 | continue; | ||
| 330 | wrapthread_mutex_lock(arg->solutions_mutex); | ||
| 331 | ret = appendsolution(arg->solution_moves, | ||
| 332 | H48_STARTING_MOVES, arg->tmask, | ||
| 333 | arg->solution_settings, arg->solution_list); | ||
| 334 | wrapthread_mutex_unlock(arg->solutions_mutex); | ||
| 335 | arg->solution_moves->nmoves--; | ||
| 336 | return ret; | ||
| 337 | } | ||
| 338 | arg->solution_moves->nmoves--; | ||
| 220 | return 0; | 339 | return 0; |
| 340 | } | ||
| 221 | 341 | ||
| 222 | backup_cube = arg->cube; | 342 | backup_cube = arg->cube; |
| 223 | backup_inverse = arg->inverse; | 343 | backup_inverse = arg->inverse; |
| 224 | lbn = arg->lb_normal; | ||
| 225 | lbi = arg->lb_inverse; | ||
| 226 | ulbn = arg->use_lb_normal; | ||
| 227 | ulbi = arg->use_lb_inverse; | ||
| 228 | 344 | ||
| 229 | ret = 0; | 345 | ret = 0; |
| 230 | mm_normal = arg->movemask_normal; | ||
| 231 | if (arg->solution_moves->nmoves > 0) { | ||
| 232 | m = arg->solution_moves->moves[arg->solution_moves->nmoves-1]; | ||
| 233 | mm_normal &= allowedmask[movebase(m)]; | ||
| 234 | } | ||
| 235 | mm_inverse = arg->movemask_inverse; | ||
| 236 | if (arg->solution_moves->npremoves > 0) { | ||
| 237 | m = arg->solution_moves->premoves[arg->solution_moves->npremoves-1]; | ||
| 238 | mm_inverse &= allowedmask[movebase(m)]; | ||
| 239 | } | ||
| 240 | if (popcount_u32(mm_normal) <= popcount_u32(mm_inverse)) { | 346 | if (popcount_u32(mm_normal) <= popcount_u32(mm_inverse)) { |
| 347 | h48_prune_pipeline(arg, prune, target, true); | ||
| 241 | arg->solution_moves->nmoves++; | 348 | arg->solution_moves->nmoves++; |
| 242 | for (m = 0; m < 18; m++) { | 349 | for (m = 0; m < NMOVES; m++) { |
| 243 | if (!(mm_normal & MM_SINGLE(m))) | 350 | if (prune[m].stop) |
| 244 | continue; | 351 | continue; |
| 245 | arg->solution_moves->moves[ | 352 | arg->movemask_normal = mm_normal; |
| 246 | arg->solution_moves->nmoves-1] = m; | 353 | arg->movemask_inverse = mm_inverse; |
| 247 | arg->cube = move(backup_cube, m); | 354 | h48_prune_restore_normal(&prune[m], arg, target); |
| 248 | arg->inverse = premove(backup_inverse, m); | ||
| 249 | arg->lb_inverse = lbi; | ||
| 250 | arg->use_lb_normal = false; | ||
| 251 | arg->use_lb_inverse = ulbi && m % 3 == 1; | ||
| 252 | n = solve_h48_dfs(arg); | 355 | n = solve_h48_dfs(arg); |
| 253 | if (n < 0) | 356 | if (n < 0) |
| 254 | return n; | 357 | return n; |
| @@ -256,17 +359,14 @@ solve_h48_dfs(dfsarg_solve_h48_t arg[static 1]) | |||
| 256 | } | 359 | } |
| 257 | arg->solution_moves->nmoves--; | 360 | arg->solution_moves->nmoves--; |
| 258 | } else { | 361 | } else { |
| 362 | h48_prune_pipeline(arg, prune, target, false); | ||
| 259 | arg->solution_moves->npremoves++; | 363 | arg->solution_moves->npremoves++; |
| 260 | for (m = 0; m < 18; m++) { | 364 | for (m = 0; m < NMOVES; m++) { |
| 261 | if(!(mm_inverse & MM_SINGLE(m))) | 365 | if (prune[m].stop) |
| 262 | continue; | 366 | continue; |
| 263 | arg->solution_moves->premoves[ | 367 | arg->movemask_normal = mm_normal; |
| 264 | arg->solution_moves->npremoves-1] = m; | 368 | arg->movemask_inverse = mm_inverse; |
| 265 | arg->inverse = move(backup_inverse, m); | 369 | h48_prune_restore_inverse(&prune[m], arg, target); |
| 266 | arg->cube = premove(backup_cube, m); | ||
| 267 | arg->lb_normal = lbn; | ||
| 268 | arg->use_lb_inverse = false; | ||
| 269 | arg->use_lb_normal = ulbn && m % 3 == 1; | ||
| 270 | n = solve_h48_dfs(arg); | 370 | n = solve_h48_dfs(arg); |
| 271 | if (n < 0) | 371 | if (n < 0) |
| 272 | return n; | 372 | return n; |
| @@ -277,6 +377,8 @@ solve_h48_dfs(dfsarg_solve_h48_t arg[static 1]) | |||
| 277 | 377 | ||
| 278 | arg->cube = backup_cube; | 378 | arg->cube = backup_cube; |
| 279 | arg->inverse = backup_inverse; | 379 | arg->inverse = backup_inverse; |
| 380 | arg->movemask_normal = mm_normal; | ||
| 381 | arg->movemask_inverse = mm_inverse; | ||
| 280 | 382 | ||
| 281 | return ret; | 383 | return ret; |
| 282 | } | 384 | } |
| @@ -286,7 +388,7 @@ solve_h48_runthread(void *arg) | |||
| 286 | { | 388 | { |
| 287 | int i, j; | 389 | int i, j; |
| 288 | uint8_t lastmove; | 390 | uint8_t lastmove; |
| 289 | int64_t nprev; | 391 | int64_t d, f, nprev; |
| 290 | dfsarg_solve_h48_t *dfsarg; | 392 | dfsarg_solve_h48_t *dfsarg; |
| 291 | 393 | ||
| 292 | dfsarg = (dfsarg_solve_h48_t *)arg; | 394 | dfsarg = (dfsarg_solve_h48_t *)arg; |
| @@ -309,11 +411,15 @@ solve_h48_runthread(void *arg) | |||
| 309 | move(dfsarg->cube, dfsarg->tasks[i].moves[j]); | 411 | move(dfsarg->cube, dfsarg->tasks[i].moves[j]); |
| 310 | dfsarg->inverse = inverse(dfsarg->cube); | 412 | dfsarg->inverse = inverse(dfsarg->cube); |
| 311 | 413 | ||
| 414 | dfsarg->nodes_visited++; | ||
| 415 | if (dfsarg->tasks[i].pval + H48_STARTING_MOVES | ||
| 416 | > dfsarg->target_depth) | ||
| 417 | continue; | ||
| 418 | |||
| 312 | dfsarg->lb_normal = 0; | 419 | dfsarg->lb_normal = 0; |
| 313 | dfsarg->lb_inverse = 0; | 420 | dfsarg->lb_inverse = 0; |
| 314 | dfsarg->use_lb_normal = false; | 421 | dfsarg->movemask_normal = allowedmask[ |
| 315 | dfsarg->use_lb_inverse = false; | 422 | movebase(dfsarg->tasks[i].moves[H48_STARTING_MOVES-1])]; |
| 316 | dfsarg->movemask_normal = MM18_ALLMOVES; | ||
| 317 | dfsarg->movemask_inverse = MM18_ALLMOVES; | 423 | dfsarg->movemask_inverse = MM18_ALLMOVES; |
| 318 | dfsarg->tmask = dfsarg->tasks[i].tmask; | 424 | dfsarg->tmask = dfsarg->tasks[i].tmask; |
| 319 | 425 | ||
| @@ -331,8 +437,9 @@ solve_h48_runthread(void *arg) | |||
| 331 | inspired by Andrew Skalski's vcube. | 437 | inspired by Andrew Skalski's vcube. |
| 332 | */ | 438 | */ |
| 333 | lastmove = dfsarg->tasks[i].moves[H48_STARTING_MOVES-1]; | 439 | lastmove = dfsarg->tasks[i].moves[H48_STARTING_MOVES-1]; |
| 334 | dfsarg->tasks[i].rank = (dfsarg->nodes_visited - nprev) * | 440 | d = (int64_t)dfsarg->nodes_visited - nprev; |
| 335 | (movebase(lastmove) % 2 == 0 ? 47525 : 58206); | 441 | f = movebase(lastmove) % 2 == 0 ? 47525 : 58206; |
| 442 | dfsarg->tasks[i].rank = d * f; | ||
| 336 | nprev = dfsarg->nodes_visited; | 443 | nprev = dfsarg->nodes_visited; |
| 337 | } | 444 | } |
| 338 | 445 | ||
| @@ -374,6 +481,8 @@ solve_h48_maketasks( | |||
| 374 | 481 | ||
| 375 | if (mtarg->nmoves == H48_STARTING_MOVES) { | 482 | if (mtarg->nmoves == H48_STARTING_MOVES) { |
| 376 | tasks[*ntasks].cube = mtarg->cube; | 483 | tasks[*ntasks].cube = mtarg->cube; |
| 484 | tasks[*ntasks].pval = | ||
| 485 | h48_prune_lookup_nocoord(mtarg->cube, solve_arg); | ||
| 377 | memcpy(tasks[*ntasks].moves, mtarg->moves, | 486 | memcpy(tasks[*ntasks].moves, mtarg->moves, |
| 378 | H48_STARTING_MOVES * sizeof(uint8_t)); | 487 | H48_STARTING_MOVES * sizeof(uint8_t)); |
| 379 | memcpy(tasks[*ntasks].tmask, mtarg->tmask, | 488 | memcpy(tasks[*ntasks].tmask, mtarg->tmask, |
| @@ -393,7 +502,7 @@ solve_h48_maketasks( | |||
| 393 | 502 | ||
| 394 | mtarg->nmoves++; | 503 | mtarg->nmoves++; |
| 395 | backup_cube = mtarg->cube; | 504 | backup_cube = mtarg->cube; |
| 396 | for (m = 0; m < 18; m++) { | 505 | for (m = 0; m < NMOVES; m++) { |
| 397 | if (!(mm & MM_SINGLE(m))) | 506 | if (!(mm & MM_SINGLE(m))) |
| 398 | continue; | 507 | continue; |
| 399 | 508 | ||
| @@ -514,7 +623,7 @@ solve_h48( | |||
| 514 | .base = info.base, | 623 | .base = info.base, |
| 515 | .cocsepdata = cocsepdata, | 624 | .cocsepdata = cocsepdata, |
| 516 | .h48data = h48data, | 625 | .h48data = h48data, |
| 517 | .h48data_fallback_eoesep = eoesep, | 626 | .eoesepdata = eoesep, |
| 518 | .solution_moves = &solution_moves[i], | 627 | .solution_moves = &solution_moves[i], |
| 519 | .solution_settings = &settings, | 628 | .solution_settings = &settings, |
| 520 | .solution_list = &sollist, | 629 | .solution_list = &sollist, |
