diff options
| author | Sebastiano Tronto <sebastiano@tronto.net> | 2025-03-24 23:09:26 +0100 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano@tronto.net> | 2025-03-24 23:09:26 +0100 |
| commit | d45e1595ec1cffeab83ac6602b748250b66bea03 (patch) | |
| tree | 44b35714cdae22026fc5e15648e91684a2fbb154 /src/solvers/coord/solve.h | |
| parent | ce3f1cc0ef9f46d70ab5387b1458e9098b40711d (diff) | |
| download | nissy-core-d45e1595ec1cffeab83ac6602b748250b66bea03.tar.gz nissy-core-d45e1595ec1cffeab83ac6602b748250b66bea03.zip | |
Big cleanup for appendsolution()
With this PR the appendsolution routine is extracted from the h48
solver and the new coordinate solver and made generic. This has
many advantages:
- less repetition (even if the two versions are different enough that
*for now* it was not a big deal)
- smaller h48/solve.h file, which is already a big beast
- easier to test the appendsolution() routine separately
Diffstat (limited to 'src/solvers/coord/solve.h')
| -rw-r--r-- | src/solvers/coord/solve.h | 147 |
1 files changed, 51 insertions, 96 deletions
diff --git a/src/solvers/coord/solve.h b/src/solvers/coord/solve.h index fa160f8..c056adc 100644 --- a/src/solvers/coord/solve.h +++ b/src/solvers/coord/solve.h | |||
| @@ -1,71 +1,21 @@ | |||
| 1 | typedef struct { | 1 | typedef struct { |
| 2 | cube_t cube; | 2 | cube_t cube; |
| 3 | uint8_t depth; | 3 | uint8_t target_depth; |
| 4 | uint8_t nmoves; | 4 | solution_moves_t *solution_moves; |
| 5 | uint8_t moves[MAXLEN]; | 5 | solution_settings_t *solution_settings; |
| 6 | coord_t *coord; | 6 | coord_t *coord; |
| 7 | const void *coord_data; | 7 | const void *coord_data; |
| 8 | const uint8_t *ptable; | 8 | const uint8_t *ptable; |
| 9 | uint8_t trans; | 9 | solution_list_t *solution_list; |
| 10 | int64_t *nsols; | ||
| 11 | int64_t maxsolutions; | ||
| 12 | int optimal; | ||
| 13 | uint8_t *shortest_sol; | ||
| 14 | size_t solutions_size; | ||
| 15 | size_t *solutions_used; | ||
| 16 | char **solutions; | ||
| 17 | } dfsarg_solve_coord_t; | 10 | } dfsarg_solve_coord_t; |
| 18 | 11 | ||
| 19 | STATIC int64_t solve_coord(cube_t, coord_t *, uint8_t, uint8_t, uint8_t, | 12 | STATIC int64_t solve_coord(cube_t, coord_t *, uint8_t, uint8_t, uint8_t, |
| 20 | uint8_t, uint64_t, int, int, uint64_t, const void *, size_t, char *); | 13 | uint8_t, uint64_t, int8_t, int, uint64_t, const void *, size_t, char *); |
| 21 | STATIC int64_t solve_coord_dispatch(cube_t, const char *, uint8_t, uint8_t, | 14 | STATIC int64_t solve_coord_dispatch(cube_t, const char *, uint8_t, uint8_t, |
| 22 | uint8_t, uint64_t, int, int, uint64_t, const void *, size_t, char *); | 15 | uint8_t, uint64_t, int8_t, int, uint64_t, const void *, size_t, char *); |
| 23 | STATIC int64_t solve_coord_appendsolution(dfsarg_solve_coord_t *); | ||
| 24 | STATIC int64_t solve_coord_dfs(dfsarg_solve_coord_t *); | 16 | STATIC int64_t solve_coord_dfs(dfsarg_solve_coord_t *); |
| 25 | 17 | ||
| 26 | STATIC int64_t | 18 | STATIC int64_t |
| 27 | solve_coord_appendsolution(dfsarg_solve_coord_t *arg) | ||
| 28 | { | ||
| 29 | uint8_t i, t, tmoves[MAXLEN]; | ||
| 30 | int64_t strl; | ||
| 31 | uint64_t l; | ||
| 32 | char *m; | ||
| 33 | |||
| 34 | if (*arg->nsols >= arg->maxsolutions || | ||
| 35 | arg->nmoves > *arg->shortest_sol + arg->optimal || | ||
| 36 | (arg->coord->is_admissible != NULL && | ||
| 37 | !arg->coord->is_admissible(arg->nmoves, arg->moves))) | ||
| 38 | return 0; | ||
| 39 | |||
| 40 | t = inverse_trans(arg->trans); | ||
| 41 | for (i = 0; i < arg->nmoves; i++) | ||
| 42 | tmoves[i] = transform_move(arg->moves[i], t); | ||
| 43 | |||
| 44 | sortparallel(arg->nmoves, tmoves); | ||
| 45 | |||
| 46 | l = arg->solutions_size - *arg->solutions_used; | ||
| 47 | m = *arg->solutions + *arg->solutions_used; | ||
| 48 | strl = writemoves(arg->nmoves, tmoves, l, m); | ||
| 49 | if (strl < 0) | ||
| 50 | goto solve_coord_appendsolution_error; | ||
| 51 | |||
| 52 | *arg->solutions_used += MAX(0, strl-1); | ||
| 53 | |||
| 54 | if (!appendchar( | ||
| 55 | arg->solutions_size, *arg->solutions, arg->solutions_used, '\n')) | ||
| 56 | goto solve_coord_appendsolution_error; | ||
| 57 | |||
| 58 | (*arg->nsols)++; | ||
| 59 | *arg->shortest_sol = MIN(*arg->shortest_sol, arg->nmoves); | ||
| 60 | |||
| 61 | return 1; | ||
| 62 | |||
| 63 | solve_coord_appendsolution_error: | ||
| 64 | LOG("Could not append solution to buffer: size too small\n"); | ||
| 65 | return NISSY_ERROR_BUFFER_SIZE; | ||
| 66 | } | ||
| 67 | |||
| 68 | STATIC int64_t | ||
| 69 | solve_coord_dfs(dfsarg_solve_coord_t *arg) | 19 | solve_coord_dfs(dfsarg_solve_coord_t *arg) |
| 70 | { | 20 | { |
| 71 | uint8_t m, pval; | 21 | uint8_t m, pval; |
| @@ -77,25 +27,30 @@ solve_coord_dfs(dfsarg_solve_coord_t *arg) | |||
| 77 | coord = arg->coord->coord(arg->cube, arg->coord_data); | 27 | coord = arg->coord->coord(arg->cube, arg->coord_data); |
| 78 | 28 | ||
| 79 | if (coord == 0) { | 29 | if (coord == 0) { |
| 80 | if (arg->nmoves != arg->depth) | 30 | if (arg->solution_moves->nmoves != arg->target_depth || |
| 31 | (arg->coord->is_admissible != NULL && | ||
| 32 | !arg->coord->is_admissible(arg->solution_moves->nmoves, | ||
| 33 | arg->solution_moves->moves))) | ||
| 81 | return 0; | 34 | return 0; |
| 82 | return solve_coord_appendsolution(arg); | 35 | return appendsolution(arg->solution_moves, |
| 36 | arg->solution_settings, arg->solution_list); | ||
| 83 | } | 37 | } |
| 84 | 38 | ||
| 85 | pval = get_coord_pval(arg->coord, arg->ptable, coord); | 39 | pval = get_coord_pval(arg->coord, arg->ptable, coord); |
| 86 | if (arg->nmoves + pval > arg->depth) | 40 | if (arg->solution_moves->nmoves + pval > arg->target_depth) |
| 87 | return 0; | 41 | return 0; |
| 88 | 42 | ||
| 89 | backup_cube = arg->cube; | 43 | backup_cube = arg->cube; |
| 90 | 44 | ||
| 91 | ret = 0; | 45 | ret = 0; |
| 92 | mm = allowednextmove_mask(arg->nmoves, arg->moves); | 46 | mm = allowednextmove_mask( |
| 93 | arg->nmoves++; | 47 | arg->solution_moves->nmoves, arg->solution_moves->moves); |
| 94 | for (m = 0; m < 18; m++) { | 48 | arg->solution_moves->nmoves++; |
| 49 | for (m = 0; m < NMOVES; m++) { | ||
| 95 | if (!(mm & (1 << m))) | 50 | if (!(mm & (1 << m))) |
| 96 | continue; | 51 | continue; |
| 97 | 52 | ||
| 98 | arg->moves[arg->nmoves-1] = m; | 53 | arg->solution_moves->moves[arg->solution_moves->nmoves-1] = m; |
| 99 | arg->cube = move(backup_cube, m); | 54 | arg->cube = move(backup_cube, m); |
| 100 | n = solve_coord_dfs(arg); | 55 | n = solve_coord_dfs(arg); |
| 101 | if (n < 0) | 56 | if (n < 0) |
| @@ -103,7 +58,7 @@ solve_coord_dfs(dfsarg_solve_coord_t *arg) | |||
| 103 | ret += n; | 58 | ret += n; |
| 104 | } | 59 | } |
| 105 | arg->cube = backup_cube; | 60 | arg->cube = backup_cube; |
| 106 | arg->nmoves--; | 61 | arg->solution_moves->nmoves--; |
| 107 | 62 | ||
| 108 | return 0; | 63 | return 0; |
| 109 | } | 64 | } |
| @@ -116,7 +71,7 @@ solve_coord_dispatch( | |||
| 116 | uint8_t minmoves, | 71 | uint8_t minmoves, |
| 117 | uint8_t maxmoves, | 72 | uint8_t maxmoves, |
| 118 | uint64_t maxsolutions, | 73 | uint64_t maxsolutions, |
| 119 | int optimal, | 74 | int8_t optimal, |
| 120 | int threads, | 75 | int threads, |
| 121 | uint64_t data_size, | 76 | uint64_t data_size, |
| 122 | const void *data, | 77 | const void *data, |
| @@ -154,7 +109,7 @@ solve_coord( | |||
| 154 | uint8_t minmoves, | 109 | uint8_t minmoves, |
| 155 | uint8_t maxmoves, | 110 | uint8_t maxmoves, |
| 156 | uint64_t maxsolutions, | 111 | uint64_t maxsolutions, |
| 157 | int optimal, | 112 | int8_t optimal, |
| 158 | int threads, | 113 | int threads, |
| 159 | uint64_t data_size, | 114 | uint64_t data_size, |
| 160 | const void *data, | 115 | const void *data, |
| @@ -163,14 +118,19 @@ solve_coord( | |||
| 163 | ) | 118 | ) |
| 164 | { | 119 | { |
| 165 | int8_t d; | 120 | int8_t d; |
| 166 | uint8_t t, shortest_sol; | 121 | uint8_t t; |
| 167 | int64_t nsols, ndepth; | 122 | int64_t ndepth; |
| 168 | size_t solutions_used; | ||
| 169 | cube_t c; | 123 | cube_t c; |
| 170 | const void *coord_data; | 124 | const void *coord_data; |
| 171 | const uint8_t *ptable; | 125 | const uint8_t *ptable; |
| 172 | dfsarg_solve_coord_t arg; | 126 | dfsarg_solve_coord_t arg; |
| 173 | tableinfo_t info; | 127 | tableinfo_t info; |
| 128 | solution_moves_t solution_moves; | ||
| 129 | solution_settings_t solution_settings; | ||
| 130 | solution_list_t solution_list; | ||
| 131 | |||
| 132 | if (!solution_list_init(&solution_list, solutions_size, sols)) | ||
| 133 | goto solve_coord_error_buffer; | ||
| 174 | 134 | ||
| 175 | if (readtableinfo(data_size, data, &info) != NISSY_OK) | 135 | if (readtableinfo(data_size, data, &info) != NISSY_OK) |
| 176 | goto solve_coord_error_data; | 136 | goto solve_coord_error_data; |
| @@ -185,64 +145,59 @@ solve_coord( | |||
| 185 | ptable = (uint8_t *)data + info.next + INFOSIZE; | 145 | ptable = (uint8_t *)data + info.next + INFOSIZE; |
| 186 | } | 146 | } |
| 187 | 147 | ||
| 188 | nsols = 0; | ||
| 189 | solutions_used = 0; | ||
| 190 | shortest_sol = MAXLEN + 1; | ||
| 191 | t = coord->axistrans[axis]; | 148 | t = coord->axistrans[axis]; |
| 192 | c = transform(cube, t); | 149 | c = transform(cube, t); |
| 193 | 150 | ||
| 151 | solution_moves_reset(&solution_moves); | ||
| 152 | |||
| 153 | solution_settings = (solution_settings_t) { | ||
| 154 | .tmask = TM_SINGLE(inverse_trans(t)), | ||
| 155 | .unniss = false, | ||
| 156 | .maxmoves = maxmoves, | ||
| 157 | .maxsolutions = maxsolutions, | ||
| 158 | .optimal = optimal, | ||
| 159 | }; | ||
| 160 | |||
| 194 | arg = (dfsarg_solve_coord_t) { | 161 | arg = (dfsarg_solve_coord_t) { |
| 195 | .cube = c, | 162 | .cube = c, |
| 196 | .coord = coord, | 163 | .coord = coord, |
| 197 | .coord_data = coord_data, | 164 | .coord_data = coord_data, |
| 198 | .ptable = ptable, | 165 | .ptable = ptable, |
| 199 | .trans = t, | 166 | .solution_moves = &solution_moves, |
| 200 | .nsols = &nsols, | 167 | .solution_settings = &solution_settings, |
| 201 | .maxsolutions = (int64_t)maxsolutions, | 168 | .solution_list = &solution_list, |
| 202 | .optimal = optimal, | ||
| 203 | .shortest_sol = &shortest_sol, | ||
| 204 | .solutions_size = solutions_size, | ||
| 205 | .solutions_used = &solutions_used, | ||
| 206 | .solutions = &sols, | ||
| 207 | }; | 169 | }; |
| 208 | 170 | ||
| 209 | if (coord->coord(c, coord_data) == 0) { | 171 | if (coord->coord(c, coord_data) == 0) { |
| 210 | if (minmoves == 0) { | 172 | if (minmoves == 0 && !appendsolution( |
| 211 | nsols = 1; | 173 | &solution_moves, &solution_settings, &solution_list)) |
| 212 | if (!appendchar(solutions_size, sols, &solutions_used, '\n')) | ||
| 213 | goto solve_coord_error_buffer; | 174 | goto solve_coord_error_buffer; |
| 214 | } | ||
| 215 | goto solve_coord_done; | 175 | goto solve_coord_done; |
| 216 | } | 176 | } |
| 217 | 177 | ||
| 218 | for ( | 178 | for ( |
| 219 | d = MAX(minmoves, 1); | 179 | d = MAX(minmoves, 1); |
| 220 | d <= maxmoves && nsols < (int64_t)maxsolutions | 180 | !solutions_done(&solution_list, &solution_settings, d); |
| 221 | && !(nsols != 0 && d > shortest_sol + optimal); | ||
| 222 | d++ | 181 | d++ |
| 223 | ) { | 182 | ) { |
| 224 | if (d >= 10) | 183 | if (d >= 10) |
| 225 | LOG("Found %" PRId64 " solutions, searching at depth %" | 184 | LOG("Found %" PRIu64 " solutions, searching at depth %" |
| 226 | PRId8 "\n", nsols, d); | 185 | PRId8 "\n", solution_list.nsols, d); |
| 227 | 186 | ||
| 228 | arg.depth = d; | 187 | arg.target_depth = d; |
| 229 | arg.nmoves = 0; | 188 | solution_moves_reset(arg.solution_moves); |
| 230 | ndepth = solve_coord_dfs(&arg); | 189 | ndepth = solve_coord_dfs(&arg); |
| 231 | 190 | ||
| 232 | /* TODO: improve error handling? */ | ||
| 233 | if (ndepth < 0) { | 191 | if (ndepth < 0) { |
| 234 | LOG("Error %" PRId64 "\n", ndepth); | 192 | LOG("Error %" PRId64 "\n", ndepth); |
| 235 | return ndepth; | 193 | return ndepth; |
| 236 | } | 194 | } |
| 237 | 195 | ||
| 238 | nsols += ndepth; | 196 | solution_list.nsols += (uint64_t)ndepth; |
| 239 | } | 197 | } |
| 240 | 198 | ||
| 241 | solve_coord_done: | 199 | solve_coord_done: |
| 242 | if (!appendchar(solutions_size, sols, &solutions_used, '\0')) | 200 | return (int64_t)solution_list.nsols; |
| 243 | goto solve_coord_error_buffer; | ||
| 244 | |||
| 245 | return nsols; | ||
| 246 | 201 | ||
| 247 | solve_coord_error_data: | 202 | solve_coord_error_data: |
| 248 | LOG("solve_coord: error reading table\n"); | 203 | LOG("solve_coord: error reading table\n"); |
