nissy-core

The "engine" of nissy, including the H48 optimal solver.
git clone https://git.tronto.net/nissy-core
Download | Log | Files | Refs | README | LICENSE

commit 039267a278bb9e0580e8aebd85ef5f3ed774688f
parent d969dc0ad57d3e1e346df719cf9f2708ee87d2e7
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Wed, 23 Apr 2025 14:42:28 +0200

Adjusted solvers, fixed bug

Diffstat:
Msrc/core/constants.h | 8++++----
Msrc/core/moves.h | 7+++++++
Msrc/nissy.c | 12++----------
Msrc/nissy.h | 5+++--
Msrc/solvers/coord/solve.h | 17+++++++++--------
Msrc/solvers/h48/solve.h | 15++++++++-------
Msrc/solvers/solutions.h | 18+++++++++++++++++-
Msrc/solvers/solutions_types_macros.h | 1+
Atest/030_move/559_solved_xzy.in | 2++
Atest/030_move/559_solved_xzy.out | 1+
Atest/030_move/560_solved_RwS.in | 2++
Atest/030_move/560_solved_RwS.out | 1+
Atest/030_move/561_solved_RwSE3.in | 2++
Atest/030_move/561_solved_RwSE3.out | 1+
Atest/030_move/569_returns_to_noreorient.in | 2++
Atest/030_move/569_returns_to_noreorient.out | 1+
16 files changed, 63 insertions(+), 32 deletions(-)

diff --git a/src/core/constants.h b/src/core/constants.h @@ -696,17 +696,17 @@ STATIC uint8_t orientation_transition_table[][3] = { [ORIENTATION_RB] = { ORIENTATION_BL, ORIENTATION_RU, ORIENTATION_DB }, [ORIENTATION_RU] = { ORIENTATION_UL, ORIENTATION_RF, ORIENTATION_BU }, [ORIENTATION_LF] = { ORIENTATION_FR, ORIENTATION_LU, ORIENTATION_DF }, - [ORIENTATION_LD] = { ORIENTATION_DR, ORIENTATION_LB, ORIENTATION_BD }, + [ORIENTATION_LD] = { ORIENTATION_DR, ORIENTATION_LF, ORIENTATION_BD }, [ORIENTATION_LB] = { ORIENTATION_BR, ORIENTATION_LD, ORIENTATION_UB }, - [ORIENTATION_LU] = { ORIENTATION_UR, ORIENTATION_LF, ORIENTATION_FU }, + [ORIENTATION_LU] = { ORIENTATION_UR, ORIENTATION_LB, ORIENTATION_FU }, [ORIENTATION_FD] = { ORIENTATION_DB, ORIENTATION_FR, ORIENTATION_LD }, [ORIENTATION_FR] = { ORIENTATION_RB, ORIENTATION_FU, ORIENTATION_DR }, [ORIENTATION_FU] = { ORIENTATION_UB, ORIENTATION_FL, ORIENTATION_RU }, [ORIENTATION_FL] = { ORIENTATION_LB, ORIENTATION_FD, ORIENTATION_UL }, [ORIENTATION_BD] = { ORIENTATION_DF, ORIENTATION_BL, ORIENTATION_RD }, - [ORIENTATION_BR] = { ORIENTATION_RF, ORIENTATION_BU, ORIENTATION_UR }, + [ORIENTATION_BR] = { ORIENTATION_RF, ORIENTATION_BD, ORIENTATION_UR }, [ORIENTATION_BU] = { ORIENTATION_UF, ORIENTATION_BR, ORIENTATION_LU }, - [ORIENTATION_BL] = { ORIENTATION_LF, ORIENTATION_BD, ORIENTATION_DL }, + [ORIENTATION_BL] = { ORIENTATION_LF, ORIENTATION_BU, ORIENTATION_DL }, }; STATIC uint8_t orientation_trans[] = { diff --git a/src/core/moves.h b/src/core/moves.h @@ -16,6 +16,7 @@ STATIC_INLINE bool isbase(uint8_t); STATIC_INLINE bool parallel(uint8_t, uint8_t); STATIC_INLINE uint8_t moveopposite(uint8_t); STATIC_INLINE uint8_t reorient_move(uint8_t, uint8_t); +STATIC_INLINE uint8_t inverse_reorient_move(uint8_t, uint8_t); STATIC_INLINE uint8_t movefollow(uint8_t); STATIC uint8_t transform_move(uint8_t, uint8_t); @@ -223,6 +224,12 @@ reorient_move(uint8_t m, uint8_t or) return transform_move(m, orientation_trans[or]); } +STATIC_INLINE uint8_t +inverse_reorient_move(uint8_t m, uint8_t or) +{ + return transform_move(m, inverse_trans_table[orientation_trans[or]]); +} + /* This is currently unused, but it may turn out to be useful at some point */ STATIC_INLINE uint8_t movefollow(uint8_t move) diff --git a/src/nissy.c b/src/nissy.c @@ -461,7 +461,6 @@ nissy_solve( ) { oriented_cube_t oc; - cube_t c; long long parse_ret; uint8_t h, k; int t; @@ -472,7 +471,6 @@ nissy_solve( } oc = readcube(cube); - c = oc.cube; /* TODO: solve should handle oriented cubes */ @@ -481,12 +479,6 @@ nissy_solve( return NISSY_ERROR_INVALID_CUBE; } - if (!issolvable((oriented_cube_t){ .cube = c, .orientation = 0})) { -/* TODO: this is step-dependent */ - LOG("[solve] Error: cube is not solvable\n"); - return NISSY_ERROR_UNSOLVABLE_CUBE; - } - /* TODO: checks for minmoves, maxmoves, nissflag */ if (maxsols == 0) { @@ -509,10 +501,10 @@ nissy_solve( parse_ret = parse_h48_solver(solver, &h, &k); if (parse_ret != NISSY_OK) return parse_ret; - return solve_h48(c, minmoves, maxmoves, maxsols, + return solve_h48(oc, minmoves, maxmoves, maxsols, optimal, t, data_size, data, sols_size, sols, stats); } else if (!strncmp(solver, "coord_", 6)) { - return solve_coord_dispatch(c, solver + 6, nissflag, + return solve_coord_dispatch(oc, solver + 6, nissflag, minmoves, maxmoves, maxsols, optimal, t, data_size, data, sols_size, sols); } else { diff --git a/src/nissy.h b/src/nissy.h @@ -8,8 +8,9 @@ below for the list of error codes and their meaning. Cubes are passed as strings in the cccccccc=eeeeeeeeeeee=r format, see the README.md file for more information. -Accepted moves are U, D, R, L, F and B, optionally followed by a 2, -a ' or a 3. +Accepted moves are any of the following: +U, D, R, L, F, B, Uw, Dw, Rw, Lw, Fw, Bw, M, S, E, x, y, z +optionally followed by a 2, a ' or a 3. A transformation must be given in the format (rotation|mirrored) (2 letters) diff --git a/src/solvers/coord/solve.h b/src/solvers/coord/solve.h @@ -12,12 +12,12 @@ typedef struct { const unsigned char *ptable; } dfsarg_solve_coord_t; -STATIC int64_t solve_coord(cube_t, coord_t [static 1], uint8_t, uint8_t, +STATIC int64_t solve_coord(oriented_cube_t, coord_t [static 1], uint8_t, + uint8_t, uint8_t, uint8_t, uint64_t, uint8_t, uint8_t, uint64_t, + const unsigned char *, size_t n, char [n]); +STATIC int64_t solve_coord_dispatch(oriented_cube_t, const char *, uint8_t, uint8_t, uint8_t, uint64_t, uint8_t, uint8_t, uint64_t, const unsigned char *, size_t n, char [n]); -STATIC int64_t solve_coord_dispatch(cube_t, const char *, uint8_t, uint8_t, - uint8_t, uint64_t, uint8_t, uint8_t, uint64_t, const unsigned char *, - size_t n, char [n]); STATIC bool coord_solution_admissible(const dfsarg_solve_coord_t [static 1]); STATIC bool solve_coord_dfs_stop(const dfsarg_solve_coord_t [static 1]); STATIC bool coord_continue_onnormal(const dfsarg_solve_coord_t [static 1]); @@ -200,7 +200,7 @@ solve_coord_dfs(dfsarg_solve_coord_t arg[static 1]) STATIC int64_t solve_coord_dispatch( - cube_t cube, + oriented_cube_t oc, const char *coord_and_axis, uint8_t nissflag, uint8_t minmoves, @@ -231,14 +231,14 @@ solve_coord_dispatch( return NISSY_ERROR_INVALID_SOLVER; } - return solve_coord(cube, coord, axis, nissflag, minmoves, maxmoves, + return solve_coord(oc, coord, axis, nissflag, minmoves, maxmoves, maxsolutions, optimal, threads, data_size, data, solutions_size, sols); } STATIC int64_t solve_coord( - cube_t cube, + oriented_cube_t oc, coord_t coord [static 1], uint8_t axis, uint8_t nissflag, @@ -266,7 +266,7 @@ solve_coord( solution_list_t solution_list; t = coord->axistrans[axis]; - c = transform(cube, t); + c = transform(oc.cube, t); if (!coord->is_solvable(c)) goto solve_coord_error_unsolvable; @@ -295,6 +295,7 @@ solve_coord( .maxmoves = maxmoves, .maxsolutions = maxsolutions, .optimal = optimal, + .orientation = oc.orientation, }; arg = (dfsarg_solve_coord_t) { diff --git a/src/solvers/h48/solve.h b/src/solvers/h48/solve.h @@ -52,8 +52,8 @@ STATIC int64_t solve_h48_maketasks( solve_h48_task_t [static STARTING_CUBES], int [static 1]); STATIC void *solve_h48_runthread(void *); STATIC int64_t solve_h48_dfs(dfsarg_solve_h48_t [static 1]); -STATIC int64_t solve_h48(cube_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, - uint64_t, const unsigned char *, size_t n, char [n], +STATIC int64_t solve_h48(oriented_cube_t, uint8_t, uint8_t, uint8_t, uint8_t, + uint8_t, uint64_t, const unsigned char *, size_t n, char [n], long long [static NISSY_SIZE_SOLVE_STATS]); STATIC_INLINE bool @@ -342,7 +342,7 @@ solve_h48_maketasks( STATIC int64_t solve_h48( - cube_t cube, + oriented_cube_t oc, uint8_t minmoves, uint8_t maxmoves, uint8_t maxsolutions, @@ -407,17 +407,18 @@ solve_h48( fallback2 = h48data + offset; settings = (solution_settings_t) { - .tmask = symmetry_mask(cube), + .tmask = symmetry_mask(oc.cube), .unniss = true, .maxmoves = maxmoves, .maxsolutions = maxsolutions, .optimal = optimal, + .orientation = oc.orientation, }; for (i = 0; i < threads; i++) { arg[i] = (dfsarg_solve_h48_t) { - .start_cube = cube, - .cube = cube, + .start_cube = oc.cube, + .cube = oc.cube, .h = info.h48h, .k = info.bits, .base = info.base, @@ -441,7 +442,7 @@ solve_h48( pthread_mutex_init(&solutions_mutex, NULL); maketasks_arg = (dfsarg_solve_h48_maketasks_t) { - .cube = cube, + .cube = oc.cube, .nmoves = 0, .minmoves = minmoves, .maxmoves = maxmoves, diff --git a/src/solvers/solutions.h b/src/solvers/solutions.h @@ -1,5 +1,6 @@ STATIC void solution_moves_reset(solution_moves_t [static 1]); -STATIC void solution_moves_transform(solution_moves_t [static 1], uint8_t t); +STATIC void solution_moves_transform(solution_moves_t [static 1], uint8_t); +STATIC void solution_moves_reorient(solution_moves_t [static 1], uint8_t); STATIC bool solution_list_init( solution_list_t [static 1], size_t n, char [n]); STATIC bool solution_moves_equal( @@ -35,6 +36,20 @@ solution_moves_transform(solution_moves_t moves[static 1], uint8_t t) moves->premoves[i] = transform_move(moves->premoves[i], t); } +STATIC void +solution_moves_reorient(solution_moves_t moves[static 1], uint8_t or) +{ + uint8_t i; + + for (i = 0; i < moves->nmoves; i++) + moves->moves[i] = + inverse_reorient_move(moves->moves[i], or); + + for (i = 0; i < moves->npremoves; i++) + moves->premoves[i] = + inverse_reorient_move(moves->premoves[i], or); +} + STATIC bool solution_list_init(solution_list_t sols[static 1], size_t n, char buf[n]) { @@ -187,6 +202,7 @@ appendsolution( continue; } solution_moves_transform(&tsol[r], t); + solution_moves_reorient(&tsol[r], settings->orientation); sortparallel_moves(tsol[r].nmoves, tsol[r].moves); sortparallel_moves(tsol[r].npremoves, tsol[r].premoves); diff --git a/src/solvers/solutions_types_macros.h b/src/solvers/solutions_types_macros.h @@ -13,6 +13,7 @@ typedef struct { uint8_t maxmoves; uint64_t maxsolutions; uint8_t optimal; + uint8_t orientation; } solution_settings_t; typedef struct { diff --git a/test/030_move/559_solved_xzy.in b/test/030_move/559_solved_xzy.in @@ -0,0 +1,2 @@ +x z y +ABCDEFGH=ABCDEFGHIJKL=A diff --git a/test/030_move/559_solved_xzy.out b/test/030_move/559_solved_xzy.out @@ -0,0 +1 @@ +ABCDEFGH=ABCDEFGHIJKL=M diff --git a/test/030_move/560_solved_RwS.in b/test/030_move/560_solved_RwS.in @@ -0,0 +1,2 @@ +Rw S +ABCDEFGH=ABCDEFGHIJKL=A diff --git a/test/030_move/560_solved_RwS.out b/test/030_move/560_solved_RwS.out @@ -0,0 +1 @@ +FJGKAXDU=EKJHBADCIFGL=N diff --git a/test/030_move/561_solved_RwSE3.in b/test/030_move/561_solved_RwSE3.in @@ -0,0 +1,2 @@ +Rw S E' +ABCDEFGH=ABCDEFGHIJKL=A diff --git a/test/030_move/561_solved_RwSE3.out b/test/030_move/561_solved_RwSE3.out @@ -0,0 +1 @@ +TQMPONSR=EKJHIFGLCDAB=M diff --git a/test/030_move/569_returns_to_noreorient.in b/test/030_move/569_returns_to_noreorient.in @@ -0,0 +1,2 @@ +Rw S L2 D E' Bw +ABCDEFGH=ABCDEFGHIJKL=A diff --git a/test/030_move/569_returns_to_noreorient.out b/test/030_move/569_returns_to_noreorient.out @@ -0,0 +1 @@ +WQEFHDBS=TJKWCFLBUXAI=A