aboutsummaryrefslogtreecommitdiff
path: root/old/2021-02-18-piecefilter/src/solve.c
diff options
context:
space:
mode:
Diffstat (limited to 'old/2021-02-18-piecefilter/src/solve.c')
-rw-r--r--old/2021-02-18-piecefilter/src/solve.c179
1 files changed, 179 insertions, 0 deletions
diff --git a/old/2021-02-18-piecefilter/src/solve.c b/old/2021-02-18-piecefilter/src/solve.c
new file mode 100644
index 0000000..ac19d6f
--- /dev/null
+++ b/old/2021-02-18-piecefilter/src/solve.c
@@ -0,0 +1,179 @@
1#include "solve.h"
2
3/* Data for creating a pruning table:
4 - compressed: if set to true, each entry occupies only 4 bits, but values
5 larger than 15 cannot be stored.
6 - available[] is the list of availabel moves, as above.
7 - *ptable is the actual table to fill.
8 - n is the number of states (size of ptable).
9 - index must "linearize" the cube, i.e. return its index in ptable.
10 - fname is the name of the file where to store the table */
11typedef struct {
12 bool compressed, *available;
13 int max_moves;
14 uint8_t *ptable;
15 uint64_t n;
16 uint64_t (*index)(Cube);
17 char *fname;
18} PruneData;
19
20/* TODO: comment this */
21typedef struct {
22 bool niss;
23 int m, d;
24 uint64_t *n;
25 Move last1, last2;
26} DfsData;
27
28void solve_dfs(Cube cube, SolveData *sd, DfsData dd);
29void init_ptable(PruneData *pd, bool read, bool write);
30
31/* Search solutions of lenght exactly d */
32void solve_dfs(Cube cube, SolveData *sd, DfsData dd) {
33 if (*dd.n >= sd->max_solutions ||
34 ((!sd->can_niss || dd.niss) && dd.m + sd->f(cube) > dd.d))
35 return;
36
37 (sd->solutions[*dd.n][dd.m]).inverse = dd.niss;
38 (sd->solutions[*dd.n][dd.m]).m = NULLMOVE;
39
40 if (!sd->f(cube)) { /* Solved */
41 if (dd.m == dd.d) {
42 (*dd.n)++;
43 if (*dd.n < sd->max_solutions)
44 copy_alg(sd->solutions[*dd.n-1], sd->solutions[*dd.n]);
45 }
46 return;
47 }
48
49 for (int i = 0; i < NMOVES && sd->sorted_moves[i] != NULLMOVE; i++) {
50 Move move = sd->sorted_moves[i];
51 if (possible_next[dd.last2][dd.last1][move]) {
52 sd->solutions[*dd.n][dd.m].inverse = dd.niss;
53 sd->solutions[*dd.n][dd.m].m = move;
54 DfsData nn = { .niss = dd.niss, .m = dd.m+1, .d = dd.d, .n = dd.n,
55 .last1 = move, .last2 = dd.last1 };
56 solve_dfs(move_cube(move, cube), sd, nn);
57 }
58 }
59
60 if (sd->can_niss && !dd.niss &&
61 (!dd.m || (dd.m && sd->f(move_cube(dd.last1, blank_cube()))))) {
62 DfsData nn = { .niss = true, .m = dd.m, .d = dd.d, .n = dd.n };
63 solve_dfs(inverse_cube(cube), sd, nn);
64 }
65}
66
67/* Iterative deepening depth-first search: for i running from the minimum
68 to the maximum number of moves allowed, looks for solutions of length i. */
69int solve(Cube cube, SolveData *sd) {
70 if (sd->precondition != NULL && !sd->precondition(cube))
71 return -1;
72
73 /* If not given, generate sorted list of moves */
74 if (sd->sorted_moves[0] == NULLMOVE) {
75 int a[NMOVES], b[NMOVES], ia = 0, ib = 0;
76 for (int i = 0; i < NMOVES; i++) {
77 if (sd->available[i]) {
78 if (sd->f(move_cube(i, blank_cube())))
79 a[ia++] = i;
80 else
81 b[ib++] = i;
82 }
83 }
84 intarrcopy(a, (int *)sd->sorted_moves, ia);
85 intarrcopy(b, (int *)sd->sorted_moves+ia, ib);
86 sd->sorted_moves[ia+ib] = NULLMOVE;
87 }
88
89 sd->max_solutions = min(sd->max_solutions, MAXS);
90 /*TODO
91 Cube rotated = apply_alg(sd->pre_rotation, blank_cube());
92 cube = apply_alg(inverse_cube(rotated), compose(cube, rotated));
93 */
94
95 uint64_t ret = 0;
96 for (int i=sd->min_moves; i<=sd->max_moves&&!(ret&&sd->optimal_only); i++) {
97 DfsData dd = { .d = i, .n = &ret };
98 solve_dfs(cube, sd, dd);
99 }
100
101 for (uint64_t i = 0; i < ret; i++) {
102 /* TODO: transform solutions with inverse of pre_rotation */
103 if (sd->cleanup)
104 cleanup(sd->solutions[i], sd->max_moves*3);
105 }
106
107 return ret;
108}
109
110void prune_dfs(Cube cube, PruneData *pd, DfsData dd) {
111 uint64_t ind = pd->index(cube);
112 if ((!ind || pd->ptable[ind]) && pd->ptable[ind] != dd.m)
113 return;
114 if (dd.m == dd.d) {
115 if (ind && !pd->ptable[ind]) {
116 pd->ptable[ind] = dd.m;
117 (*dd.n)++;
118 }
119 return;
120 }
121
122 for (int i = 0; i < NMOVES; i++) {
123 if (dd.m<20)
124 if (possible_next[dd.last2][dd.last1][i] && pd->available[i]) {
125 DfsData nn = { .m = dd.m+1, .d = dd.d, .n = dd.n,
126 .last1 = i, .last2 = dd.last1 };
127 prune_dfs(move_cube(i, cube), pd, nn);
128 }
129 }
130}
131
132void init_ptable(PruneData *pd, bool read, bool write) {
133 if (read) {
134 FILE *ptf;
135 if ((ptf = fopen(pd->fname, "rb")) != NULL) {
136 fread(pd->ptable, sizeof(uint8_t), pd->n, ptf);
137 fclose(ptf);
138 return;
139 }
140 }
141
142 /* TODO: for now it behaves always as if copressed = false */
143 for (uint64_t i = 0; i < pd->n; i++)
144 pd->ptable[i] = 0;
145
146 uint64_t s = 1;
147 for (int i = 1; i < pd->max_moves && s < pd->n; i++) {
148 DfsData dd = { .d = i, .n = &s };
149 prune_dfs(blank_cube(), pd, dd);
150 }
151
152 if (write) {
153 FILE *ptf;
154 if ((ptf = fopen(pd->fname, "wb")) != NULL) {
155 fwrite(pd->ptable, sizeof(uint8_t), pd->n, ptf);
156 fclose(ptf);
157 return;
158 }
159 }
160}
161
162/* Solving steps (and indexing functions) */
163
164uint64_t index_eofb(Cube cube) { return cube.eofb; }
165uint16_t f_eofb(Cube cube) {
166 static bool initialized_ptable;
167 static uint8_t pt_eofb[pow2to11];
168 if (!initialized_ptable) {
169 PruneData pd = {
170 .compressed = false, .available = standard_moveset, .max_moves = 13,
171 .ptable = pt_eofb, .n = pow2to11, .index = index_eofb,
172 .fname = "ptable_eofb"
173 };
174 init_ptable(&pd, false, true);
175 initialized_ptable = true;
176 }
177 return cube.eofb ? pt_eofb[cube.eofb] : 0;
178}
179

Generated with cgit - Back to sebastiano.tronto.net