aboutsummaryrefslogtreecommitdiff
path: root/src/solve_h48.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/solve_h48.h')
-rw-r--r--src/solve_h48.h266
1 files changed, 266 insertions, 0 deletions
diff --git a/src/solve_h48.h b/src/solve_h48.h
new file mode 100644
index 0000000..84bea31
--- /dev/null
+++ b/src/solve_h48.h
@@ -0,0 +1,266 @@
1#define _esep_ind(i) (i / 8U)
2#define _esep_shift(i) (4U * (i % 8U))
3#define _esep_mask(i) (((1U << 4U) - 1U) << _esep_shift(i))
4#define _visited_ind(i) (i / 8U)
5#define _visited_mask(i) (1U << (i % 8U))
6
7typedef struct {
8 cube_fast_t cube;
9 uint8_t *visited;
10 uint8_t *moves;
11 uint8_t nmoves;
12 uint8_t depth;
13 uint16_t *nclasses;
14 uint32_t *cocsepdata;
15 uint32_t *buf32;
16} dfsarg_gendata_t;
17
18_static_inline int64_t coord_h48(cube_fast_t, uint32_t *, uint8_t);
19
20_static size_t gendata_cocsep(void *);
21_static uint32_t gendata_cocsep_dfs( /* TODO: use dfsarg */
22 cube_fast_t, uint8_t, uint8_t, uint16_t *, uint32_t *, uint8_t *);
23
24_static size_t gendata_esep(const void *, void *);
25_static uint32_t gendata_esep_dfs(dfsarg_gendata_t *);
26
27_static_inline bool get_visited(const uint8_t *, int64_t);
28_static_inline void set_visited(uint8_t *, int64_t);
29_static_inline uint8_t get_esep_pval(const uint32_t *, int64_t);
30_static_inline void set_esep_pval(uint32_t *, int64_t, uint8_t);
31
32/* h is the number of eo bits used */
33_static_inline int64_t
34coord_h48(cube_fast_t c, uint32_t *cocsepdata, uint8_t h)
35{
36 cube_fast_t d;
37 int64_t cocsep, coclass, esep, eo, esize, ret;
38 uint32_t data;
39 uint8_t ttrep;
40
41 DBG_ASSERT(h <= 11, -1, "coord_h48: h must be between 0 and 11\n");
42
43 cocsep = coord_fast_cocsep(c);
44 data = cocsepdata[cocsep];
45 coclass = (data & (0xFFFFU << 16U)) >> 16U;
46 ttrep = (data & (0xFFU << 8U)) >> 8U;
47
48 d = transform(c, ttrep); /* TODO: transform only edges */
49 esep = coord_fast_esep(d);
50 eo = coord_fast_eo(d);
51
52 esize = (_12c4 * _8c4) << h;
53 ret = (coclass * esize) + (esep << h) + (eo >> (11-h));
54
55 return ret;
56}
57
58/*
59Each element of the cocsep table is a uint32_t used as follows:
60 - Lowest 8-bit block: pruning value
61 - Second-lower 8-bit block: "ttrep" (transformation to representative)
62 - Top 16-bit block: symcoord value
63After the data as described above, more auxiliary information is appended:
64 - A uint32_t representing the number of symmetry classes
65 - A uint32_t representing the highest value of the pruning table
66 - One uint32_t for each "line" of the pruning table, representing the number
67 of positions having that pruning value.
68*/
69_static size_t
70gendata_cocsep(void *buf)
71{
72 size_t tablesize = _3p7 << 7U;
73 size_t visitedsize = (tablesize + 7U) / 8U;
74 size_t infosize = 12;
75
76 cube_fast_t solved;
77 uint32_t *buf32, *info, cc;
78 uint16_t n;
79 uint8_t i, j, visited[visitedsize];
80
81 buf32 = (uint32_t *)buf;
82 info = buf32 + tablesize;
83 memset(buf32, 0xFFU, 4*tablesize);
84 memset(info, 0, 4*infosize);
85
86 solved = cubetofast(solvedcube());
87 for (i = 0, n = 0, cc = 0; i < 10; i++) {
88 memset(visited, 0, visitedsize);
89 DBG_LOG("cocsep: generating depth %" PRIu8 "\n", i);
90 cc = gendata_cocsep_dfs(solved, 0, i, &n, buf32, visited);
91 info[i+2] = cc;
92 DBG_LOG("found %" PRIu32 "\n", cc);
93 }
94
95 info[0] = (uint32_t)n;
96 info[1] = 9U; /* Known max pruning value */
97 DBG_ASSERT(n == COCSEP_CLASSES, 0,
98 "cocsep: computed %" PRIu16 " symmetry classes, "
99 "expected %" PRIu16 "\n", n, COCSEP_CLASSES);
100
101 DBG_LOG("cocsep data computed\n");
102 DBG_LOG("Symmetry classes: %" PRIu32 "\n", info[0]);
103 DBG_LOG("Maximum pruning value: %" PRIu32 "\n", info[1]);
104 DBG_LOG("Pruning value distribution:\n");
105 for (j = 0; j < 10; j++)
106 DBG_LOG("%" PRIu8 ":\t%" PRIu32 "\n", j, info[j+2]);
107
108 return 4*(tablesize + infosize);
109}
110
111_static uint32_t
112gendata_cocsep_dfs(
113 cube_fast_t c,
114 uint8_t depth,
115 uint8_t maxdepth,
116 uint16_t *n,
117 uint32_t *buf32,
118 uint8_t *visited
119)
120{
121 uint8_t m, t, tinv, olddepth;
122 uint32_t cc;
123 int64_t i;
124 cube_fast_t d;
125
126 i = coord_fast_cocsep(c);
127 olddepth = (uint8_t)(buf32[i] & 0xFFU);
128 if (olddepth < depth || get_visited(visited, i))
129 return 0;
130 set_visited(visited, i);
131
132 if (depth == maxdepth) {
133 if ((buf32[i] & 0xFFU) != 0xFFU)
134 return 0;
135
136 for (t = 0, cc = 0; t < 48; t++) {
137 d = transform(c, t);
138 i = coord_fast_cocsep(d);
139 set_visited(visited, i);
140 tinv = inverse_trans(t);
141 cc += (buf32[i] & 0xFFU) == 0xFFU;
142 buf32[i] = (*n << 16U) | (tinv << 8U) | depth;
143 }
144 (*n)++;
145
146 return cc;
147 }
148
149 for (m = 0, cc = 0; m < 18; m++) {
150 d = move(c, m);
151 cc += gendata_cocsep_dfs(d, depth+1, maxdepth, n, buf32, visited);
152 }
153
154 return cc;
155}
156
157/*
158TODO description
159generating fixed table with h=0, k=4
160*/
161_static size_t
162gendata_esep(const void *cocsepdata, void *buf)
163{
164 size_t tablesize = (COCSEP_CLASSES * _12c4 * _8c4) / 2U;
165 size_t visitedsize = (tablesize * 2U + 7U) / 8U;
166 size_t infosize = 25; /* TODO unknown yet */
167
168 uint32_t *buf32, *info, cc;
169 uint8_t moves[20];
170 dfsarg_gendata_t arg;
171
172 arg.visited = malloc(visitedsize);
173 buf32 = (uint32_t *)buf;
174 info = buf32 + tablesize;
175 memset(buf32, 0xFFU, 4*tablesize);
176 memset(info, 0, 4*infosize);
177
178 arg.cube = cubetofast(solvedcube());
179 arg.moves = moves;
180 arg.nmoves = 0;
181 arg.cocsepdata = (uint32_t *)cocsepdata;
182 arg.buf32 = buf32;
183 /* TODO loop until no more is done, not until 12! (or hardcode limits)*/
184 for (arg.depth = 0, cc = 0; arg.depth < 12; arg.depth++) {
185 DBG_LOG("esep: generating depth %" PRIu8 "\n", arg.depth);
186 memset(arg.visited, 0, visitedsize);
187 cc = gendata_esep_dfs(&arg);
188 info[arg.depth+1] = cc;
189 DBG_LOG("found %" PRIu32 "\n", cc);
190 }
191 free(arg.visited);
192
193 return cc;
194}
195
196_static uint32_t
197gendata_esep_dfs(dfsarg_gendata_t *arg)
198{
199 uint8_t m, t, olddepth;
200 uint32_t cc;
201 uint64_t i;
202 cube_fast_t d;
203 dfsarg_gendata_t nextarg;
204
205 if (!allowednextmove(arg->moves, arg->nmoves))
206 return 0;
207
208 if (arg->nmoves > 0)
209 arg->cube = move(arg->cube, arg->moves[arg->nmoves-1]);
210
211 i = coord_h48(arg->cube, arg->cocsepdata, 0U);
212 olddepth = get_esep_pval(arg->buf32, i);
213
214 if (olddepth < arg->nmoves || get_visited(arg->visited, i))
215 return 0;
216 set_visited(arg->visited, i);
217
218 if (arg->nmoves == arg->depth) {
219 if (olddepth != 15U)
220 return 0;
221
222 for (t = 0, cc = 0; t < 48; t++) {
223 d = transform(arg->cube, t);
224 i = coord_h48(d, arg->cocsepdata, 0U);
225 set_visited(arg->visited, i);
226 cc += get_esep_pval(arg->buf32, i) == 15U;
227 set_esep_pval(arg->buf32, i, arg->depth);
228 }
229
230 return cc;
231 }
232
233
234 nextarg = *arg;
235 nextarg.nmoves = arg->nmoves + 1;
236 for (m = 0, cc = 0; m < 18; m++) {
237 nextarg.cube = arg->cube;
238 nextarg.moves[arg->nmoves] = m;
239 cc += gendata_esep_dfs(&nextarg);
240 }
241
242 return cc;
243}
244
245_static_inline bool get_visited(const uint8_t *a, int64_t i)
246{
247 return a[_visited_ind(i)] & _visited_mask(i);
248}
249
250_static_inline void set_visited(uint8_t *a, int64_t i)
251{
252 a[_visited_ind(i)] |= _visited_mask(i);
253}
254
255_static_inline uint8_t
256get_esep_pval(const uint32_t *buf32, int64_t i)
257{
258 return (buf32[_esep_ind(i)] & _esep_mask(i)) >> _esep_shift(i);
259}
260
261_static_inline void
262set_esep_pval(uint32_t *buf32, int64_t i, uint8_t val)
263{
264 buf32[_esep_ind(i)] =
265 (buf32[_esep_ind(i)] & (~_esep_mask(i))) | (val << _esep_shift(i));
266}

Generated with cgit - Back to sebastiano.tronto.net