File size: 4,547 Bytes
d594310 b745e8c d594310 65c605b d594310 c1dc3b9 7f41a3c c1dc3b9 d594310 c1dc3b9 d594310 62fd5e6 d594310 65c605b d594310 62fd5e6 d594310 7f41a3c d594310 b745e8c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | ---
license: mit
library_name: pytorch
tags:
- rubiks-cube
- search
- value-iteration
- reinforcement-learning
pipeline_tag: other
---
# tiny-cube-solver
A 33.6M-parameter network that guesses how many moves a Rubik's Cube is from
solved, plus a search that uses the guess to find the moves. It was trained from
nothing: no solver, no example solutions, no human data.
- Solves **95%** of fully scrambled cubes (142 of 150, scrambles of 20 to 100 moves)
- Solves **every** cube scrambled with 10 moves or fewer
- Built as a control for [RubiksBench](https://brianbriscoe.dev/lab/rubiksbench),
where language models must write the whole answer in one reply. On the same
full scrambles the best of them, GPT-6 Astra, solves 9 of 10 with answers
averaging over 100 moves; this model's answers average about 22. It is not the
same test: this model gets a search loop, the language models get one reply.
Write-up and replays: https://brianbriscoe.dev/lab/tiny-cube-solver
## Try it
```sh
pip install torch transformers safetensors huggingface_hub
python solve.py --scramble "R U F' D2 L B'"
```
or with a cube state in the `kociemba` layout (faces U R F D L B, nine stickers
each):
```sh
python solve.py --facelets <54 characters>
```
Use `--beam 1024` for full scrambles, which needs a GPU. The default, 64, is
fast enough for a laptop, but it only solves short scrambles.
`solve.py` has no other dependencies. It downloads `config.json` and
`model.safetensors` from this repo the first time.
## How it works
The network does not write moves. It reads the 54 stickers of one cube and
returns one number: its guess of the distance to solved.
`solve.py` then searches:
1. Apply each of the 18 moves to every position it is keeping.
2. Ask the network to score all the new positions.
3. Keep the best `--beam` of them, and repeat.
4. Stop when one of them is the solved cube.
Every move is applied by ordinary code, and the answer is checked before it is
printed. The network only decides which positions are worth keeping.
### Training: the model makes its own answers
The model was trained by approximate value iteration (the method behind
[DeepCubeA](https://www.nature.com/articles/s42256-019-0070-z)). It starts from
one free fact: the solved cube is 0 moves from solved. A cube is then 1 more
than its best neighbour. The network learns from its own previous guesses, and
the correct answers spread outward from the solved cube, one move further each
round. No solver is involved at any point.
An earlier version with the identical network was trained on distances from the
Kociemba solver instead. It solved only 16% of full scrambles. Kociemba returns
good solutions, not the shortest, and 47% of random cubes got the label "21", so
there was nothing to learn from above distance 15. Changing only the labels took
full scrambles from 16% to 96%.
## Results
Canonical RubiksBench scrambles (the same cubes every language model on the
board is tested on), 25 cubes per scramble length:
| Scramble length | Solved (beam 1024) | Average answer |
|---|---|---|
| 3 | 25/25 | 3.0 moves |
| 6 | 25/25 | 6.0 |
| 10 | 25/25 | 10.0 |
| 15 | 25/25 | 20.4 |
| 20 | 24/25 | 22.0 |
| 25 | 24/25 | 21.9 |
| 30 | 25/25 | 21.6 |
| 40 | 23/25 | 23.0 |
| 50 | 23/25 | 21.9 |
| 100 | 23/25 | 21.5 |
| **all** | **242/250 (96.8%)** | |
Measured 2026-09-24 on one RTX A6000. Every cube and answer is replayable at
https://brianbriscoe.dev/lab/tiny-cube-solver.
Past about 15 moves, every scramble is fully mixed, so 25, 50 or 100 moves are
no harder than 20. A full scramble takes about 80 to 90 seconds on one RTX A6000.
## Model
- A Llama-shaped encoder, trained from scratch: 8 layers, width 512, 8 heads.
The architecture only; no Llama weights.
- Input: `[BOS]` + 54 sticker tokens + `[SEP]`. Output: the mean of the final
layer, through one linear layer, to one number.
- 33,577,985 parameters, float32.
## Things that give much lower numbers
| What you did | What you get at 20 moves |
|---|---|
| Always take the best-scored move, no search | 34% even at 10 moves |
| Judge the network by its average error | about 1.5 moves, which looks poor; the search only needs the correct ranking of the 18 neighbours |
## Limits
- It is not fast. The Kociemba two-phase solver solves any cube in milliseconds.
This model exists to show that a small network can learn the task at all.
- Solutions are not guaranteed to be shortest. Full scrambles average about 22
moves.
- 3x3x3 only.
## License
MIT. See `LICENSE`.
|