diff options
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | README.md | 5 | ||||
| -rw-r--r-- | src/coord.c | 8 | ||||
| -rw-r--r-- | src/cubetypes.h | 1 | ||||
| -rw-r--r-- | src/pruning.c | 157 | ||||
| -rw-r--r-- | src/symcoord.c | 9 |
6 files changed, 155 insertions, 26 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d9168a4 --- /dev/null +++ b/.gitignore | |||
| @@ -0,0 +1 @@ | |||
| nissy.o | |||
| @@ -109,8 +109,9 @@ table to solving EO with HTM moveset and this coordinate would have values 0 (fo | |||
| 109 | There is one caveat: each coordinates also needs an inverse function that takes a | 109 | There is one caveat: each coordinates also needs an inverse function that takes a |
| 110 | coordinate value and returns a cube which has that coordinate. This is in general | 110 | coordinate value and returns a cube which has that coordinate. This is in general |
| 111 | more complicated, but luckily the cube does not need to be fully built or consistent. | 111 | more complicated, but luckily the cube does not need to be fully built or consistent. |
| 112 | This inverse-coordinate is used only in one specific step when building pruning tables | 112 | This inverse-coordinate is used only in one specific step when generating symmetry |
| 113 | to avoid using up hundreds of Gb of memory. | 113 | data, and I don't know if it is possible to avoid it (maybe it is). It is also used |
| 114 | when building pruning tables, but in that case it is avoidable. | ||
| 114 | 115 | ||
| 115 | Note: this part is different from what Cube Explorer does. Overall I think it is | 116 | Note: this part is different from what Cube Explorer does. Overall I think it is |
| 116 | conceptually easier, although in practice it was still hard to implement. | 117 | conceptually easier, although in practice it was still hard to implement. |
diff --git a/src/coord.c b/src/coord.c index 7e691ef..059a7a2 100644 --- a/src/coord.c +++ b/src/coord.c | |||
| @@ -171,7 +171,7 @@ antindex_eofbepos(uint64_t ind) | |||
| 171 | 171 | ||
| 172 | /* We need eorl for sym16 coordinate */ | 172 | /* We need eorl for sym16 coordinate */ |
| 173 | static int initialized = false; | 173 | static int initialized = false; |
| 174 | static uint64_t eorl_aux[POW2TO11][BINOM12ON4]; | 174 | static uint64_t eorl_a[POW2TO11][BINOM12ON4]; |
| 175 | static int eo_aux[12], ep_aux[12]; | 175 | static int eo_aux[12], ep_aux[12]; |
| 176 | unsigned int i, j, k; | 176 | unsigned int i, j, k; |
| 177 | 177 | ||
| @@ -181,8 +181,10 @@ antindex_eofbepos(uint64_t ind) | |||
| 181 | int_to_sum_zero_array(i, 2, 12, eo_aux); | 181 | int_to_sum_zero_array(i, 2, 12, eo_aux); |
| 182 | index_to_subset(j, 12, 4, ep_aux); | 182 | index_to_subset(j, 12, 4, ep_aux); |
| 183 | for (k = 0; k < 12; k++) | 183 | for (k = 0; k < 12; k++) |
| 184 | if (ep_aux[k]) | 184 | if ((ep_aux[k] && k < FR) || |
| 185 | (!ep_aux[k] && k >= FR)) | ||
| 185 | eo_aux[k] = 1 - eo_aux[k]; | 186 | eo_aux[k] = 1 - eo_aux[k]; |
| 187 | eorl_a[i][j] = digit_array_to_int(eo_aux,11,2); | ||
| 186 | } | 188 | } |
| 187 | } | 189 | } |
| 188 | 190 | ||
| @@ -191,7 +193,7 @@ antindex_eofbepos(uint64_t ind) | |||
| 191 | 193 | ||
| 192 | ret.eofb = ind % POW2TO11; | 194 | ret.eofb = ind % POW2TO11; |
| 193 | ret.epose = (ind / POW2TO11) * 24; | 195 | ret.epose = (ind / POW2TO11) * 24; |
| 194 | ret.eorl = eorl_aux[ret.eofb][ret.epose/24]; | 196 | ret.eorl = eorl_a[ret.eofb][ret.epose/24]; |
| 195 | 197 | ||
| 196 | return ret; | 198 | return ret; |
| 197 | } | 199 | } |
diff --git a/src/cubetypes.h b/src/cubetypes.h index 6602a68..da8ab6b 100644 --- a/src/cubetypes.h +++ b/src/cubetypes.h | |||
| @@ -213,6 +213,7 @@ dfsdata | |||
| 213 | Alg * current_alg; | 213 | Alg * current_alg; |
| 214 | Move sorted_moves[NMOVES]; | 214 | Move sorted_moves[NMOVES]; |
| 215 | int move_position[NMOVES]; | 215 | int move_position[NMOVES]; |
| 216 | uint8_t * visited; | ||
| 216 | }; | 217 | }; |
| 217 | 218 | ||
| 218 | struct | 219 | struct |
diff --git a/src/pruning.c b/src/pruning.c index b7fedd4..ca6f57a 100644 --- a/src/pruning.c +++ b/src/pruning.c | |||
| @@ -1,7 +1,20 @@ | |||
| 1 | #include "pruning.h" | 1 | #include "pruning.h" |
| 2 | 2 | ||
| 3 | /* | ||
| 4 | * The commented functions are a way to generate a pruning table | ||
| 5 | * without using anti-indexes. It does not matter too much because | ||
| 6 | * we still need anti-indexes in gensym. | ||
| 7 | */ | ||
| 8 | /* | ||
| 9 | static bool dfs_get_visited(PruneData *pd, DfsData *dd, Cube c); | ||
| 10 | static bool dfs_get_visited_index(DfsData *dd, uint64_t ind); | ||
| 11 | static void dfs_set_visited(PruneData *pd, DfsData *dd, Cube c, bool b); | ||
| 12 | static void dfs_set_visited_index(DfsData *dd, uint64_t ind, bool b); | ||
| 13 | static void genptable_dfs(Cube c, PruneData *pd, DfsData *dd); | ||
| 14 | */ | ||
| 15 | |||
| 3 | static void genptable_bfs(PruneData *pd, int d, Move *ms); | 16 | static void genptable_bfs(PruneData *pd, int d, Move *ms); |
| 4 | static void genptable_branch(PruneData *pd, uint64_t i, int d, Move *m); | 17 | static void genptable_branch(PruneData *pd,uint64_t ind,int d,Move *ms); |
| 5 | static void ptable_update(PruneData *pd, Cube cube, int m); | 18 | static void ptable_update(PruneData *pd, Cube cube, int m); |
| 6 | static void ptable_update_index(PruneData *pd, uint64_t ind, int m); | 19 | static void ptable_update_index(PruneData *pd, uint64_t ind, int m); |
| 7 | static int ptableval_index(PruneData *pd, uint64_t ind); | 20 | static int ptableval_index(PruneData *pd, uint64_t ind); |
| @@ -78,6 +91,54 @@ pd_khuge_HTM = { | |||
| 78 | .moveset = moveset_HTM, | 91 | .moveset = moveset_HTM, |
| 79 | }; | 92 | }; |
| 80 | 93 | ||
| 94 | /* | ||
| 95 | void | ||
| 96 | genptable(PruneData *pd) | ||
| 97 | { | ||
| 98 | Move ms[NMOVES]; | ||
| 99 | uint64_t j, oldn; | ||
| 100 | DfsData dd; | ||
| 101 | |||
| 102 | if (pd->generated) | ||
| 103 | return; | ||
| 104 | |||
| 105 | pd->ptable = malloc(ptablesize(pd) * sizeof(uint8_t)); | ||
| 106 | |||
| 107 | if (read_ptable_file(pd)) { | ||
| 108 | pd->generated = true; | ||
| 109 | return; | ||
| 110 | } | ||
| 111 | pd->generated = true; | ||
| 112 | |||
| 113 | fprintf(stderr, "Cannot load %s, generating it\n", pd->filename); | ||
| 114 | |||
| 115 | moveset_to_list(pd->moveset, ms); | ||
| 116 | |||
| 117 | for (j = 0; j < pd->coord->max; j++) | ||
| 118 | ptable_update_index(pd, j, 15); | ||
| 119 | |||
| 120 | dd = (DfsData) { .m = 0 }; | ||
| 121 | dd.visited = malloc((ptablesize(pd)/4 + 1) * sizeof(uint8_t)); | ||
| 122 | moveset_to_list(pd->moveset, dd.sorted_moves); | ||
| 123 | oldn = 0; | ||
| 124 | pd->n = 0; | ||
| 125 | |||
| 126 | for (dd.d = 0; dd.d < 15 && pd->n < pd->coord->max; dd.d++) { | ||
| 127 | for (j = 0; j < pd->coord->max; j++) | ||
| 128 | dfs_set_visited_index(&dd, j, false); | ||
| 129 | genptable_dfs((Cube){0}, pd, &dd); | ||
| 130 | fprintf(stderr, "Depth %d done, generated %lu\t(%lu/%lu)\n", | ||
| 131 | dd.d+1, pd->n - oldn, pd->n, pd->coord->max); | ||
| 132 | oldn = pd->n; | ||
| 133 | } | ||
| 134 | |||
| 135 | if (!write_ptable_file(pd)) | ||
| 136 | fprintf(stderr, "Error writing ptable file\n"); | ||
| 137 | |||
| 138 | free(dd.visited); | ||
| 139 | } | ||
| 140 | */ | ||
| 141 | |||
| 81 | void | 142 | void |
| 82 | genptable(PruneData *pd) | 143 | genptable(PruneData *pd) |
| 83 | { | 144 | { |
| @@ -105,13 +166,6 @@ genptable(PruneData *pd) | |||
| 105 | for (j = 0; j < pd->coord->max; j++) | 166 | for (j = 0; j < pd->coord->max; j++) |
| 106 | ptable_update_index(pd, j, 15); | 167 | ptable_update_index(pd, j, 15); |
| 107 | 168 | ||
| 108 | for (j = 0; j < pd->coord->max; j++) | ||
| 109 | if (ptableval_index(pd, j) != 15) { | ||
| 110 | printf("Error, non-max value at index %lu!\n", j); | ||
| 111 | break; | ||
| 112 | } | ||
| 113 | printf("Table set, ready to start\n"); | ||
| 114 | |||
| 115 | ptable_update(pd, (Cube){0}, 0); | 169 | ptable_update(pd, (Cube){0}, 0); |
| 116 | pd->n = 1; | 170 | pd->n = 1; |
| 117 | oldn = 0; | 171 | oldn = 0; |
| @@ -127,7 +181,81 @@ genptable(PruneData *pd) | |||
| 127 | 181 | ||
| 128 | if (!write_ptable_file(pd)) | 182 | if (!write_ptable_file(pd)) |
| 129 | fprintf(stderr, "Error writing ptable file\n"); | 183 | fprintf(stderr, "Error writing ptable file\n"); |
| 184 | |||
| 185 | } | ||
| 186 | |||
| 187 | /* | ||
| 188 | static void | ||
| 189 | genptable_dfs(Cube c, PruneData *pd, DfsData *dd) | ||
| 190 | { | ||
| 191 | int i, j, pv; | ||
| 192 | Move mm; | ||
| 193 | Cube cc; | ||
| 194 | |||
| 195 | if (pd->coord->index(c) > 2*ptablesize(pd)) { | ||
| 196 | printf("error! %lu > %lu\n", pd->coord->index(c), 2*ptablesize(pd)); | ||
| 197 | print_cube(c); | ||
| 198 | exit(1); | ||
| 199 | } | ||
| 200 | pv = ptableval(pd, c); | ||
| 201 | |||
| 202 | if (pv < dd->m || dd->m > dd->d) | ||
| 203 | return; | ||
| 204 | |||
| 205 | if (dfs_get_visited(pd, dd, c)) | ||
| 206 | return; | ||
| 207 | dfs_set_visited(pd, dd, c, true); | ||
| 208 | |||
| 209 | if (pv != dd->m) | ||
| 210 | ptable_update(pd, c, dd->m); | ||
| 211 | |||
| 212 | for (i = 0; i < pd->coord->ntrans; i++) { | ||
| 213 | cc = i == 0 ? c : | ||
| 214 | apply_trans(pd->coord->trans[i], c); | ||
| 215 | for (j = 0; dd->sorted_moves[j] != NULLMOVE; j++) { | ||
| 216 | mm = dd->sorted_moves[j]; | ||
| 217 | dd->m++; | ||
| 218 | genptable_dfs(apply_move(mm, cc), pd, dd); | ||
| 219 | dd->m--; | ||
| 220 | } | ||
| 221 | } | ||
| 222 | } | ||
| 223 | */ | ||
| 224 | |||
| 225 | /* | ||
| 226 | static bool | ||
| 227 | dfs_get_visited(PruneData *pd, DfsData *dd, Cube c) | ||
| 228 | { | ||
| 229 | return dfs_get_visited_index(dd, pd->coord->index(c)); | ||
| 230 | } | ||
| 231 | */ | ||
| 232 | |||
| 233 | /* | ||
| 234 | static bool | ||
| 235 | dfs_get_visited_index(DfsData *dd, uint64_t ind) | ||
| 236 | { | ||
| 237 | return dd->visited[ind/8] & ((uint8_t)1 << (ind % 8)); | ||
| 238 | } | ||
| 239 | */ | ||
| 240 | |||
| 241 | /* | ||
| 242 | static void | ||
| 243 | dfs_set_visited(PruneData *pd, DfsData *dd, Cube c, bool b) | ||
| 244 | { | ||
| 245 | dfs_set_visited_index(dd, pd->coord->index(c), b); | ||
| 246 | } | ||
| 247 | */ | ||
| 248 | |||
| 249 | /* | ||
| 250 | static void | ||
| 251 | dfs_set_visited_index(DfsData *dd, uint64_t ind, bool b) | ||
| 252 | { | ||
| 253 | if (b) | ||
| 254 | dd->visited[ind/8] |= ((uint8_t)1 << (ind % 8)); | ||
| 255 | else | ||
| 256 | dd->visited[ind/8] &= ~((uint8_t)1 << (ind % 8)); | ||
| 130 | } | 257 | } |
| 258 | */ | ||
| 131 | 259 | ||
| 132 | static void | 260 | static void |
| 133 | genptable_bfs(PruneData *pd, int d, Move *ms) | 261 | genptable_bfs(PruneData *pd, int d, Move *ms) |
| @@ -145,22 +273,9 @@ genptable_branch(PruneData *pd, uint64_t ind, int d, Move *ms) | |||
| 145 | int i, j; | 273 | int i, j; |
| 146 | Cube ci, cc, c; | 274 | Cube ci, cc, c; |
| 147 | 275 | ||
| 148 | /* | ||
| 149 | * This is the only line of the whole program where we REALLY need an | ||
| 150 | * anti-indexer function. We could get rid of it if only we could save | ||
| 151 | * a cube object for each index value as we go, but then we would need | ||
| 152 | * an incredible amount of memory to generate each ptable: assuming | ||
| 153 | * fields in struct cube are 32 bit ints that would take 88 times the | ||
| 154 | * memory of the table to be generated, more than 120Gb for | ||
| 155 | * ptable_khuge for example! | ||
| 156 | * | ||
| 157 | * TODO: it would be nice to get rid of this... | ||
| 158 | * | ||
| 159 | */ | ||
| 160 | ci = pd->coord->cube(ind); | 276 | ci = pd->coord->cube(ind); |
| 161 | 277 | ||
| 162 | for (i = 0; i < pd->coord->ntrans; i++) { | 278 | for (i = 0; i < pd->coord->ntrans; i++) { |
| 163 | /* For simplicity trans[] is NULL when ntrans = 1 */ | ||
| 164 | c = i == 0 ? ci : | 279 | c = i == 0 ? ci : |
| 165 | apply_trans(pd->coord->trans[i], ci); | 280 | apply_trans(pd->coord->trans[i], ci); |
| 166 | for (j = 0; ms[j] != NULLMOVE; j++) { | 281 | for (j = 0; ms[j] != NULLMOVE; j++) { |
diff --git a/src/symcoord.c b/src/symcoord.c index 97a8d9a..e9374d7 100644 --- a/src/symcoord.c +++ b/src/symcoord.c | |||
| @@ -257,7 +257,16 @@ gensym(SymData *sd) | |||
| 257 | 257 | ||
| 258 | for (i = 0; i < sd->coord->max; i++) { | 258 | for (i = 0; i < sd->coord->max; i++) { |
| 259 | if (sd->class[i] == sd->coord->max + 1) { | 259 | if (sd->class[i] == sd->coord->max + 1) { |
| 260 | |||
| 261 | /* | ||
| 262 | * TODO: this is the only unavoidable use of | ||
| 263 | * antindexes. I also use them in genptable() (see | ||
| 264 | * pruning.c), but there I can do without (see | ||
| 265 | * commented functions in that file. | ||
| 266 | * Removing this would allow for a great simplification | ||
| 267 | */ | ||
| 260 | c = sd->coord->cube(i); | 268 | c = sd->coord->cube(i); |
| 269 | |||
| 261 | sd->rep[nreps] = c; | 270 | sd->rep[nreps] = c; |
| 262 | for (j = 0; j < sd->ntrans; j++) { | 271 | for (j = 0; j < sd->ntrans; j++) { |
| 263 | d = apply_trans(sd->trans[j], c); | 272 | d = apply_trans(sd->trans[j], c); |
