aboutsummaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc')
-rw-r--r--doc/h48.md124
-rw-r--r--doc/solvers.md7
2 files changed, 53 insertions, 78 deletions
diff --git a/doc/h48.md b/doc/h48.md
index c601b75..0b9541a 100644
--- a/doc/h48.md
+++ b/doc/h48.md
@@ -1,9 +1,8 @@
1# The H48 optimal solver 1# The H48 optimal solver
2 2
3This document contains information on the H48 Rubik's Cube optimal solver. 3This document contains information on the H48 Rubik's Cube optimal solver.
4The implementation of the solver is still in progress. This document 4This solver is occasionally improved and optimized, and this document
5partly describes ideas that have not been implemented yet, and it will 5is updated accordingly to reflect the current implementation.
6be updated to reflect the actual implementation.
7 6
8I highly encourage the reader to check out Jaap Scherphuis' 7I highly encourage the reader to check out Jaap Scherphuis'
9[Computer Puzzling page](https://www.jaapsch.net/puzzles/compcube.htm) 8[Computer Puzzling page](https://www.jaapsch.net/puzzles/compcube.htm)
@@ -215,46 +214,40 @@ stored in a single 32 bit integer, so that the table uses less than 12MB.
215 214
216### Getting the pruning value 215### Getting the pruning value
217 216
218Once we have computed the full h0 coordinate, we can access the correct 217Once we have computed the full h0 coordinate, we can access
219entry in the full pruning table. As mentioned above, the pruning table 218the correct entry in the full pruning table. We chose to
220can be one of three kinds: 219use 2 bits per entry, as described by Rokicki in the [nxopt
220document](https://github.com/rokicki/cube20src/blob/master/nxopt.md).
221This means that every pruning table needs to have an associated *base
222value*, that determines the offset to be added to each entry (each entry
223can only be 0, 1, 2 or 3). If the base value is `b`, a pruning value
224of 1, 2 or 3 can be used directly as a lower bound of b+1, b+2 and b+3
225respectively. However, a value of 0 could mean that the actual lower
226bound is anything between 0 and b, so we cannot take b as a lower bound.
221 227
222* 4 bits per entry, or `k4`: In this case the pruning value (between 0 228To be able to still use some sort of pruning value even when we get a
223 and 15) can be simply read off the table. 2290 read, we use a **fallback table**. Inspired by nxopt, this table is
224* 2 bits per entry, or `k2`: Tables of this kind work as described by 230interleaved with the main table for cache efficiency: every 254 entries
225 Rokicki in the 231(508 bits), we store in 4 bits the minimum of the pruning values of these
226 [nxopt document](https://github.com/rokicki/cube20src/blob/master/nxopt.md). 232254 entries as a number from 0 to 16, without subtracting the table's
227 In this case the pruning table also has a *base value*, that determines 233base. Since a cache line is 512 bits long, we never get a cache miss
228 the offset to be added to each entry (each entry can only be 0, 1, 2 or 3). 234when looking up the minimum value in the fallback table after a 0 read.
229 If the base value is `b`, a pruning value of 1, 2 or 3 can be used directly 235Smaller lines (of 256 or 128 bits) have been tried, but they do not
230 as a lower bound of b+1, b+2 and b+3 respectively. However, a value of 0 236give any significant improvement over 512 bit lines.
231 could mean that the actual lower bound is anything between 0 and b, so we
232 cannot take b as a lower bound. Instead we have to use a pruning value from
233 another table - see the section "Fallback tables" below.
234* 1 bit per entry, or `k1`: With one bit per entry, the only information we
235 can get from the pruning table is wether or not the current position
236 requires more or fewer moves than a fixed base value b. This can still be
237 valuable if most positions are more or less equally split between two
238 pruning values.
239 (Work in progress - `k1` tables not available in the code yet)
240 237
241### Fallback tables 238Moreover, as an additional heuristic, in case of a 0 read we also look
239up another pruning value in a table that takes into account only the
240position of the edges. This table is small (around 1MB), so repeated
241accesses to it are not too slow. In practice, this gives a small speed up
242of around 5%. More tables could be used to refine the fallback estimate,
243but each additional table leads to longer lookup times, especially if
244it is too large to fit in cache.
242 245
243When a pruning table does not store the exact lower bound value, for 246Previous versions of this implementation (up to commit 6c42463, or
244example in the case of `k2` table as described above, we need to refine 247to version 0.2) also included the possibility of a table with 4 bits
245our estimate using another table, which we call *fallback table*. 248per entry, at least for the `h0` case. Such tables did not require
246In the current implementation, we actually use two different tables: 249a fallback lookup, but due to their large size they were not less
247 250efficient. Therefore, they have been removed.
248* **h0** table: for larger `k2` tables we get a fallback value from the full
249 table for the **h0** coordinate.
250* edges-only table: to improve the pruning value for certain specific
251 scrambles, namely whose with solved corners such as the superflip,
252 we employ a second table that takes into account the edges of a full
253 **h11** coordinate. This table is small (around 1MB).
254
255More tables could be used to refine the fallback estimate, but each
256additional table leads to longer lookup times, especially if it is
257too large to fit in cache.
258 251
259### Estimation refinements 252### Estimation refinements
260 253
@@ -368,20 +361,20 @@ they are obviously inexistent when looking for *all* optimal solutions.
368 361
369## Pruning table computation 362## Pruning table computation
370 363
371### 4 bits tables for h0 and h11 364We first describe how the pruning table would be computed if we stored
365each pruning value fully, using 4 bits per entry. This algorithm used
366to be implemented (up to commit 6c42463), but has since been removed.
372 367
373Computing the pruning table for a "real" h48 coordinate, that **h0** 368### Full tables for h0 and h11 (not implemented)
374or **h11**, using 4 bits per entry is quite simple. The method currently
375implemented works as follows.
376 369
377First, we set the value of the solved cube's coordinate to 0 and every 370If we are allowed to store the full pruning value for each entry,
378other entry to 15, the largest 4-bit integer. Then we iteratively scan 371computing the pruning tables is not that difficult. First, we set the
379through the table and compute the coordinates at depth n+1 from those at 372value of the solved cube's coordinate to 0 and every other entry to 15,
380depth n as follows: for each coordinate at depth n, we compute a valid 373the largest 4-bit integer. Then we iteratively scan through the table and
381representative for it, we apply each of the possible 18 moves to it, and 374compute the coordinates at depth n+1 from those at depth n as follows:
382we set their value to n+1. Once the table is filled or we have reached 375for each coordinate at depth n, we compute a valid representative for it,
383depth 15, we stop (there are no **h0** coordinates at depth 16 or more, 376we apply each of the possible 18 moves to it, and we set their value to
384but I currently don't know if this is the case for **h11**). 377n+1. Once the table is filled or we have reached depth 15, we stop.
385 378
386Unfortunately what I described above is an oversimplification: one 379Unfortunately what I described above is an oversimplification: one
387also must take into account the case where the corner coordinate is 380also must take into account the case where the corner coordinate is
@@ -400,20 +393,7 @@ Finally, this algorithm can be easily parallelized by dividing the set
400of coordinates into separate sections, but one must take into account 393of coordinates into separate sections, but one must take into account
401that a coordinate and its neighbors are usually not in the same section. 394that a coordinate and its neighbors are usually not in the same section.
402 395
403This method is currently implemented only for **h0**, since the 4 bits 396### 2 bit tables
404table for **h11** would require around 115GB of RAM to compute, and I
405don't have this much memory.
406
407### 2 bits tables with for h0 and h11
408
409(Work in progress - currently there is no specialized routine for
410computing 2 bits table for "real" coordinates; instead, an optimized
411version of the generic method explained below is used)
412
413### A generic method for intermediate coordinates (from h1 to h10)
414
415(Work in progress - this method is quite slow and it may be replaced
416by a better algorithm in the future)
417 397
418Computing the pruning tables for intermediate coordinates is not as 398Computing the pruning tables for intermediate coordinates is not as
419simple. The reason is that these coordinates are not invariant under 399simple. The reason is that these coordinates are not invariant under
@@ -441,14 +421,13 @@ map indexed by their **h11** coordinate value. This way we do not have
441to brute-force our way through from depth 0, and it make this method 421to brute-force our way through from depth 0, and it make this method
442considerably faster. Unfortunately, since the number of coordinates 422considerably faster. Unfortunately, since the number of coordinates
443at a certain depth increases exponentially with the depth, we are for 423at a certain depth increases exponentially with the depth, we are for
444now limited at storing the coordinates at depth 8. (Work in progress - 424now limited at storing the coordinates at depth 8.
445we may experiment with depth 9 in the future)
446 425
447This method works for the "real" coordinates **h0** and **h11** as well. 426This method works for the "real" coordinates **h0** and **h11** as well.
448Moreover, in this case one can optimize it further by avoiding to repeat 427Moreover, in this case one can optimize it further by avoiding to repeat
449the search from a coordinate that has already been visited. (Work 428the search from a coordinate that has already been visited. Further
450in progress - this method will be replaced in the future by a more 429optimization are possible for **h0** and **h11**, and we may implement
451efficient one) 430them in the future.
452 431
453## Possible future improvements 432## Possible future improvements
454 433
@@ -458,9 +437,6 @@ notes rather than a description of the solver.*
458There are some areas where this implementation of the H48 optimal solver 437There are some areas where this implementation of the H48 optimal solver
459can be improved: 438can be improved:
460 439
461* Intertwining fallback tables to the main table. This is a trick that
462 nxopt uses to reduce the number of cache misses, but we have not
463 implemented in H48 yet.
464* Faster pruning table generation for **h11** and **h0**. Since these 440* Faster pruning table generation for **h11** and **h0**. Since these
465 two coordinates are "real" coordinates, we can use a different technique 441 two coordinates are "real" coordinates, we can use a different technique
466 to generate their tables faster. This won't affect the solver speed. 442 to generate their tables faster. This won't affect the solver speed.
diff --git a/doc/solvers.md b/doc/solvers.md
index e90a40b..a246c54 100644
--- a/doc/solvers.md
+++ b/doc/solvers.md
@@ -10,12 +10,11 @@ An HTM-optimal solver using fully-symmetric pruning tables. For details
10about how this solver works, see [h48.md](./h48.md). For benchmarks see 10about how this solver works, see [h48.md](./h48.md). For benchmarks see
11[benchmarks/benchmarks.md](../benchmarks/benchmarks.md). 11[benchmarks/benchmarks.md](../benchmarks/benchmarks.md).
12 12
13* Name: of the form `h8hXk2` for `X` from 0 to 11, or `h48h0k4`. The name 13* Name: of the form `h8hX` for `X` from 0 to 11. The name `optimal` is
14 `optimal` is an alias for `h48h7k2`. 14 an alias for `h48h7`.
15* Requisites: none. 15* Requisites: none.
16* Moveset: HTM (all 18 basic moves). 16* Moveset: HTM (all 18 basic moves).
17* Data size: 59MB for `h48h0k4`, from 115MB to 59GB for `h48hXk2` 17* From 115MB to 59GB (roughly 2<sup>X</sup>*56MB).
18 (roughly 59MB + 2<sup>X</sup>*56MB).
19 18
20## Coordinate solvers 19## Coordinate solvers
21 20

Generated with cgit - Back to sebastiano.tronto.net