diff options
| author | Sebastiano Tronto <sebastiano@tronto.net> | 2024-08-25 14:36:11 +0200 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano@tronto.net> | 2024-08-25 15:40:08 +0200 |
| commit | 25c16cc4350a659ede2a2503c4c5be36264e853d (patch) | |
| tree | 97af17c9497817959909e0a17bc1286c7c0feccd /src/solvers/h48/gendata_h48.h | |
| parent | cdf311166da0171c2787fb1745072cd14569ff4f (diff) | |
| download | nissy-core-25c16cc4350a659ede2a2503c4c5be36264e853d.tar.gz nissy-core-25c16cc4350a659ede2a2503c4c5be36264e853d.zip | |
Renamed file
Diffstat (limited to 'src/solvers/h48/gendata_h48.h')
| -rw-r--r-- | src/solvers/h48/gendata_h48.h | 351 |
1 files changed, 351 insertions, 0 deletions
diff --git a/src/solvers/h48/gendata_h48.h b/src/solvers/h48/gendata_h48.h new file mode 100644 index 0000000..2b1347f --- /dev/null +++ b/src/solvers/h48/gendata_h48.h | |||
| @@ -0,0 +1,351 @@ | |||
| 1 | #define H48_COORDMAX_NOEO (COCSEP_CLASSES * (size_t)_12c4 * (size_t)_8c4) | ||
| 2 | #define H48_COORDMAX(h) (H48_COORDMAX_NOEO << (size_t)(h)) | ||
| 3 | #define H48_TABLESIZE(h, k) (H48_COORDMAX((h)) / ((size_t)8 / (size_t)(k))) | ||
| 4 | |||
| 5 | #define H48_COEFF(k) (UINT32_C(32) / (uint32_t)(k)) | ||
| 6 | #define H48_INDEX(i, k) ((uint32_t)(i) / H48_COEFF(k)) | ||
| 7 | #define H48_SHIFT(i, k) ((uint32_t)(k) * ((uint32_t)(i) % H48_COEFF(k))) | ||
| 8 | #define H48_MASK(i, k) ((_bit_u32(k) - (uint32_t)(1)) << H48_SHIFT(i, k)) | ||
| 9 | |||
| 10 | #define MAXLEN 20 | ||
| 11 | |||
| 12 | /* | ||
| 13 | TODO: This loop over similar h48 coordinates can be improved by only | ||
| 14 | transforming edges, but we need to compose transformations (i.e. conjugate | ||
| 15 | _t by _ttrep). | ||
| 16 | */ | ||
| 17 | #define _foreach_h48sim(_cube, _cocsepdata, _selfsim, _h, _action) \ | ||
| 18 | int64_t _cocsep = coord_cocsep(_cube); \ | ||
| 19 | uint8_t _ttrep = TTREP(_cocsepdata[_cocsep]); \ | ||
| 20 | uint8_t _inverse_ttrep = inverse_trans(_ttrep); \ | ||
| 21 | int64_t _coclass = COCLASS(_cocsepdata[_cocsep]); \ | ||
| 22 | cube_t _rep = transform(_cube, _ttrep); \ | ||
| 23 | uint64_t _sim = _selfsim[_coclass]; \ | ||
| 24 | for (uint8_t _t = 0; _t < 48 && _sim; _t++, _sim >>= 1) { \ | ||
| 25 | if (!(_sim & 1)) continue; \ | ||
| 26 | _cube = transform(_rep, _t); \ | ||
| 27 | _cube = transform(_cube, _inverse_ttrep); \ | ||
| 28 | _action \ | ||
| 29 | } | ||
| 30 | |||
| 31 | typedef struct { | ||
| 32 | uint8_t h; | ||
| 33 | uint8_t k; | ||
| 34 | uint8_t maxdepth; | ||
| 35 | void *buf; | ||
| 36 | uint32_t *info; | ||
| 37 | uint32_t *cocsepdata; | ||
| 38 | uint32_t *h48data; | ||
| 39 | uint64_t selfsim[COCSEP_CLASSES]; | ||
| 40 | cube_t crep[COCSEP_CLASSES]; | ||
| 41 | } gendata_h48_arg_t; | ||
| 42 | |||
| 43 | typedef struct { | ||
| 44 | uint8_t maxdepth; | ||
| 45 | const uint32_t *cocsepdata; | ||
| 46 | const cube_t *crep; | ||
| 47 | const uint64_t *selfsim; | ||
| 48 | h48map_t *map; | ||
| 49 | } gendata_h48short_arg_t; | ||
| 50 | |||
| 51 | typedef struct { | ||
| 52 | uint8_t depth; | ||
| 53 | uint32_t *cocsepdata; | ||
| 54 | uint32_t *buf32; | ||
| 55 | uint64_t *selfsim; | ||
| 56 | int64_t done; | ||
| 57 | cube_t *crep; | ||
| 58 | } bfsarg_esep_t; | ||
| 59 | |||
| 60 | _static_inline uint8_t get_esep_pval(const uint32_t *, int64_t, uint8_t); | ||
| 61 | _static_inline void set_esep_pval(uint32_t *, int64_t, uint8_t, uint8_t); | ||
| 62 | |||
| 63 | _static uint64_t gen_h48short(gendata_h48short_arg_t *); | ||
| 64 | _static size_t gendata_h48(gendata_h48_arg_t *); | ||
| 65 | _static size_t gendata_h48h0k4(gendata_h48_arg_t *); | ||
| 66 | _static int64_t gendata_h48h0k4_bfs(bfsarg_esep_t *); | ||
| 67 | _static int64_t gendata_h48h0k4_bfs_fromdone(bfsarg_esep_t *); | ||
| 68 | _static int64_t gendata_h48h0k4_bfs_fromnew(bfsarg_esep_t *); | ||
| 69 | _static size_t gendata_h48k2(gendata_h48_arg_t *); | ||
| 70 | |||
| 71 | _static_inline int8_t get_h48_bound(cube_t, uint32_t, uint8_t, uint8_t, uint32_t *); | ||
| 72 | |||
| 73 | _static uint64_t | ||
| 74 | gen_h48short(gendata_h48short_arg_t *arg) | ||
| 75 | { | ||
| 76 | uint8_t i, m; | ||
| 77 | int64_t coord; | ||
| 78 | uint64_t j, oldn; | ||
| 79 | kvpair_t kv; | ||
| 80 | cube_t cube, d; | ||
| 81 | |||
| 82 | cube = solvedcube(); | ||
| 83 | coord = coord_h48(cube, arg->cocsepdata, 11); | ||
| 84 | h48map_insertmin(arg->map, coord, 0); | ||
| 85 | oldn = 0; | ||
| 86 | LOG("Short h48: depth 0\nfound %" PRIu8 "\n", arg->map->n-oldn); | ||
| 87 | for (i = 0; i < arg->maxdepth; i++) { | ||
| 88 | LOG("Short h48: depth %" PRIu8 "\n", i+1); | ||
| 89 | j = 0; | ||
| 90 | oldn = arg->map->n; | ||
| 91 | for (kv = h48map_nextkvpair(arg->map, &j); | ||
| 92 | j != arg->map->capacity; | ||
| 93 | kv = h48map_nextkvpair(arg->map, &j) | ||
| 94 | ) { | ||
| 95 | if (kv.val != i) | ||
| 96 | continue; | ||
| 97 | cube = invcoord_h48(kv.key, arg->crep, 11); | ||
| 98 | for (m = 0; m < 18; m++) { | ||
| 99 | d = move(cube, m); | ||
| 100 | _foreach_h48sim( | ||
| 101 | d, arg->cocsepdata, arg->selfsim, 11, | ||
| 102 | coord = coord_h48(d, arg->cocsepdata, 11); | ||
| 103 | h48map_insertmin(arg->map, coord, i+1); | ||
| 104 | ) | ||
| 105 | } | ||
| 106 | } | ||
| 107 | LOG("found %" PRIu8 "\n", arg->map->n-oldn); | ||
| 108 | } | ||
| 109 | |||
| 110 | return arg->map->n; | ||
| 111 | } | ||
| 112 | |||
| 113 | /* Generic function that dispatches to the data generators */ | ||
| 114 | _static size_t | ||
| 115 | gendata_h48(gendata_h48_arg_t *arg) | ||
| 116 | { | ||
| 117 | static const size_t infosize = 88; /* TODO: change to e.g. 1024 */ | ||
| 118 | |||
| 119 | size_t cocsepsize, h48size; | ||
| 120 | |||
| 121 | /* TODO: move info at the start */ | ||
| 122 | arg->cocsepdata = (uint32_t *)arg->buf; | ||
| 123 | cocsepsize = gendata_cocsep( | ||
| 124 | (void *)arg->cocsepdata, arg->selfsim, arg->crep); | ||
| 125 | arg->h48data = arg->cocsepdata + (cocsepsize / sizeof(uint32_t)); | ||
| 126 | arg->info = arg->h48data + | ||
| 127 | (H48_TABLESIZE(arg->h, arg->k) / sizeof(uint32_t)); | ||
| 128 | |||
| 129 | if (arg->buf != NULL) | ||
| 130 | memset(arg->h48data, 0xFF, H48_TABLESIZE(arg->h, arg->k)); | ||
| 131 | |||
| 132 | if (arg->h == 0 && arg->k == 4) { | ||
| 133 | h48size = gendata_h48h0k4(arg); | ||
| 134 | } else if (arg->k == 2) { | ||
| 135 | h48size = gendata_h48k2(arg); | ||
| 136 | } else { | ||
| 137 | h48size = 0; | ||
| 138 | LOG("Cannot generate data for h = %" PRIu8 " and k = %" PRIu8 | ||
| 139 | " (not implemented yet)\n", arg->h, arg->k); | ||
| 140 | } | ||
| 141 | |||
| 142 | return infosize + cocsepsize + h48size; | ||
| 143 | } | ||
| 144 | |||
| 145 | /* | ||
| 146 | TODO description | ||
| 147 | generating fixed table with h=0, k=4 | ||
| 148 | */ | ||
| 149 | _static size_t | ||
| 150 | gendata_h48h0k4(gendata_h48_arg_t *arg) | ||
| 151 | { | ||
| 152 | uint32_t j; | ||
| 153 | bfsarg_esep_t bfsarg; | ||
| 154 | int64_t sc, cc, esep_max; | ||
| 155 | /* | ||
| 156 | uint64_t selfsim[COCSEP_CLASSES]; | ||
| 157 | cube_t crep[COCSEP_CLASSES]; | ||
| 158 | size_t cocsepsize, infosize; | ||
| 159 | */ | ||
| 160 | |||
| 161 | if (arg->buf == NULL) | ||
| 162 | goto gendata_h48h0k4_return_size; | ||
| 163 | /* | ||
| 164 | cocsepsize = gendata_cocsep(buf, selfsim, crep); | ||
| 165 | infosize = 88; | ||
| 166 | |||
| 167 | cocsepdata = (uint32_t *)buf; | ||
| 168 | buf32 = cocsepdata + cocsepsize / 4; | ||
| 169 | info = buf32 + (H48_TABLESIZE(0, 4) / sizeof(uint32_t)); | ||
| 170 | memset(buf32, 0xFF, H48_TABLESIZE(0, 4)); | ||
| 171 | */ | ||
| 172 | |||
| 173 | esep_max = (int64_t)H48_COORDMAX(0); | ||
| 174 | sc = coord_h48(solved, arg->cocsepdata, 0); | ||
| 175 | set_esep_pval(arg->h48data, sc, 4, 0); | ||
| 176 | arg->info[1] = 1; | ||
| 177 | bfsarg = (bfsarg_esep_t) { | ||
| 178 | .cocsepdata = arg->cocsepdata, | ||
| 179 | .buf32 = arg->h48data, | ||
| 180 | .selfsim = arg->selfsim, | ||
| 181 | .crep = arg->crep | ||
| 182 | }; | ||
| 183 | for ( | ||
| 184 | bfsarg.done = 1, bfsarg.depth = 1, cc = 0; | ||
| 185 | bfsarg.done < esep_max && bfsarg.depth <= arg->maxdepth; | ||
| 186 | bfsarg.depth++ | ||
| 187 | ) { | ||
| 188 | LOG("esep: generating depth %" PRIu8 "\n", bfsarg.depth); | ||
| 189 | cc = gendata_h48h0k4_bfs(&bfsarg); | ||
| 190 | bfsarg.done += cc; | ||
| 191 | arg->info[bfsarg.depth+1] = cc; | ||
| 192 | LOG("found %" PRId64 "\n", cc); | ||
| 193 | } | ||
| 194 | |||
| 195 | arg->info[0] = bfsarg.depth-1; | ||
| 196 | |||
| 197 | LOG("h48 pruning table computed\n"); | ||
| 198 | LOG("Maximum pruning value: %" PRIu32 "\n", arg->info[0]); | ||
| 199 | LOG("Pruning value distribution:\n"); | ||
| 200 | for (j = 0; j <= arg->info[0]; j++) | ||
| 201 | LOG("%" PRIu8 ":\t%" PRIu32 "\n", j, arg->info[j+1]); | ||
| 202 | |||
| 203 | gendata_h48h0k4_return_size: | ||
| 204 | return H48_TABLESIZE(0, 4); | ||
| 205 | } | ||
| 206 | |||
| 207 | _static int64_t | ||
| 208 | gendata_h48h0k4_bfs(bfsarg_esep_t *arg) | ||
| 209 | { | ||
| 210 | const uint8_t breakpoint = 10; /* Hand-picked optimal */ | ||
| 211 | |||
| 212 | if (arg->depth < breakpoint) | ||
| 213 | return gendata_h48h0k4_bfs_fromdone(arg); | ||
| 214 | else | ||
| 215 | return gendata_h48h0k4_bfs_fromnew(arg); | ||
| 216 | } | ||
| 217 | |||
| 218 | _static int64_t | ||
| 219 | gendata_h48h0k4_bfs_fromdone(bfsarg_esep_t *arg) | ||
| 220 | { | ||
| 221 | uint8_t c, m, x; | ||
| 222 | uint32_t cc; | ||
| 223 | int64_t i, j, k; | ||
| 224 | cube_t cube, moved; | ||
| 225 | |||
| 226 | for (i = 0, cc = 0; i < (int64_t)H48_COORDMAX(0); i++) { | ||
| 227 | c = get_esep_pval(arg->buf32, i, 4); | ||
| 228 | if (c != arg->depth - 1) | ||
| 229 | continue; | ||
| 230 | cube = invcoord_h48(i, arg->crep, 0); | ||
| 231 | for (m = 0; m < 18; m++) { | ||
| 232 | moved = move(cube, m); | ||
| 233 | j = coord_h48(moved, arg->cocsepdata, 0); | ||
| 234 | if (get_esep_pval(arg->buf32, j, 4) <= arg->depth) | ||
| 235 | continue; | ||
| 236 | _foreach_h48sim(moved, arg->cocsepdata, arg->selfsim, 0, | ||
| 237 | k = coord_h48(moved, arg->cocsepdata, 0); | ||
| 238 | x = get_esep_pval(arg->buf32, k, 4); | ||
| 239 | set_esep_pval(arg->buf32, k, 4, arg->depth); | ||
| 240 | cc += x != arg->depth; | ||
| 241 | ) | ||
| 242 | } | ||
| 243 | } | ||
| 244 | |||
| 245 | return cc; | ||
| 246 | } | ||
| 247 | |||
| 248 | _static int64_t | ||
| 249 | gendata_h48h0k4_bfs_fromnew(bfsarg_esep_t *arg) | ||
| 250 | { | ||
| 251 | uint8_t c, m, x; | ||
| 252 | uint32_t cc; | ||
| 253 | int64_t i, j; | ||
| 254 | cube_t cube, moved; | ||
| 255 | |||
| 256 | for (i = 0, cc = 0; i < (int64_t)H48_COORDMAX(0); i++) { | ||
| 257 | c = get_esep_pval(arg->buf32, i, 4); | ||
| 258 | if (c != 0xF) | ||
| 259 | continue; | ||
| 260 | cube = invcoord_h48(i, arg->crep, 0); | ||
| 261 | for (m = 0; m < 18; m++) { | ||
| 262 | moved = move(cube, m); | ||
| 263 | j = coord_h48(moved, arg->cocsepdata, 0); | ||
| 264 | x = get_esep_pval(arg->buf32, j, 4); | ||
| 265 | if (x >= arg->depth) | ||
| 266 | continue; | ||
| 267 | _foreach_h48sim(cube, arg->cocsepdata, arg->selfsim, 0, | ||
| 268 | j = coord_h48(cube, arg->cocsepdata, 0); | ||
| 269 | x = get_esep_pval(arg->buf32, j, 4); | ||
| 270 | set_esep_pval(arg->buf32, j, 4, arg->depth); | ||
| 271 | cc += x == 0xF; | ||
| 272 | ) | ||
| 273 | break; /* Enough to find one, skip the rest */ | ||
| 274 | } | ||
| 275 | } | ||
| 276 | |||
| 277 | return cc; | ||
| 278 | } | ||
| 279 | |||
| 280 | _static size_t | ||
| 281 | gendata_h48k2(gendata_h48_arg_t *arg) | ||
| 282 | { | ||
| 283 | static const uint8_t shortdepth = 8; | ||
| 284 | static const uint64_t capacity = 10000019; | ||
| 285 | static const uint64_t randomizer = 10000079; | ||
| 286 | static const uint8_t base[] = { | ||
| 287 | [0] = 8, | ||
| 288 | [1] = 8, | ||
| 289 | [2] = 8, | ||
| 290 | [3] = 8, | ||
| 291 | [4] = 9, | ||
| 292 | [5] = 9, | ||
| 293 | [6] = 9, | ||
| 294 | [7] = 9, | ||
| 295 | [8] = 10, | ||
| 296 | [9] = 10, | ||
| 297 | [10] = 10, | ||
| 298 | [11] = 10 | ||
| 299 | }; | ||
| 300 | |||
| 301 | uint64_t nshort; | ||
| 302 | h48map_t shortcubes; | ||
| 303 | gendata_h48short_arg_t shortarg; | ||
| 304 | |||
| 305 | DBG_ASSERT(base[arg->h] == 8, 0, "Only implemented for h <= 3 (base 8)\n"); | ||
| 306 | |||
| 307 | if (arg->buf == NULL) | ||
| 308 | goto gendata_h48k2_return_size; | ||
| 309 | |||
| 310 | LOG("Computing depth <=%" PRIu8 "\n", shortdepth) | ||
| 311 | h48map_create(&shortcubes, capacity, randomizer); | ||
| 312 | shortarg = (gendata_h48short_arg_t) { | ||
| 313 | .maxdepth = shortdepth, | ||
| 314 | .cocsepdata = arg->cocsepdata, | ||
| 315 | .crep = arg->crep, | ||
| 316 | .selfsim = arg->selfsim, | ||
| 317 | .map = &shortcubes | ||
| 318 | }; | ||
| 319 | nshort = gen_h48short(&shortarg); | ||
| 320 | LOG("Found %" PRIu64 "\n", nshort); | ||
| 321 | |||
| 322 | /* TODO: loop over map, set all found to 0, do 2 moves each */ | ||
| 323 | LOG("The rest is not implemented yet\n"); | ||
| 324 | |||
| 325 | h48map_destroy(&shortcubes); | ||
| 326 | |||
| 327 | gendata_h48k2_return_size: | ||
| 328 | return H48_TABLESIZE(arg->h, 2); | ||
| 329 | } | ||
| 330 | |||
| 331 | _static_inline uint8_t | ||
| 332 | get_esep_pval(const uint32_t *buf32, int64_t i, uint8_t k) | ||
| 333 | { | ||
| 334 | return (buf32[H48_INDEX(i, k)] & H48_MASK(i, k)) >> H48_SHIFT(i, k); | ||
| 335 | } | ||
| 336 | |||
| 337 | _static_inline void | ||
| 338 | set_esep_pval(uint32_t *buf32, int64_t i, uint8_t k, uint8_t val) | ||
| 339 | { | ||
| 340 | buf32[H48_INDEX(i, k)] = (buf32[H48_INDEX(i, k)] & (~H48_MASK(i, k))) | ||
| 341 | | (val << H48_SHIFT(i, k)); | ||
| 342 | } | ||
| 343 | |||
| 344 | _static_inline int8_t | ||
| 345 | get_h48_bound(cube_t cube, uint32_t cdata, uint8_t h, uint8_t k, uint32_t *h48data) | ||
| 346 | { | ||
| 347 | int64_t coord; | ||
| 348 | |||
| 349 | coord = coord_h48_edges(cube, COCLASS(cdata), TTREP(cdata), h); | ||
| 350 | return get_esep_pval(h48data, coord, k); | ||
| 351 | } | ||
