aboutsummaryrefslogtreecommitdiff
path: root/src/solvers/coord/solve.h
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano@tronto.net>2025-03-25 14:09:14 +0100
committerSebastiano Tronto <sebastiano@tronto.net>2025-03-25 14:09:14 +0100
commit9154476ba6bf400c1eb379f0a3aa6caae2d06d4d (patch)
tree73bfb47ccb6cb31a7c91f9917b37a517f2146c24 /src/solvers/coord/solve.h
parentcc2dacd43eb7f5ed3a2917612b9a2a9232a61e59 (diff)
downloadnissy-core-9154476ba6bf400c1eb379f0a3aa6caae2d06d4d.tar.gz
nissy-core-9154476ba6bf400c1eb379f0a3aa6caae2d06d4d.zip
Added NISS to coord solver
Diffstat (limited to 'src/solvers/coord/solve.h')
-rw-r--r--src/solvers/coord/solve.h199
1 files changed, 167 insertions, 32 deletions
diff --git a/src/solvers/coord/solve.h b/src/solvers/coord/solve.h
index c056adc..c3fbd02 100644
--- a/src/solvers/coord/solve.h
+++ b/src/solvers/coord/solve.h
@@ -1,66 +1,191 @@
1typedef struct { 1typedef struct {
2 cube_t cube; 2 cube_t cube;
3 cube_t inverse;
3 uint8_t target_depth; 4 uint8_t target_depth;
4 solution_moves_t *solution_moves; 5 solution_moves_t *solution_moves;
5 solution_settings_t *solution_settings; 6 solution_settings_t *solution_settings;
7 solution_list_t *solution_list;
8 uint8_t nissflag;
9 bool lastisnormal;
6 coord_t *coord; 10 coord_t *coord;
7 const void *coord_data; 11 const void *coord_data;
8 const uint8_t *ptable; 12 const uint8_t *ptable;
9 solution_list_t *solution_list;
10} dfsarg_solve_coord_t; 13} dfsarg_solve_coord_t;
11 14
12STATIC int64_t solve_coord(cube_t, coord_t *, uint8_t, uint8_t, uint8_t, 15STATIC int64_t solve_coord(cube_t, coord_t [static 1], uint8_t, uint8_t,
13 uint8_t, uint64_t, int8_t, int, uint64_t, const void *, size_t, char *); 16 uint8_t, uint8_t, uint64_t, int8_t, int, uint64_t, const void *,
17 size_t n, char [n]);
14STATIC int64_t solve_coord_dispatch(cube_t, const char *, uint8_t, uint8_t, 18STATIC int64_t solve_coord_dispatch(cube_t, const char *, uint8_t, uint8_t,
15 uint8_t, uint64_t, int8_t, int, uint64_t, const void *, size_t, char *); 19 uint8_t, uint64_t, int8_t, int, uint64_t, const void *, size_t n, char [n]);
16STATIC int64_t solve_coord_dfs(dfsarg_solve_coord_t *); 20STATIC bool coord_solution_admissible(const dfsarg_solve_coord_t [static 1]);
21STATIC bool solve_coord_dfs_stop(const dfsarg_solve_coord_t [static 1]);
22STATIC bool coord_continue_onnormal(const dfsarg_solve_coord_t [static 1]);
23STATIC bool coord_continue_oninverse(const dfsarg_solve_coord_t [static 1]);
24STATIC int64_t solve_coord_dfs(dfsarg_solve_coord_t [static 1]);
25
26STATIC bool
27coord_solution_admissible(const dfsarg_solve_coord_t arg[static 1])
28{
29 uint8_t n;
30
31 n = arg->solution_moves->nmoves + arg->solution_moves->npremoves;
32 if (arg->target_depth != n)
33 return false;
34
35 return arg->coord->is_admissible == NULL ||
36 arg->coord->is_admissible(arg->solution_moves);
37}
38
39STATIC bool
40solve_coord_dfs_stop(const dfsarg_solve_coord_t arg[static 1])
41{
42 bool hasnissed;
43 uint8_t n, pval;
44 uint64_t coord;
45 const cube_t *c;
46
47 n = arg->solution_moves->nmoves + arg->solution_moves->npremoves;
48 if (n >= arg->target_depth)
49 return true;
50
51 hasnissed = arg->solution_moves->nmoves > 0 &&
52 arg->solution_moves->npremoves > 0;
53 if (!hasnissed && (arg->nissflag & NISSY_NISSFLAG_MIXED))
54 return false;
55
56 c = arg->lastisnormal ? &arg->cube : &arg->inverse;
57
58 coord = arg->coord->coord(*c, arg->coord_data);
59 pval = get_coord_pval(arg->coord, arg->ptable, coord);
60
61 return n + pval > arg->target_depth;
62}
63
64STATIC bool
65coord_continue_onnormal(const dfsarg_solve_coord_t arg[static 1])
66{
67 uint8_t f, nn, ni, th;
68
69 f = arg->nissflag;
70 nn = arg->solution_moves->nmoves;
71 ni = arg->solution_moves->npremoves;
72 th = DIV_ROUND_UP(arg->target_depth, 2);
73
74 if (nn + ni == 0)
75 return f & (NISSY_NISSFLAG_NORMAL | NISSY_NISSFLAG_MIXED);
76
77 if (arg->lastisnormal)
78 return (f & NISSY_NISSFLAG_NORMAL) ||
79 ((f & NISSY_NISSFLAG_MIXED) && (ni > 0 || nn <= th));
80
81 return (f & NISSY_NISSFLAG_MIXED) && nn == 0 && ni < th &&
82 coord_can_switch(arg->coord, arg->coord_data,
83 ni, arg->solution_moves->premoves);
84}
85
86STATIC bool
87coord_continue_oninverse(const dfsarg_solve_coord_t arg[static 1])
88{
89 uint8_t f, nn, ni, th;
90
91 f = arg->nissflag;
92 nn = arg->solution_moves->nmoves;
93 ni = arg->solution_moves->npremoves;
94 th = DIV_ROUND_UP(arg->target_depth, 2);
95
96 if (nn + ni == 0)
97 return f & (NISSY_NISSFLAG_INVERSE | NISSY_NISSFLAG_MIXED);
98
99 if (!arg->lastisnormal)
100 return (f & NISSY_NISSFLAG_INVERSE) ||
101 ((f & NISSY_NISSFLAG_MIXED) && (nn > 0 || ni < th));
102
103 return (f & NISSY_NISSFLAG_MIXED) && ni == 0 && nn <= th &&
104 coord_can_switch(arg->coord, arg->coord_data,
105 nn, arg->solution_moves->moves);
106}
17 107
18STATIC int64_t 108STATIC int64_t
19solve_coord_dfs(dfsarg_solve_coord_t *arg) 109solve_coord_dfs(dfsarg_solve_coord_t arg[static 1])
20{ 110{
21 uint8_t m, pval; 111 bool lastbackup;
112 uint8_t m, l, nnbackup, nibackup;
22 uint32_t mm; 113 uint32_t mm;
23 uint64_t coord; 114 uint64_t coord;
24 int64_t n, ret; 115 int64_t n, ret;
25 cube_t backup_cube; 116 cube_t backup_cube, backup_inverse;
26 117
27 coord = arg->coord->coord(arg->cube, arg->coord_data); 118 coord = arg->coord->coord(arg->cube, arg->coord_data);
28
29 if (coord == 0) { 119 if (coord == 0) {
30 if (arg->solution_moves->nmoves != arg->target_depth || 120 if (!coord_solution_admissible(arg))
31 (arg->coord->is_admissible != NULL &&
32 !arg->coord->is_admissible(arg->solution_moves->nmoves,
33 arg->solution_moves->moves)))
34 return 0; 121 return 0;
35 return appendsolution(arg->solution_moves, 122 return appendsolution(arg->solution_moves,
36 arg->solution_settings, arg->solution_list); 123 arg->solution_settings, arg->solution_list);
37 } 124 }
38 125
39 pval = get_coord_pval(arg->coord, arg->ptable, coord); 126 if (solve_coord_dfs_stop(arg))
40 if (arg->solution_moves->nmoves + pval > arg->target_depth)
41 return 0; 127 return 0;
42 128
43 backup_cube = arg->cube; 129 backup_cube = arg->cube;
130 backup_inverse = arg->inverse;
131 lastbackup = arg->lastisnormal;
132 nnbackup = arg->solution_moves->nmoves;
133 nibackup = arg->solution_moves->npremoves;
44 134
45 ret = 0; 135 ret = 0;
46 mm = allowednextmove_mask( 136 if (coord_continue_onnormal(arg)) {
47 arg->solution_moves->nmoves, arg->solution_moves->moves); 137 l = arg->solution_moves->nmoves;
48 arg->solution_moves->nmoves++; 138 mm = allowednextmove_mask(l, arg->solution_moves->moves);
49 for (m = 0; m < NMOVES; m++) { 139 arg->solution_moves->nmoves++;
50 if (!(mm & (1 << m))) 140 arg->lastisnormal = true;
51 continue;
52 141
53 arg->solution_moves->moves[arg->solution_moves->nmoves-1] = m; 142 for (m = 0; m < NMOVES; m++) {
54 arg->cube = move(backup_cube, m); 143 if (!(mm & (UINT32_C(1) << (uint32_t)m)))
55 n = solve_coord_dfs(arg); 144 continue;
56 if (n < 0) 145
57 return n; 146 arg->solution_moves->moves[l] = m;
58 ret += n; 147 arg->cube = move(backup_cube, m);
148 arg->inverse = premove(backup_inverse, m);
149 n = solve_coord_dfs(arg);
150 if (n < 0)
151 return n;
152 ret += n;
153 arg->solution_moves->npremoves = nibackup;
154 }
155
156 arg->solution_moves->nmoves--;
59 } 157 }
158
159 arg->lastisnormal = lastbackup;
160
161 if (coord_continue_oninverse(arg)) {
162 l = arg->solution_moves->npremoves;
163 mm = allowednextmove_mask(l, arg->solution_moves->premoves);
164 arg->solution_moves->npremoves++;
165 arg->lastisnormal = false;
166
167 for (m = 0; m < NMOVES; m++) {
168 if (!(mm & (UINT32_C(1) << (uint32_t)m)))
169 continue;
170
171 arg->solution_moves->premoves[l] = m;
172 arg->inverse = move(backup_inverse, m);
173 arg->cube = premove(backup_cube, m);
174 n = solve_coord_dfs(arg);
175 if (n < 0)
176 return n;
177 ret += n;
178 arg->solution_moves->nmoves = nnbackup;
179 }
180
181 arg->solution_moves->npremoves--;
182 }
183
60 arg->cube = backup_cube; 184 arg->cube = backup_cube;
61 arg->solution_moves->nmoves--; 185 arg->inverse = backup_inverse;
186 arg->lastisnormal = lastbackup;
62 187
63 return 0; 188 return ret;
64} 189}
65 190
66STATIC int64_t 191STATIC int64_t
@@ -76,7 +201,7 @@ solve_coord_dispatch(
76 uint64_t data_size, 201 uint64_t data_size,
77 const void *data, 202 const void *data,
78 size_t solutions_size, 203 size_t solutions_size,
79 char *sols 204 char sols[solutions_size]
80) 205)
81{ 206{
82 coord_t *coord; 207 coord_t *coord;
@@ -103,7 +228,7 @@ solve_coord_dispatch(
103STATIC int64_t 228STATIC int64_t
104solve_coord( 229solve_coord(
105 cube_t cube, 230 cube_t cube,
106 coord_t *coord, 231 coord_t coord [static 1],
107 uint8_t axis, 232 uint8_t axis,
108 uint8_t nissflag, 233 uint8_t nissflag,
109 uint8_t minmoves, 234 uint8_t minmoves,
@@ -114,7 +239,7 @@ solve_coord(
114 uint64_t data_size, 239 uint64_t data_size,
115 const void *data, 240 const void *data,
116 size_t solutions_size, 241 size_t solutions_size,
117 char *sols 242 char sols[solutions_size]
118) 243)
119{ 244{
120 int8_t d; 245 int8_t d;
@@ -160,12 +285,22 @@ solve_coord(
160 285
161 arg = (dfsarg_solve_coord_t) { 286 arg = (dfsarg_solve_coord_t) {
162 .cube = c, 287 .cube = c,
288 .inverse = inverse(c),
163 .coord = coord, 289 .coord = coord,
164 .coord_data = coord_data, 290 .coord_data = coord_data,
165 .ptable = ptable, 291 .ptable = ptable,
166 .solution_moves = &solution_moves, 292 .solution_moves = &solution_moves,
167 .solution_settings = &solution_settings, 293 .solution_settings = &solution_settings,
168 .solution_list = &solution_list, 294 .solution_list = &solution_list,
295 .nissflag = nissflag,
296
297 /*
298 Since no move has been done yet, this field should be
299 neither true nor false; using its value now is logically
300 undefined behavior.
301 TODO: find a more elegant solution
302 */
303 .lastisnormal = true,
169 }; 304 };
170 305
171 if (coord->coord(c, coord_data) == 0) { 306 if (coord->coord(c, coord_data) == 0) {

Generated with cgit - Back to sebastiano.tronto.net