diff options
| author | Sebastiano Tronto <sebastiano@tronto.net> | 2024-04-12 18:49:14 +0200 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano@tronto.net> | 2024-04-12 18:49:14 +0200 |
| commit | 1cf6502c9f3d8994e5c97f90cc29392043e40f2b (patch) | |
| tree | 5a0b7da5f701094c1e809ed2a3b11b5c2c29379d | |
| parent | 6e9ca0165e27bb863b25ff2d72844731f38efca7 (diff) | |
| download | nissy-core-1cf6502c9f3d8994e5c97f90cc29392043e40f2b.tar.gz nissy-core-1cf6502c9f3d8994e5c97f90cc29392043e40f2b.zip | |
Added edge pruning table, to be tested
| -rw-r--r-- | TODO.txt | 9 | ||||
| -rw-r--r-- | cube.c | 181 |
2 files changed, 176 insertions, 14 deletions
| @@ -1,5 +1,10 @@ | |||
| 1 | TODO implement big pruning table for H48 solver (edges) | 1 | TODO test big pruning table for H48 |
| 2 | TODO alternative: ARM NEON part | 2 | TODO generate edge tables by corner case? |
| 3 | TODO make h48-core-portable | ||
| 4 | TODO checkdata and hash check for cocsep | ||
| 5 | TODO benchmarks for solve and table generation | ||
| 6 | TODO optimization for transform edges only (and test) | ||
| 7 | TODO ARM NEON part | ||
| 3 | 8 | ||
| 4 | ## H48 optimal solver | 9 | ## H48 optimal solver |
| 5 | 10 | ||
| @@ -38,6 +38,8 @@ Section: mathematical constants | |||
| 38 | #define _12c4 495U | 38 | #define _12c4 495U |
| 39 | #define _8c4 70U | 39 | #define _8c4 70U |
| 40 | 40 | ||
| 41 | #define COCSEP_CLASSES 3393U | ||
| 42 | |||
| 41 | _static int64_t binomial[12][12] = { | 43 | _static int64_t binomial[12][12] = { |
| 42 | {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, | 44 | {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, |
| 43 | {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, | 45 | {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, |
| @@ -1183,6 +1185,8 @@ _static void writetrans(uint8_t, char *); | |||
| 1183 | _static cube_fast_t move(cube_fast_t, uint8_t); | 1185 | _static cube_fast_t move(cube_fast_t, uint8_t); |
| 1184 | _static cube_fast_t transform(cube_fast_t, uint8_t); | 1186 | _static cube_fast_t transform(cube_fast_t, uint8_t); |
| 1185 | 1187 | ||
| 1188 | _static_inline int64_t coord_fast_h48(cube_fast_t, uint32_t *, uint8_t); | ||
| 1189 | |||
| 1186 | cube_t | 1190 | cube_t |
| 1187 | solvedcube(void) | 1191 | solvedcube(void) |
| 1188 | { | 1192 | { |
| @@ -1774,7 +1778,7 @@ move(cube_fast_t c, uint8_t m) | |||
| 1774 | case B3: | 1778 | case B3: |
| 1775 | return _move(B3, c); | 1779 | return _move(B3, c); |
| 1776 | default: | 1780 | default: |
| 1777 | DBG_LOG("mover error, unknown move\n"); | 1781 | DBG_LOG("move error, unknown move\n"); |
| 1778 | return zero_fast; | 1782 | return zero_fast; |
| 1779 | } | 1783 | } |
| 1780 | } | 1784 | } |
| @@ -1885,6 +1889,31 @@ transform(cube_fast_t c, uint8_t t) | |||
| 1885 | } | 1889 | } |
| 1886 | } | 1890 | } |
| 1887 | 1891 | ||
| 1892 | /* h is the number of eo bits used */ | ||
| 1893 | _static_inline int64_t | ||
| 1894 | coord_fast_h48(cube_fast_t c, uint32_t *cocsepdata, uint8_t h) | ||
| 1895 | { | ||
| 1896 | cube_fast_t d; | ||
| 1897 | int64_t cocsep, coclass, esep, eo, esize; | ||
| 1898 | uint32_t data; | ||
| 1899 | uint8_t ttrep; | ||
| 1900 | |||
| 1901 | DBG_ASSERT(h <= 11, -1, | ||
| 1902 | "coord_fast_h48: h must be between 0 and 11\n"); | ||
| 1903 | |||
| 1904 | cocsep = coord_fast_cocsep(c); | ||
| 1905 | data = cocsepdata[cocsep]; | ||
| 1906 | coclass = (data & (0xFFFFU << 16U)) >> 16U; | ||
| 1907 | ttrep = (data & (0xFFU << 8U)) >> 8U; | ||
| 1908 | |||
| 1909 | d = transform(c, ttrep); /* TODO: transform only edges */ | ||
| 1910 | esep = coord_fast_esep(d); | ||
| 1911 | eo = coord_fast_eo(d); | ||
| 1912 | |||
| 1913 | esize = (_12c4 * _8c4) << h; | ||
| 1914 | return (coclass * esize) + (esep << h) + (eo >> (11-h)); | ||
| 1915 | } | ||
| 1916 | |||
| 1888 | /****************************************************************************** | 1917 | /****************************************************************************** |
| 1889 | Section: moves, move sequences and transformations | 1918 | Section: moves, move sequences and transformations |
| 1890 | 1919 | ||
| @@ -1918,10 +1947,28 @@ moveaxis(uint8_t move) | |||
| 1918 | Section: auxiliary procedures for H48 optimal solver (temporary) | 1947 | Section: auxiliary procedures for H48 optimal solver (temporary) |
| 1919 | ******************************************************************************/ | 1948 | ******************************************************************************/ |
| 1920 | 1949 | ||
| 1950 | typedef struct { | ||
| 1951 | cube_fast_t cube; | ||
| 1952 | uint8_t nmoves; | ||
| 1953 | uint8_t depth; | ||
| 1954 | uint8_t h; | ||
| 1955 | uint8_t k; | ||
| 1956 | uint16_t *nclasses; | ||
| 1957 | uint32_t *cocsepdata; | ||
| 1958 | uint32_t *buf32; | ||
| 1959 | bool *visited; | ||
| 1960 | } dfsarg_gendata_t; | ||
| 1961 | |||
| 1921 | _static size_t gendata_cocsep(void *); | 1962 | _static size_t gendata_cocsep(void *); |
| 1922 | _static uint32_t dfs_cocsep( | 1963 | _static uint32_t dfs_cocsep( /* TODO: use dfsarg */ |
| 1923 | cube_fast_t, uint8_t, uint8_t, uint16_t *, uint32_t *, bool *); | 1964 | cube_fast_t, uint8_t, uint8_t, uint16_t *, uint32_t *, bool *); |
| 1924 | 1965 | ||
| 1966 | _static size_t gendata_eoesep(uint8_t, uint8_t, void *, void *); | ||
| 1967 | _static uint32_t dfs_eoesep(dfsarg_gendata_t *); | ||
| 1968 | |||
| 1969 | _static_inline uint8_t get_h48_pval(uint32_t *, int64_t, uint8_t); | ||
| 1970 | _static_inline void set_h48_pval(uint32_t *, int64_t, uint8_t, uint8_t); | ||
| 1971 | |||
| 1925 | /* | 1972 | /* |
| 1926 | Each element of the cocsep table is a uint32_t used as follows: | 1973 | Each element of the cocsep table is a uint32_t used as follows: |
| 1927 | - Lowest 8-bit block: pruning value | 1974 | - Lowest 8-bit block: pruning value |
| @@ -1937,35 +1984,41 @@ _static size_t | |||
| 1937 | gendata_cocsep(void *buf) | 1984 | gendata_cocsep(void *buf) |
| 1938 | { | 1985 | { |
| 1939 | static size_t tablesize = _3p7 << 7U; | 1986 | static size_t tablesize = _3p7 << 7U; |
| 1987 | static size_t infosize = 12; | ||
| 1940 | 1988 | ||
| 1941 | cube_fast_t solved; | 1989 | cube_fast_t solved; |
| 1942 | uint32_t *buf32, cc; | 1990 | uint32_t *buf32, *info, cc; |
| 1943 | uint16_t n; | 1991 | uint16_t n; |
| 1944 | uint8_t i, j; | 1992 | uint8_t i, j; |
| 1945 | bool visited[tablesize]; | 1993 | bool visited[tablesize]; |
| 1946 | 1994 | ||
| 1947 | buf32 = (uint32_t *)buf; | 1995 | buf32 = (uint32_t *)buf; |
| 1996 | info = buf32 + tablesize; | ||
| 1948 | memset(buf32, 0xFFU, 4*tablesize); | 1997 | memset(buf32, 0xFFU, 4*tablesize); |
| 1949 | memset(buf32 + tablesize, 0, 21*4); | 1998 | memset(info, 0, 4*infosize); |
| 1950 | 1999 | ||
| 1951 | solved = cubetofast(solvedcube()); | 2000 | solved = cubetofast(solvedcube()); |
| 1952 | buf32[tablesize+1] = 9U; /* Known max pruning value */ | ||
| 1953 | for (i = 0, n = 0, cc = 0; i < 10; i++) { | 2001 | for (i = 0, n = 0, cc = 0; i < 10; i++) { |
| 1954 | memset(visited, 0, tablesize); /* Set visited bit for dfs */ | 2002 | memset(visited, 0, tablesize * sizeof(bool)); |
| 1955 | DBG_LOG("gendata_cocsep: generating depth %" PRIu8 "\n", i); | 2003 | DBG_LOG("gendata_cocsep: generating depth %" PRIu8 "\n", i); |
| 1956 | cc = dfs_cocsep(solved, 0, i, &n, buf32, visited); | 2004 | cc = dfs_cocsep(solved, 0, i, &n, buf32, visited); |
| 1957 | buf32[tablesize+i+2] = cc; | 2005 | info[i+2] = cc; |
| 1958 | DBG_LOG("found %" PRIu32 "\n", cc); | 2006 | DBG_LOG("found %" PRIu32 "\n", cc); |
| 1959 | } | 2007 | } |
| 1960 | buf32[tablesize] = (uint32_t)n; | 2008 | info[0] = (uint32_t)n; |
| 2009 | info[1] = 9U; /* Known max pruning value */ | ||
| 2010 | DBG_ASSERT(n == COCSEP_CLASSES, 0, | ||
| 2011 | "cocsep: computed %" PRIu16 " symmetry classes, " | ||
| 2012 | "expected %" PRIu16 "\n", n, COCSEP_CLASSES); | ||
| 1961 | 2013 | ||
| 1962 | DBG_LOG("cocsep data computed, %" PRIu32 " symmetry classes\n", n); | 2014 | DBG_LOG("cocsep data computed\n"); |
| 1963 | DBG_LOG("Maximum pruning value: %" PRIu32 "\n", buf32[tablesize+1]); | 2015 | DBG_LOG("Symmetry classes: %" PRIu32 "\n", info[0]); |
| 2016 | DBG_LOG("Maximum pruning value: %" PRIu32 "\n", info[1]); | ||
| 1964 | DBG_LOG("Pruning value distribution:\n"); | 2017 | DBG_LOG("Pruning value distribution:\n"); |
| 1965 | for (j = 0; j < 10; j++) | 2018 | for (j = 0; j < 10; j++) |
| 1966 | DBG_LOG("%" PRIu8 ":\t%" PRIu32 "\n", j, buf32[tablesize+j+2]); | 2019 | DBG_LOG("%" PRIu8 ":\t%" PRIu32 "\n", j, info[j+2]); |
| 1967 | 2020 | ||
| 1968 | return 4*(tablesize + 12); | 2021 | return 4*(tablesize + infosize); |
| 1969 | } | 2022 | } |
| 1970 | 2023 | ||
| 1971 | _static uint32_t | 2024 | _static uint32_t |
| @@ -2014,6 +2067,110 @@ dfs_cocsep( | |||
| 2014 | return cc; | 2067 | return cc; |
| 2015 | } | 2068 | } |
| 2016 | 2069 | ||
| 2070 | /* | ||
| 2071 | TODO description | ||
| 2072 | h is the number of eo bits | ||
| 2073 | k is the compression size (4, 2 or 1 bit) | ||
| 2074 | */ | ||
| 2075 | _static size_t | ||
| 2076 | gendata_eoesep(uint8_t h, uint8_t k, void *cocsepdata, void *buf) | ||
| 2077 | { | ||
| 2078 | DBG_ASSERT(k == 4, 0, "eoesep: only k=4 is supported"); | ||
| 2079 | |||
| 2080 | size_t tablesize = ((COCSEP_CLASSES * _12c4 * _8c4) / (8U / k)) << h; | ||
| 2081 | size_t infosize = 25; /* TODO unknown yet */ | ||
| 2082 | |||
| 2083 | uint32_t *buf32, *info, cc; | ||
| 2084 | bool visited[tablesize]; /* TODO: change this, becomes too large */ | ||
| 2085 | dfsarg_gendata_t arg; | ||
| 2086 | |||
| 2087 | buf32 = (uint32_t *)buf; | ||
| 2088 | info = buf32 + tablesize; | ||
| 2089 | memset(buf32, 0xFFU, 4*tablesize); | ||
| 2090 | memset(info, 0, 4*infosize); | ||
| 2091 | |||
| 2092 | arg.cube = cubetofast(solvedcube()); | ||
| 2093 | arg.nmoves = 0; | ||
| 2094 | arg.cocsepdata = (uint32_t *)cocsepdata; | ||
| 2095 | arg.buf32 = buf32; | ||
| 2096 | arg.visited = visited; | ||
| 2097 | /* TODO loop until no more is done, not until 12! (or hardcode limits)*/ | ||
| 2098 | for (arg.depth = 0, cc = 0; arg.depth < 12; arg.depth++) { | ||
| 2099 | memset(visited, 0, tablesize * sizeof(bool)); | ||
| 2100 | DBG_LOG("gendata_eoesep: generating depth %" PRIu8 "\n", | ||
| 2101 | arg.depth); | ||
| 2102 | cc = dfs_eoesep(&arg); | ||
| 2103 | info[arg.depth+1] = cc; | ||
| 2104 | DBG_LOG("found %" PRIu32 "\n", cc); | ||
| 2105 | } | ||
| 2106 | |||
| 2107 | return cc; | ||
| 2108 | } | ||
| 2109 | |||
| 2110 | _static_inline uint8_t | ||
| 2111 | get_h48_pval(uint32_t *buf32, int64_t index, uint8_t k) | ||
| 2112 | { | ||
| 2113 | uint8_t mask, shift; | ||
| 2114 | |||
| 2115 | DBG_ASSERT(k == 1 || k == 2 || k == 4, 0, | ||
| 2116 | "h48 coordinate invalid k=%" PRIu8 "\n", k); | ||
| 2117 | |||
| 2118 | shift = (uint8_t)(k * index % (32 / k)); | ||
| 2119 | mask = (1U << k) - 1U; | ||
| 2120 | |||
| 2121 | return (buf32[index] & (mask << shift)) >> shift; | ||
| 2122 | } | ||
| 2123 | |||
| 2124 | _static_inline void | ||
| 2125 | set_h48_pval(uint32_t *buf32, int64_t index, uint8_t k, uint8_t val) | ||
| 2126 | { | ||
| 2127 | uint8_t mask, shift; | ||
| 2128 | |||
| 2129 | DBG_ASSERT(k == 1 || k == 2 || k == 4, , | ||
| 2130 | "h48 coordinate invalid k=%" PRIu8 "\n", k); | ||
| 2131 | |||
| 2132 | shift = (uint8_t)(k * index % (32 / k)); | ||
| 2133 | mask = (1U << k) - 1U; | ||
| 2134 | |||
| 2135 | buf32[index] = (buf32[index] & (~mask)) | (val << shift); | ||
| 2136 | } | ||
| 2137 | |||
| 2138 | _static uint32_t | ||
| 2139 | dfs_eoesep(dfsarg_gendata_t *arg) | ||
| 2140 | { | ||
| 2141 | uint8_t m, olddepth; | ||
| 2142 | uint32_t cc; | ||
| 2143 | uint64_t i; | ||
| 2144 | dfsarg_gendata_t newarg; | ||
| 2145 | |||
| 2146 | i = coord_fast_h48(arg->cube, arg->cocsepdata, arg->h); | ||
| 2147 | olddepth = get_h48_pval(arg->buf32, i, arg->k); | ||
| 2148 | if (olddepth < arg->nmoves || arg->visited[i]) | ||
| 2149 | return 0; | ||
| 2150 | arg->visited[i] = true; | ||
| 2151 | |||
| 2152 | if (arg->nmoves == arg->depth) { | ||
| 2153 | cc = olddepth == 0xFFU; | ||
| 2154 | set_h48_pval(arg->buf32, i, arg->k, arg->depth); | ||
| 2155 | return cc; | ||
| 2156 | } | ||
| 2157 | |||
| 2158 | cc = 0; | ||
| 2159 | newarg = *arg; | ||
| 2160 | newarg.nmoves = arg->nmoves + 1; | ||
| 2161 | /* | ||
| 2162 | newarg.nmoves = arg->nmoves + 1; | ||
| 2163 | newarg.depth = arg->depth; | ||
| 2164 | newarg.h = arg->h; | ||
| 2165 | newarg.k = arg->k; | ||
| 2166 | */ | ||
| 2167 | _foreach_move(m, arg->cube, newarg.cube, | ||
| 2168 | cc += dfs_eoesep(&newarg); | ||
| 2169 | ) | ||
| 2170 | |||
| 2171 | return cc; | ||
| 2172 | } | ||
| 2173 | |||
| 2017 | /****************************************************************************** | 2174 | /****************************************************************************** |
| 2018 | Section: solvers | 2175 | Section: solvers |
| 2019 | 2176 | ||
