aboutsummaryrefslogtreecommitdiff
path: root/src/solvers/coord
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano@tronto.net>2025-03-24 23:09:26 +0100
committerSebastiano Tronto <sebastiano@tronto.net>2025-03-24 23:09:26 +0100
commitd45e1595ec1cffeab83ac6602b748250b66bea03 (patch)
tree44b35714cdae22026fc5e15648e91684a2fbb154 /src/solvers/coord
parentce3f1cc0ef9f46d70ab5387b1458e9098b40711d (diff)
downloadnissy-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')
-rw-r--r--src/solvers/coord/solve.h147
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 @@
1typedef struct { 1typedef 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
19STATIC int64_t solve_coord(cube_t, coord_t *, uint8_t, uint8_t, uint8_t, 12STATIC 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 *);
21STATIC int64_t solve_coord_dispatch(cube_t, const char *, uint8_t, uint8_t, 14STATIC 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 *);
23STATIC int64_t solve_coord_appendsolution(dfsarg_solve_coord_t *);
24STATIC int64_t solve_coord_dfs(dfsarg_solve_coord_t *); 16STATIC int64_t solve_coord_dfs(dfsarg_solve_coord_t *);
25 17
26STATIC int64_t 18STATIC int64_t
27solve_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
63solve_coord_appendsolution_error:
64 LOG("Could not append solution to buffer: size too small\n");
65 return NISSY_ERROR_BUFFER_SIZE;
66}
67
68STATIC int64_t
69solve_coord_dfs(dfsarg_solve_coord_t *arg) 19solve_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
241solve_coord_done: 199solve_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
247solve_coord_error_data: 202solve_coord_error_data:
248 LOG("solve_coord: error reading table\n"); 203 LOG("solve_coord: error reading table\n");

Generated with cgit - Back to sebastiano.tronto.net