aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/solvers/h48/solve.h245
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
61typedef 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
71typedef 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
61STATIC long long solve_h48_dispatch(oriented_cube_t, const char *, unsigned, 83STATIC 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 *);
65STATIC_INLINE bool solve_h48_stop(dfsarg_solve_h48_t [static 1]); 87STATIC_INLINE bool solve_h48_stop(dfsarg_solve_h48_t [static 1]);
88STATIC_INLINE solve_h48_prune_return_t solve_h48_prune(solve_h48_prune_arg_t);
66STATIC int64_t solve_h48_maketasks( 89STATIC 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
214STATIC_INLINE solve_h48_prune_return_t
215solve_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
274solve_h48_prune_return_false:
275 ret.stop = false;
276 return ret;
277
278solve_h48_prune_return_true:
279 ret.stop = true;
280 return ret;
281}
282
283#if 1
284
285STATIC int64_t
286solve_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
194STATIC int64_t 415STATIC int64_t
195solve_h48_dfs(dfsarg_solve_h48_t arg[static 1]) 416solve_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
284STATIC void * 508STATIC void *
285solve_h48_runthread(void *arg) 509solve_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

Generated with cgit - Back to sebastiano.tronto.net