diff options
Diffstat (limited to 'src/solve_h48.h')
| -rw-r--r-- | src/solve_h48.h | 176 |
1 files changed, 85 insertions, 91 deletions
diff --git a/src/solve_h48.h b/src/solve_h48.h index b04ae47..b95e6ce 100644 --- a/src/solve_h48.h +++ b/src/solve_h48.h | |||
| @@ -1,20 +1,20 @@ | |||
| 1 | #define COCSEP_CLASSES 3393U | 1 | #define COCSEP_CLASSES 3393U |
| 2 | #define COCSEP_TABLESIZE (_3p7 << 7U) | 2 | #define COCSEP_TABLESIZE (_3p7 << 7U) |
| 3 | #define COCSEP_VISITEDSIZE ((COCSEP_TABLESIZE + 7U) / 8U) | 3 | #define COCSEP_VISITEDSIZE ((COCSEP_TABLESIZE + 7U) / 8U) |
| 4 | #define COCSEP_INFOSIZE 12U | 4 | #define COCSEP_INFOSIZE 12U |
| 5 | #define COCSEP_FULLSIZE (4 * (COCSEP_TABLESIZE + COCSEP_INFOSIZE)) | 5 | #define COCSEP_FULLSIZE (4 * (COCSEP_TABLESIZE + COCSEP_INFOSIZE)) |
| 6 | 6 | ||
| 7 | #define ESEP_TABLESIZE ((COCSEP_CLASSES * _12c4 * _8c4) / 2U) | 7 | #define ESEP_MAX(h) ((COCSEP_CLASSES * _12c4 * _8c4) << (h)) |
| 8 | #define ESEP_VISITEDSIZE ((ESEP_TABLESIZE * 2U + 7U) / 8U) | 8 | #define ESEP_TABLESIZE(h, k) (ESEP_MAX((h)) >> (k)) |
| 9 | #define ESEP_INFOSIZE 25 /* TODO unknown yet */ | 9 | #define ESEP_INFOSIZE 25 /* TODO unknown yet */ |
| 10 | 10 | ||
| 11 | #define H48_ESIZE(h) ((_12c4 * _8c4) << (h)) | 11 | #define H48_ESIZE(h) ((_12c4 * _8c4) << (h)) |
| 12 | 12 | ||
| 13 | #define _esep_ind(i) (i / 8U) | 13 | #define _esep_ind(i) (i / 8U) |
| 14 | #define _esep_shift(i) (4U * (i % 8U)) | 14 | #define _esep_shift(i) (4U * (i % 8U)) |
| 15 | #define _esep_mask(i) (((1U << 4U) - 1U) << _esep_shift(i)) | 15 | #define _esep_mask(i) (((1U << 4U) - 1U) << _esep_shift(i)) |
| 16 | #define _visited_ind(i) (i / 8U) | 16 | #define _visited_ind(i) (i / 8U) |
| 17 | #define _visited_mask(i) (1U << (i % 8U)) | 17 | #define _visited_mask(i) (1U << (i % 8U)) |
| 18 | 18 | ||
| 19 | typedef struct { | 19 | typedef struct { |
| 20 | cube_fast_t cube; | 20 | cube_fast_t cube; |
| @@ -28,23 +28,21 @@ typedef struct { | |||
| 28 | } dfsarg_cocsep_t; | 28 | } dfsarg_cocsep_t; |
| 29 | 29 | ||
| 30 | typedef struct { | 30 | typedef struct { |
| 31 | cube_fast_t cube; | ||
| 32 | uint8_t *visited; | ||
| 33 | uint8_t *moves; | ||
| 34 | uint8_t nmoves; | ||
| 35 | uint8_t depth; | 31 | uint8_t depth; |
| 36 | uint16_t *nclasses; | 32 | uint8_t h; |
| 37 | uint32_t *cocsepdata; | 33 | uint32_t *cocsepdata; |
| 38 | uint32_t *buf32; | 34 | uint32_t *buf32; |
| 39 | } dfsarg_esep_t; | 35 | uint64_t *selfsim; |
| 36 | cube_fast_t *crep; | ||
| 37 | } bfsarg_esep_t; | ||
| 40 | 38 | ||
| 41 | _static_inline int64_t coord_h48(cube_fast_t, const uint32_t *, uint8_t); | 39 | _static_inline int64_t coord_h48(cube_fast_t, const uint32_t *, uint8_t); |
| 42 | _static_inline cube_fast_t invcoord_h48(int64_t, const cube_fast_t *, uint8_t); | 40 | _static_inline cube_fast_t invcoord_h48(int64_t, const cube_fast_t *, uint8_t); |
| 43 | 41 | ||
| 44 | _static size_t gendata_cocsep(void *, uint64_t *, cube_fast_t *); | 42 | _static size_t gendata_cocsep(void *, uint64_t *, cube_fast_t *); |
| 45 | _static uint32_t gendata_cocsep_dfs(dfsarg_cocsep_t *); | 43 | _static uint32_t gendata_cocsep_dfs(dfsarg_cocsep_t *); |
| 46 | _static size_t gendata_esep(void *); | 44 | _static size_t gendata_h48(void *, uint8_t); |
| 47 | _static uint32_t gendata_esep_dfs(dfsarg_esep_t *); | 45 | _static uint64_t gendata_esep_bfs(bfsarg_esep_t *); |
| 48 | 46 | ||
| 49 | _static_inline bool get_visited(const uint8_t *, int64_t); | 47 | _static_inline bool get_visited(const uint8_t *, int64_t); |
| 50 | _static_inline void set_visited(uint8_t *, int64_t); | 48 | _static_inline void set_visited(uint8_t *, int64_t); |
| @@ -86,7 +84,7 @@ invcoord_h48(int64_t i, const cube_fast_t *crep, uint8_t h) { | |||
| 86 | cube_fast_t ret; int64_t coclass, ee, esep, eo; | 84 | cube_fast_t ret; int64_t coclass, ee, esep, eo; |
| 87 | 85 | ||
| 88 | DBG_ASSERT(h <= 11, cubetofast(zero), | 86 | DBG_ASSERT(h <= 11, cubetofast(zero), |
| 89 | "invcoord_h48: h must be between 0 and 11\n"); | 87 | "invcoord_h48: h must be between 0 and 11\n"); |
| 90 | 88 | ||
| 91 | coclass = i / H48_ESIZE(h); | 89 | coclass = i / H48_ESIZE(h); |
| 92 | ee = i % H48_ESIZE(h); | 90 | ee = i % H48_ESIZE(h); |
| @@ -164,7 +162,7 @@ gendata_cocsep_dfs(dfsarg_cocsep_t *arg) | |||
| 164 | { | 162 | { |
| 165 | uint8_t m, t, tinv, olddepth; | 163 | uint8_t m, t, tinv, olddepth; |
| 166 | uint32_t cc; | 164 | uint32_t cc; |
| 167 | int64_t i; | 165 | int64_t i, ii; |
| 168 | uint64_t sim; | 166 | uint64_t sim; |
| 169 | cube_fast_t d; | 167 | cube_fast_t d; |
| 170 | dfsarg_cocsep_t nextarg; | 168 | dfsarg_cocsep_t nextarg; |
| @@ -181,13 +179,12 @@ gendata_cocsep_dfs(dfsarg_cocsep_t *arg) | |||
| 181 | 179 | ||
| 182 | for (t = 0, cc = 0; t < 48; t++) { | 180 | for (t = 0, cc = 0; t < 48; t++) { |
| 183 | d = transform(arg->cube, t); | 181 | d = transform(arg->cube, t); |
| 184 | sim = equal_fast(arg->cube, d); | 182 | ii = coord_fast_cocsep(d); |
| 185 | arg->selfsim[*arg->n] |= sim << t; | 183 | arg->selfsim[*arg->n] |= (i == ii) << t; |
| 186 | i = coord_fast_cocsep(d); | 184 | set_visited(arg->visited, ii); |
| 187 | set_visited(arg->visited, i); | ||
| 188 | tinv = inverse_trans(t); | 185 | tinv = inverse_trans(t); |
| 189 | cc += (arg->buf32[i] & 0xFFU) == 0xFFU; | 186 | cc += (arg->buf32[ii] & 0xFFU) == 0xFFU; |
| 190 | arg->buf32[i] = | 187 | arg->buf32[ii] = |
| 191 | (*arg->n << 16U) | (tinv << 8U) | arg->depth; | 188 | (*arg->n << 16U) | (tinv << 8U) | arg->depth; |
| 192 | } | 189 | } |
| 193 | arg->rep[*arg->n] = arg->cube; | 190 | arg->rep[*arg->n] = arg->cube; |
| @@ -211,84 +208,81 @@ TODO description | |||
| 211 | generating fixed table with h=0, k=4 | 208 | generating fixed table with h=0, k=4 |
| 212 | */ | 209 | */ |
| 213 | _static size_t | 210 | _static size_t |
| 214 | gendata_esep(void *buf) | 211 | gendata_h48(void *buf, uint8_t h) |
| 215 | { | 212 | { |
| 216 | uint32_t *buf32, *info, *cocsepdata, cc; | 213 | const int k = 1; /* TODO: other cases? */ |
| 217 | uint8_t moves[20]; | 214 | uint32_t *buf32, *info, *cocsepdata; |
| 218 | dfsarg_esep_t arg; | 215 | bfsarg_esep_t arg; |
| 216 | int64_t sc, cc, tot; | ||
| 217 | uint64_t selfsim[COCSEP_CLASSES]; | ||
| 218 | cube_fast_t crep[COCSEP_CLASSES]; | ||
| 219 | size_t cocsepsize; | ||
| 219 | 220 | ||
| 220 | arg.visited = malloc(ESEP_TABLESIZE); | 221 | cocsepsize = gendata_cocsep(buf, selfsim, crep); |
| 222 | DBG_ASSERT(cocsepsize == COCSEP_FULLSIZE, 0, | ||
| 223 | "gendata_h48: error computing cocsep data\n"); | ||
| 221 | 224 | ||
| 222 | cocsepdata = (uint32_t *)buf; | 225 | cocsepdata = (uint32_t *)buf; |
| 223 | buf32 = cocsepdata + COCSEP_FULLSIZE; | 226 | buf32 = cocsepdata + cocsepsize; |
| 224 | info = buf32 + ESEP_TABLESIZE; | 227 | info = buf32 + ESEP_TABLESIZE(h, k); |
| 225 | memset(buf32, 0xFFU, sizeof(uint32_t) * ESEP_TABLESIZE); | 228 | memset(buf32, 0xFFU, sizeof(uint32_t) * ESEP_TABLESIZE(h, k)); |
| 226 | memset(info, 0, sizeof(uint32_t) * ESEP_INFOSIZE); | 229 | memset(info, 0, sizeof(uint32_t) * ESEP_INFOSIZE); |
| 227 | 230 | ||
| 228 | arg.cube = cubetofast(solvedcube()); | 231 | sc = coord_h48(cubetofast(solved), cocsepdata, h); |
| 229 | arg.moves = moves; | 232 | set_esep_pval(buf32, sc, 0); |
| 230 | arg.nmoves = 0; | 233 | arg = (bfsarg_esep_t) { |
| 231 | arg.cocsepdata = cocsepdata; | 234 | .h = h, |
| 232 | arg.buf32 = buf32; | 235 | .cocsepdata = cocsepdata, |
| 233 | /* TODO loop until no more is done, not until 12! (or hardcode limits)*/ | 236 | .buf32 = buf32, |
| 234 | /* TODO use bfs instead | 237 | .crep = crep, |
| 235 | how to work with different k? k=1 is the easiest */ | 238 | .selfsim = selfsim |
| 236 | for (arg.depth = 0, cc = 0; arg.depth < 12; arg.depth++) { | 239 | }; |
| 240 | for (tot = 1, arg.depth = 1, cc = 0; tot < ESEP_MAX(h); arg.depth++) { | ||
| 237 | DBG_LOG("esep: generating depth %" PRIu8 "\n", arg.depth); | 241 | DBG_LOG("esep: generating depth %" PRIu8 "\n", arg.depth); |
| 238 | memset(arg.visited, 0, ESEP_VISITEDSIZE); | 242 | cc = gendata_esep_bfs(&arg); |
| 239 | cc = gendata_esep_dfs(&arg); | 243 | tot += cc; |
| 240 | info[arg.depth+1] = cc; | 244 | info[arg.depth+1] = cc; |
| 241 | DBG_LOG("found %" PRIu32 "\n", cc); | 245 | DBG_LOG("found %" PRIu64 "\n", cc); |
| 242 | } | 246 | } |
| 243 | free(arg.visited); | ||
| 244 | 247 | ||
| 245 | return COCSEP_FULLSIZE + cc; | 248 | return COCSEP_FULLSIZE + cc; |
| 246 | } | 249 | } |
| 247 | 250 | ||
| 248 | _static uint32_t | 251 | _static uint64_t |
| 249 | gendata_esep_dfs(dfsarg_esep_t *arg) | 252 | gendata_esep_bfs(bfsarg_esep_t *arg) |
| 250 | { | 253 | { |
| 251 | uint8_t m, t, olddepth; | 254 | uint8_t c, m, t, x; |
| 252 | uint32_t cc; | 255 | uint32_t cc; |
| 253 | uint64_t i; | 256 | uint64_t i, j, k, cocsep_coord, sim; |
| 254 | cube_fast_t d; | 257 | cube_fast_t cube, moved, transd; |
| 255 | dfsarg_esep_t nextarg; | ||
| 256 | |||
| 257 | if (!allowednextmove(arg->moves, arg->nmoves)) | ||
| 258 | return 0; | ||
| 259 | 258 | ||
| 260 | if (arg->nmoves > 0) | 259 | for (i = 0, cc = 0; i < ESEP_MAX(arg->h); i++) { |
| 261 | arg->cube = move(arg->cube, arg->moves[arg->nmoves-1]); | 260 | c = get_esep_pval(arg->buf32, i); |
| 262 | 261 | if (c != arg->depth - 1) | |
| 263 | i = coord_h48(arg->cube, arg->cocsepdata, 0U); | 262 | continue; |
| 264 | olddepth = get_esep_pval(arg->buf32, i); | 263 | cube = invcoord_h48(i, arg->crep, arg->h); |
| 265 | 264 | for (m = 0; m < 18; m++) { | |
| 266 | if (olddepth < arg->nmoves || get_visited(arg->visited, i)) | 265 | moved = move(cube, m); |
| 267 | return 0; | 266 | j = coord_h48(moved, arg->cocsepdata, arg->h); |
| 268 | set_visited(arg->visited, i); | 267 | x = get_esep_pval(arg->buf32, j); |
| 269 | 268 | if (x <= arg->depth) | |
| 270 | if (arg->nmoves == arg->depth) { | 269 | continue; |
| 271 | if (olddepth != 15U) | 270 | set_esep_pval(arg->buf32, j, arg->depth); |
| 272 | return 0; | 271 | cc += x != arg->depth; |
| 273 | 272 | cocsep_coord = j / H48_ESIZE(arg->h); | |
| 274 | for (t = 0, cc = 0; t < 48; t++) { | 273 | sim = arg->selfsim[cocsep_coord]; |
| 275 | d = transform(arg->cube, t); | 274 | for (t = 1; t < 48; t++) { /* Skip trivial trans */ |
| 276 | i = coord_h48(d, arg->cocsepdata, 0U); | 275 | if (!(sim & (1 << t))) |
| 277 | set_visited(arg->visited, i); | 276 | continue; |
| 278 | cc += get_esep_pval(arg->buf32, i) == 15U; | 277 | transd = transform(moved, t); |
| 279 | set_esep_pval(arg->buf32, i, arg->depth); | 278 | k = coord_h48(transd, arg->cocsepdata, arg->h); |
| 279 | x = get_esep_pval(arg->buf32, k); | ||
| 280 | if (x <= arg->depth) | ||
| 281 | continue; | ||
| 282 | set_esep_pval(arg->buf32, k, arg->depth); | ||
| 283 | cc += x != arg->depth; | ||
| 284 | } | ||
| 280 | } | 285 | } |
| 281 | |||
| 282 | return cc; | ||
| 283 | } | ||
| 284 | |||
| 285 | |||
| 286 | nextarg = *arg; | ||
| 287 | nextarg.nmoves = arg->nmoves + 1; | ||
| 288 | for (m = 0, cc = 0; m < 18; m++) { | ||
| 289 | nextarg.cube = arg->cube; | ||
| 290 | nextarg.moves[arg->nmoves] = m; | ||
| 291 | cc += gendata_esep_dfs(&nextarg); | ||
| 292 | } | 286 | } |
| 293 | 287 | ||
| 294 | return cc; | 288 | return cc; |
