Skip to content

M21: Thistlethwaite solver — four-phase group reduction with staged playback#22

Merged
cypherair merged 1 commit into
mainfrom
m21-thistlethwaite
Jun 12, 2026
Merged

M21: Thistlethwaite solver — four-phase group reduction with staged playback#22
cypherair merged 1 commit into
mainfrom
m21-thistlethwaite

Conversation

@cypherair

Copy link
Copy Markdown
Owner

What

Adds Thistlethwaite as a fourth solving method: the classic 1981 four-phase group reduction G0 ⊃ G1 ⊃ G2 ⊃ G3 ⊃ solved. Each phase restricts the move set further and is solved provably shortest for its goal by greedy descent over an exact BFS distance table. Typical solutions run ~30–45 moves with four named stages in playback ("Orient edges", "Orient corners + slice", "Separate pieces", "Half-turn finish").

Design

Phase coordinates and tables (~5 MB total, thistlethwaite-tables.bin):

Phase Goal Coordinate Size Moves Max
1 orient all edges edge flip 2,048 all 18 7
2 orient corners, E-slice home twist × slice 2187 × 495 U* D* L* R* F2 B2 10
3 into the square group corner perm × M-separation 40320 × C(8,4) U* D* R2 L2 F2 B2 13
4 solved corner-96 × within-slice perms 96 × 24³ half turns 15
  • Phase 3's goal is seeded as a multi-source BFS over the whole goal coset (every half-turn-reachable corner permutation with the M edges home) instead of hand-deriving Thistlethwaite's tetrad-twist condition. That characterization is exact: legality ties edge parity to corner parity, and 96 × 6912 matches the square group's order.
  • Phase 4 covers exactly half its index space (half turns are even permutations); the table keeps -1 for the unreachable parity class.
  • Greedy descent can't stall: every phase move set is closed under inverses, so the move graph is undirected and a BFS parent edge always leads from distance d to d−1 — and any such move lies on a shortest path.
  • The test suite pins the known per-phase maxima 7/10/13/15 (total worst case 45), which doubles as a convention anchor for all four coordinates.

Shared refactors:

  • StagedSolution is now StagedSolution<StageKind: SolverStage> — Thistlethwaite and the upcoming CFOP solver reuse the beginner solver's staged-playback pipeline. BeginnerSolverTests needed zero changes.
  • TableBuilder extracts the move-table/BFS builders from SolverTables (multi-source starts, optional coverage assert, parameterized move lists). Pure refactor: regenerated kociemba-tables.bin verified byte-identical (sha256 c54577ac… before and after).
  • Settings hardening: the snapshot now stores the solving method as a raw string, so a settings file written by a newer build (with methods this build doesn't know) degrades to Fast instead of throwing inside try? and silently resetting every setting.

App integration: new method row (auto-populated), lazy table build on the first Thistlethwaite solve (~1 s release, cached in Application Support), stage chips and solve flow identical to the beginner method.

Verification

  • swift test -c release: 76 tests pass (6 new: 200-state sweep with per-phase invariants + per-phase move-set checks against an independently constructed square-group closure, table depth pins, cache round-trip, solved/illegal edge cases).
  • Kociemba regression: anchor suite green, regenerated table file byte-identical.
  • macOS + iOS Simulator builds green.
  • Interactive (macOS app): Settings › Solving shows the new method; scramble → solve produced a 29-move staged solution, played through all four stage chips to "Solved!"; second solve used the cached tables instantly.

🤖 Generated with Claude Code

- StagedSolution is now generic over the stage kind (SolverStage
  protocol); BeginnerSolver returns StagedSolution<BeginnerStage>
- TableBuilder: shared move-table/BFS builders extracted from
  SolverTables (multi-source starts, optional coverage check,
  parameterized move lists); Kociemba table bytes verified identical
- ThistlethwaiteTables: four exact BFS distance tables (~5 MB,
  thistlethwaite-tables.bin); phase-3 goal seeded as a multi-source
  BFS over the half-turn coset instead of a hand-derived tetrad-twist
  condition; phase 4 covers exactly half its space by parity
- ThistlethwaiteSolver: greedy descent per phase, each provably
  shortest; tests pin the known maxima 7/10/13/15 and sweep 200
  seeded states with per-phase invariants and move-set checks
- App: Thistlethwaite method row, lazy table build on first solve,
  staged chips reuse the beginner pipeline; settings snapshot now
  tolerates unknown solving-method values instead of resetting

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cypherair cypherair merged commit 54b5518 into main Jun 12, 2026
2 checks passed
@cypherair cypherair deleted the m21-thistlethwaite branch June 12, 2026 08:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant