aboutsummaryrefslogtreecommitdiff
path: root/src/solvers/h48/gendata.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/solvers/h48/gendata.h')
-rw-r--r--src/solvers/h48/gendata.h425
1 files changed, 425 insertions, 0 deletions
diff --git a/src/solvers/h48/gendata.h b/src/solvers/h48/gendata.h
new file mode 100644
index 0000000..d6bf85b
--- /dev/null
+++ b/src/solvers/h48/gendata.h
@@ -0,0 +1,425 @@
1#define COCSEP_CLASSES ((size_t)3393)
2#define COCSEP_TABLESIZE ((size_t)_3p7 << (size_t)7)
3#define COCSEP_VISITEDSIZE ((COCSEP_TABLESIZE + (size_t)7) / (size_t)8)
4#define COCSEP_FULLSIZE ((size_t)4 * (COCSEP_TABLESIZE + (size_t)12))
5
6#define ESEP_NOEO (COCSEP_CLASSES * (size_t)_12c4 * (size_t)_8c4)
7#define ESEP_MAX(h) (ESEP_NOEO << (size_t)(h))
8#define ESEP_TABLESIZE(h, k) (ESEP_MAX((h)) / ((size_t)8 / (size_t)(k)))
9
10#define ESEP_IND(i) ((uint32_t)(i) / UINT32_C(8))
11#define ESEP_SHIFT(i) (UINT32_C(4) * ((uint32_t)(i) % UINT32_C(8)))
12#define ESEP_MASK(i) ((_bit_u32(4) - (uint32_t)(1)) << ESEP_SHIFT(i))
13#define VISITED_IND(i) ((uint32_t)(i) / UINT32_C(8))
14#define VISITED_MASK(i) (UINT32_C(1) << ((uint32_t)(i) % UINT32_C(8)))
15
16#define CBOUND_MASK UINT32_C(0xFF)
17#define CBOUND(x) ((x) & CBOUND_MASK)
18
19#define MAXLEN 20
20
21/*
22TODO: This loop over similar h48 coordinates can be improved by only
23transforming edges, but we need to compose transformations (i.e. conjugate
24_t by _ttrep).
25*/
26#define _foreach_h48sim(_cube, _cocsepdata, _selfsim, _h, _action) \
27 int64_t _cocsep = coord_cocsep(_cube); \
28 uint8_t _ttrep = TTREP(_cocsepdata[_cocsep]); \
29 uint8_t _inverse_ttrep = inverse_trans(_ttrep); \
30 int64_t _coclass = COCLASS(_cocsepdata[_cocsep]); \
31 cube_t _rep = transform(_cube, _ttrep); \
32 uint64_t _sim = _selfsim[_coclass]; \
33 for (uint8_t _t = 0; _t < 48 && _sim; _t++, _sim >>= 1) { \
34 if (!(_sim & 1)) continue; \
35 _cube = transform(_rep, _t); \
36 _cube = transform(_cube, _inverse_ttrep); \
37 _action \
38 }
39
40typedef struct {
41 cube_t cube;
42 uint8_t depth;
43 uint8_t maxdepth;
44 uint16_t *n;
45 uint32_t *buf32;
46 uint8_t *visited;
47 uint64_t *selfsim;
48 cube_t *rep;
49} dfsarg_cocsep_t;
50
51/* TODO keep or not? */
52typedef struct {
53 cube_t cube;
54 int8_t nmoves;
55 int8_t depth;
56 uint8_t moves[MAXLEN];
57 uint32_t *cocsepdata;
58 h48map_t *visited;
59} dfsarg_genh48set_t;
60
61typedef struct {
62 uint8_t depth;
63 uint32_t *cocsepdata;
64 uint32_t *buf32;
65 uint64_t *selfsim;
66 int64_t done;
67 cube_t *crep;
68} bfsarg_esep_t;
69
70_static_inline bool get_visited(const uint8_t *, int64_t);
71_static_inline void set_visited(uint8_t *, int64_t);
72_static_inline uint8_t get_esep_pval(const uint32_t *, int64_t);
73_static_inline void set_esep_pval(uint32_t *, int64_t, uint8_t);
74
75_static size_t gendata_cocsep(void *, uint64_t *, cube_t *);
76_static uint32_t gendata_cocsep_dfs(dfsarg_cocsep_t *);
77_static uint64_t gen_h48short(
78 uint8_t, const uint32_t *, const cube_t *, const uint64_t *, h48map_t *);
79_static size_t gendata_h48h0k4(void *, uint8_t);
80_static int64_t gendata_h48h0k4_bfs(bfsarg_esep_t *);
81_static int64_t gendata_h48h0k4_bfs_fromdone(bfsarg_esep_t *);
82_static int64_t gendata_h48h0k4_bfs_fromnew(bfsarg_esep_t *);
83
84_static_inline int8_t get_h48_cdata(cube_t, uint32_t *, uint32_t *);
85_static_inline int8_t get_h48_bound(cube_t, uint32_t, uint8_t, uint32_t *);
86
87/*
88Each element of the cocsep table is a uint32_t used as follows:
89 - Lowest 8-bit block: pruning value
90 - Second-lowest 8-bit block: "ttrep" (transformation to representative)
91 - Top 16-bit block: symcoord value
92After the data as described above, more auxiliary information is appended:
93 - A uint32_t representing the number of symmetry classes
94 - A uint32_t representing the highest value of the pruning table
95 - One uint32_t for each "line" of the pruning table, representing the number
96 of positions having that pruning value.
97*/
98_static size_t
99gendata_cocsep(void *buf, uint64_t *selfsim, cube_t *rep)
100{
101 uint32_t *buf32, *info, cc;
102 uint16_t n;
103 uint8_t i, j, visited[COCSEP_VISITEDSIZE];
104 dfsarg_cocsep_t arg;
105
106 if (buf == NULL)
107 goto gendata_cocsep_return_size;
108
109 buf32 = (uint32_t *)buf;
110 info = buf32 + COCSEP_TABLESIZE;
111 memset(buf32, 0xFF, sizeof(uint32_t) * COCSEP_TABLESIZE);
112 if (selfsim != NULL)
113 memset(selfsim, 0, sizeof(uint64_t) * COCSEP_CLASSES);
114
115 arg = (dfsarg_cocsep_t) {
116 .cube = solved,
117 .n = &n,
118 .buf32 = buf32,
119 .visited = visited,
120 .selfsim = selfsim,
121 .rep = rep
122 };
123 for (i = 0, n = 0, cc = 0; i < 10; i++) {
124 LOG("cocsep: generating depth %" PRIu8 "\n", i);
125 memset(visited, 0, COCSEP_VISITEDSIZE);
126 arg.depth = 0;
127 arg.maxdepth = i;
128 cc = gendata_cocsep_dfs(&arg);
129 info[i+2] = cc;
130 LOG("found %" PRIu32 "\n", cc);
131 }
132
133 info[0] = (uint32_t)n;
134 info[1] = 9; /* Known max pruning value */
135 DBG_ASSERT(n == COCSEP_CLASSES, 0,
136 "cocsep: computed %" PRIu16 " symmetry classes, "
137 "expected %zu\n", n, COCSEP_CLASSES);
138
139 LOG("cocsep data computed\n");
140 LOG("Symmetry classes: %" PRIu32 "\n", info[0]);
141 LOG("Maximum pruning value: %" PRIu32 "\n", info[1]);
142 LOG("Pruning value distribution:\n");
143 for (j = 0; j < 10; j++)
144 LOG("%" PRIu8 ":\t%" PRIu32 "\n", j, info[j+2]);
145
146gendata_cocsep_return_size:
147 return COCSEP_FULLSIZE;
148}
149
150_static uint32_t
151gendata_cocsep_dfs(dfsarg_cocsep_t *arg)
152{
153 uint8_t m;
154 uint32_t cc, class, ttrep, depth, olddepth, tinv;
155 uint64_t t;
156 int64_t i, j;
157 cube_t d;
158 dfsarg_cocsep_t nextarg;
159
160 i = coord_cocsep(arg->cube);
161 olddepth = (uint8_t)(arg->buf32[i] & 0xFF);
162 if (olddepth < arg->depth || get_visited(arg->visited, i))
163 return 0;
164 set_visited(arg->visited, i);
165
166 if (arg->depth == arg->maxdepth) {
167 if ((arg->buf32[i] & 0xFF) != 0xFF)
168 return 0;
169
170 if (arg->rep != NULL)
171 arg->rep[*arg->n] = arg->cube;
172 for (t = 0, cc = 0; t < 48; t++) {
173 d = transform_corners(arg->cube, t);
174 j = coord_cocsep(d);
175 if (i == j && arg->selfsim != NULL)
176 arg->selfsim[*arg->n] |= UINT64_C(1) << t;
177 if (COCLASS(arg->buf32[j]) != UINT32_C(0xFFFF))
178 continue;
179 set_visited(arg->visited, j);
180 tinv = inverse_trans(t);
181 olddepth = arg->buf32[j] & 0xFF;
182 cc += olddepth == 0xFF;
183
184 class = (uint32_t)(*arg->n) << UINT32_C(16);
185 ttrep = (uint32_t)tinv << UINT32_C(8);
186 depth = (uint32_t)arg->depth;
187 arg->buf32[j] = class | ttrep | depth;
188 }
189 (*arg->n)++;
190
191 return cc;
192 }
193
194 memcpy(&nextarg, arg, sizeof(dfsarg_cocsep_t));
195 nextarg.depth++;
196 for (m = 0, cc = 0; m < 18; m++) {
197 nextarg.cube = move(arg->cube, m);
198 cc += gendata_cocsep_dfs(&nextarg);
199 }
200
201 return cc;
202}
203
204_static uint64_t
205gen_h48short(
206 uint8_t n,
207 const uint32_t *cocsepdata,
208 const cube_t *crep,
209 const uint64_t *selfsim,
210 h48map_t *map
211) {
212 uint8_t i, m;
213 int64_t coord;
214 uint64_t j, oldn;
215 kvpair_t kv;
216 cube_t cube, d;
217
218 cube = solvedcube();
219 coord = coord_h48(cube, cocsepdata, 11);
220 h48map_insertmin(map, coord, 0);
221 oldn = 0;
222 LOG("Short h48: generating depth 0\nfound %" PRIu8 "\n", map->n-oldn);
223 for (i = 0; i < n; i++) {
224 LOG("Short h48: generating depth %" PRIu8 "\n", i+1);
225 j = 0;
226 oldn = map->n;
227 for (kv = h48map_nextkvpair(map, &j);
228 j != map->capacity;
229 kv = h48map_nextkvpair(map, &j)
230 ) {
231 if (kv.val != i)
232 continue;
233 cube = invcoord_h48(kv.key, crep, 11);
234 for (m = 0; m < 18; m++) {
235 d = move(cube, m);
236 _foreach_h48sim(d, cocsepdata, selfsim, 11,
237 coord = coord_h48(d, cocsepdata, 11);
238 h48map_insertmin(map, coord, i+1);
239 )
240 }
241 }
242 LOG("found %" PRIu8 "\n", map->n-oldn);
243 }
244
245 return map->n;
246}
247
248/*
249TODO description
250generating fixed table with h=0, k=4
251*/
252_static size_t
253gendata_h48h0k4(void *buf, uint8_t maxdepth)
254{
255 uint32_t j, *buf32, *info, *cocsepdata;
256 bfsarg_esep_t arg;
257 int64_t sc, cc, esep_max;
258 uint64_t selfsim[COCSEP_CLASSES];
259 cube_t crep[COCSEP_CLASSES];
260 size_t cocsepsize, infosize;
261
262 /* TODO: move info at start of tables (all tables!) */
263 infosize = 4 * maxdepth;
264 cocsepsize = gendata_cocsep(buf, selfsim, crep);
265 infosize = 88;
266
267 if (buf == NULL)
268 goto gendata_h48h0k4_return_size;
269
270 esep_max = (int64_t)ESEP_MAX(0);
271 cocsepdata = (uint32_t *)buf;
272 buf32 = cocsepdata + cocsepsize / 4;
273 info = buf32 + (ESEP_TABLESIZE(0, 4) / sizeof(uint32_t));
274 memset(buf32, 0xFF, ESEP_TABLESIZE(0, 4));
275
276 sc = coord_h48(solved, cocsepdata, 0);
277 set_esep_pval(buf32, sc, 0);
278 info[1] = 1;
279 arg = (bfsarg_esep_t) {
280 .cocsepdata = cocsepdata,
281 .buf32 = buf32,
282 .selfsim = selfsim,
283 .crep = crep
284 };
285 for (
286 arg.done = 1, arg.depth = 1, cc = 0;
287 arg.done < esep_max && arg.depth <= maxdepth;
288 arg.depth++
289 ) {
290 LOG("esep: generating depth %" PRIu8 "\n", arg.depth);
291 cc = gendata_h48h0k4_bfs(&arg);
292 arg.done += cc;
293 info[arg.depth+1] = cc;
294 LOG("found %" PRId64 "\n", cc);
295 }
296
297 info[0] = arg.depth-1;
298
299 LOG("h48 pruning table computed\n");
300 LOG("Maximum pruning value: %" PRIu32 "\n", info[0]);
301 LOG("Pruning value distribution:\n");
302 for (j = 0; j <= info[0]; j++)
303 LOG("%" PRIu8 ":\t%" PRIu32 "\n", j, info[j+1]);
304
305gendata_h48h0k4_return_size:
306 return cocsepsize + ESEP_TABLESIZE(0, 4) + infosize;
307}
308
309_static int64_t
310gendata_h48h0k4_bfs(bfsarg_esep_t *arg)
311{
312 const uint8_t breakpoint = 10; /* Hand-picked optimal */
313
314 if (arg->depth < breakpoint)
315 return gendata_h48h0k4_bfs_fromdone(arg);
316 else
317 return gendata_h48h0k4_bfs_fromnew(arg);
318}
319
320_static int64_t
321gendata_h48h0k4_bfs_fromdone(bfsarg_esep_t *arg)
322{
323 uint8_t c, m, x;
324 uint32_t cc;
325 int64_t i, j, k;
326 cube_t cube, moved;
327
328 for (i = 0, cc = 0; i < (int64_t)ESEP_MAX(0); i++) {
329 c = get_esep_pval(arg->buf32, i);
330 if (c != arg->depth - 1)
331 continue;
332 cube = invcoord_h48(i, arg->crep, 0);
333 for (m = 0; m < 18; m++) {
334 moved = move(cube, m);
335 j = coord_h48(moved, arg->cocsepdata, 0);
336 if (get_esep_pval(arg->buf32, j) <= arg->depth)
337 continue;
338 _foreach_h48sim(moved, arg->cocsepdata, arg->selfsim, 0,
339 k = coord_h48(moved, arg->cocsepdata, 0);
340 x = get_esep_pval(arg->buf32, k);
341 set_esep_pval(arg->buf32, k, arg->depth);
342 cc += x != arg->depth;
343 )
344 }
345 }
346
347 return cc;
348}
349
350_static int64_t
351gendata_h48h0k4_bfs_fromnew(bfsarg_esep_t *arg)
352{
353 uint8_t c, m, x;
354 uint32_t cc;
355 int64_t i, j;
356 cube_t cube, moved;
357
358 for (i = 0, cc = 0; i < (int64_t)ESEP_MAX(0); i++) {
359 c = get_esep_pval(arg->buf32, i);
360 if (c != 0xF)
361 continue;
362 cube = invcoord_h48(i, arg->crep, 0);
363 for (m = 0; m < 18; m++) {
364 moved = move(cube, m);
365 j = coord_h48(moved, arg->cocsepdata, 0);
366 x = get_esep_pval(arg->buf32, j);
367 if (x >= arg->depth)
368 continue;
369 _foreach_h48sim(cube, arg->cocsepdata, arg->selfsim, 0,
370 j = coord_h48(cube, arg->cocsepdata, 0);
371 x = get_esep_pval(arg->buf32, j);
372 set_esep_pval(arg->buf32, j, arg->depth);
373 cc += x == 0xF;
374 )
375 break; /* Enough to find one, skip the rest */
376 }
377 }
378
379 return cc;
380}
381
382_static_inline bool
383get_visited(const uint8_t *a, int64_t i)
384{
385 return a[VISITED_IND(i)] & VISITED_MASK(i);
386}
387
388_static_inline void
389set_visited(uint8_t *a, int64_t i)
390{
391 a[VISITED_IND(i)] |= VISITED_MASK(i);
392}
393
394_static_inline uint8_t
395get_esep_pval(const uint32_t *buf32, int64_t i)
396{
397 return (buf32[ESEP_IND(i)] & ESEP_MASK(i)) >> ESEP_SHIFT(i);
398}
399
400_static_inline void
401set_esep_pval(uint32_t *buf32, int64_t i, uint8_t val)
402{
403 buf32[ESEP_IND(i)] =
404 (buf32[ESEP_IND(i)] & (~ESEP_MASK(i))) | (val << ESEP_SHIFT(i));
405}
406
407_static_inline int8_t
408get_h48_cdata(cube_t cube, uint32_t *cocsepdata, uint32_t *cdata)
409{
410 int64_t coord;
411
412 coord = coord_cocsep(cube);
413 *cdata = cocsepdata[coord];
414
415 return CBOUND(*cdata);
416}
417
418_static_inline int8_t
419get_h48_bound(cube_t cube, uint32_t cdata, uint8_t h, uint32_t *h48data)
420{
421 int64_t coord;
422
423 coord = coord_h48_edges(cube, COCLASS(cdata), TTREP(cdata), h);
424 return get_esep_pval(h48data, coord);
425}

Generated with cgit - Back to sebastiano.tronto.net